"""Tests for the CMS-10114 NPI Application/Update filler (Standard no-login path). Verifies the overlay-based filler: - selects the correct Reason-for-Submittal checkbox per reason/slug - places the NPI on the correct line for each reason - writes the provider name into Section 2A and the Section 4A certification - produces a signature anchor on the certification page - surfaces the right "manual completion" notes - mails to the verified Baltimore NPI Enumerator address (via mac_routing) Run: python scripts/tests/test_cms10114.py """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "scripts")) import importlib.util # noqa: E402 import pdfplumber # noqa: E402 from workers import mac_routing as mr # noqa: E402 def _load_module(name, rel_path): spec = importlib.util.spec_from_file_location(name, ROOT / rel_path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod # Load the filler directly to avoid document_gen/__init__ side-effects (python-docx). f = _load_module("cms10114_pdf_filler", "scripts/document_gen/templates/cms10114_pdf_filler.py") H = 792.0 _fails = 0 def check(name, cond): global _fails status = "PASS" if cond else "FAIL" if not cond: _fails += 1 print(f" {status} {name}") def _tokens(pdf_bytes, page_index): import io pdf = pdfplumber.open(io.BytesIO(pdf_bytes)) page = pdf.pages[page_index] return {w["text"]: (w["x0"], H - w["bottom"]) for w in page.extract_words()} SAMPLE = { "provider_name": "Jane Q Smith", "npi": "1234567893", "practice_state": "CA", "enumeration_type": "NPI-1", } def main(): print("reason normalization") check("slug nppes-update -> change", f.normalize_reason("nppes-update") == "change") check("slug npi-reactivation -> reactivation", f.normalize_reason("npi-reactivation") == "reactivation") check("explicit 'deactivation' kept", f.normalize_reason("deactivation") == "deactivation") check("unknown -> change (safe default)", f.normalize_reason("zzz") == "change") print("checkbox + NPI placement per reason (page 2)") # Expected checkbox X positions (lower-left) per reason, from the form layout. expect = { "change": {"X": (48, 582), "NPI": (132, 570)}, "reactivation": {"X": (325, 506), "NPI": (408, 529)}, "deactivation": {"X": (325, 608), "NPI": (408, 599)}, } for reason, exp in expect.items(): pdf, anchors, missing = f.fill_cms10114(SAMPLE, reason=reason) toks = _tokens(pdf, f.PAGE_BASIC) x = toks.get("X") npi = toks.get("1234567893") check(f"{reason}: X near {exp['X']}", x and abs(x[0] - exp["X"][0]) < 6 and abs(x[1] - exp["X"][1]) < 6) check(f"{reason}: NPI near {exp['NPI']}", npi and abs(npi[0] - exp["NPI"][0]) < 6 and abs(npi[1] - exp["NPI"][1]) < 6) print("identity + certification name (Section 2A / 4A)") pdf, anchors, missing = f.fill_cms10114(SAMPLE, reason="change") p2 = _tokens(pdf, f.PAGE_BASIC) p4 = _tokens(pdf, f.PAGE_CERT) check("Section 2A first name placed", "Jane" in p2) check("Section 2A last name placed", "Smith" in p2) check("Section 4A cert first name placed", "Jane" in p4) check("Section 4A cert last name placed", "Smith" in p4) print("signature anchor") check("exactly one signature anchor", len(anchors) == 1) check("anchor on certification page", anchors and anchors[0]["page"] == f.PAGE_CERT) check("anchor field is 'signer'", anchors and anchors[0]["field"] == "signer") print("manual-completion notes") _, _, m_change = f.fill_cms10114(SAMPLE, reason="change") _, _, m_react = f.fill_cms10114(SAMPLE, reason="reactivation") _, _, m_deact = f.fill_cms10114(SAMPLE, reason="deactivation") check("change asks to mark changing fields", any("changing" in x.lower() for x in m_change)) check("reactivation asks for reason text", any("reactivation reason" in x.lower() for x in m_react)) check("deactivation asks for reason box", any("deactivation reason" in x.lower() for x in m_deact)) _, _, m_noni = f.fill_cms10114({"provider_name": "No NPI"}, reason="change") check("missing NPI flagged", any("npi is required" in x.lower() for x in m_noni)) _, _, m_org = f.fill_cms10114({**SAMPLE, "enumeration_type": "NPI-2"}, reason="change") check("org (NPI-2) flagged for 4B path", any("organization" in x.lower() for x in m_org)) print("routing destination = verified Baltimore Enumerator") addr = " ".join(mr.NPI_ENUMERATOR.address_lines).lower() check("destination is Baltimore (not Fargo)", "baltimore" in addr and "fargo" not in addr) check("destination has the Mail Stop", "do-01-51" in addr) print() if _fails: print(f"FAILED: {_fails} checks") sys.exit(1) print("all CMS-10114 checks passed") if __name__ == "__main__": main()