r""" Dental claims run every applicable condition (operator, 2026-10-07 and 2026-10-12): every "All payers" condition plus the claim's own payer's — the same rule as UB/HCFA. Spec: docs/superpowers/specs/2026-10-07-dental-claims-run-all-conditions-design.md python tests\test_dental_conditions.py Uses tests/fixtures/dental_claim.html: D0120 (row 0, checked, 45.00) and DCONS (row 1, checked, 30.00), ICD 1 = Z01.20, payer DentaQuest. """ import sys import pathlib import inspect ROOT = pathlib.Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "src")) FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "dental_claim.html" from ecw_bot.pages import claim_form # noqa: E402 from ecw_bot.selectors import claim_form as sel # noqa: E402 from ecw_bot.conditions import (dummy_codes, telehealth, # noqa: E402 medicare_telehealth, vaccine_admin_codes, bh_h_code_modifier, j2930_j2001_update) from ecw_bot.conditions.base import run_all # noqa: E402 CASES = [] def case(fn): CASES.append(fn) return fn def _add_row(page, code, fee="40.00", checked=True, icd1="1"): """One more real service line, cloned from row 0.""" page.evaluate( """(a) => { const rows = document.querySelectorAll( 'tr[ng-repeat^="CPT in CPTCodes"]'); const tr = rows[0].cloneNode(true); tr.querySelector('[data-fieldname="web_cptcode"]').value = a.code; tr.querySelector('[data-fieldname="web_billedFee"]').value = a.fee; tr.querySelector('[data-fieldname="web_icd1"]').value = a.icd1; const box = tr.querySelector('[ng-click*="updateBillToIns("]'); box.checked = a.checked; rows[rows.length - 1].after(tr); }""", {"code": code, "fee": fee, "checked": checked, "icd1": icd1}) def _row(page, index): tr = page.locator(sel.SEL_CPT_ROWS).nth(index) return (tr.locator(sel.SEL_CPT_CODE).first.input_value(), tr.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked(), tr.locator(sel.SEL_CPT_BILLED_FEE).first.input_value()) # ── reading the Dental screen ──────────────────────────────────────────────── @case def extract_reads_the_dental_grid_in_the_ub_row_shape(page): page.goto(FIXTURE.as_uri()) data = claim_form.extract(page) assert data["screen"] == "dental", data.get("screen") assert data["claim_no"] == "5000000", data["claim_no"] cpt = data["cpt"] assert [r["code"] for r in cpt] == ["D0120", "DCONS"], cpt row = cpt[1] assert row["billed"] is True and row["billed_fee"] == "30.00", row assert row["icd1"] == "1" and row["units"] == "1", row assert row["sdos"] == "09/01/2026", row assert row["mod1"] == "" and row["pos"] == "", "no such columns" assert data["insurance"][0]["Name"] == "DentaQuest", data["insurance"] assert data["icd"] == [{"#": "1", "Code": "Z01.20", "Name": "Encounter for dental exam"}], data["icd"] assert data["notes"] == "Routine visit.", data["notes"] @case def extract_on_ub_and_hcfa_says_which_screen(page): page.goto(FIXTURE.with_name("ub_claim.html").as_uri()) assert claim_form.extract(page)["screen"] == "ub" page.goto(FIXTURE.with_name("hcfa_claim.html").as_uri()) assert claim_form.extract(page)["screen"] == "hcfa" @case def a_hidden_dental_form_is_never_read(page): """eCW leaves closed forms in the DOM; only the one on screen counts.""" page.goto(FIXTURE.as_uri()) page.evaluate("""() => document.getElementById('dentalClaim7777777777777') .style.display = 'none'""") data = claim_form.extract(page) assert data["screen"] != "dental" and data["cpt"] == [], data # ── the row helpers work on the Dental grid ────────────────────────────────── @case def dcons_is_unchecked_and_zeroed_on_the_dental_screen(page): page.goto(FIXTURE.as_uri()) data = claim_form.extract(page) data["insurance"] = [{"Name": "DentaQuest"}] assert dummy_codes.detect("C1", data) is True result = dummy_codes.apply(page, "C1", data) assert result.changed is True, result assert result.changes == [{"row": 1, "code": "DCONS", "unchecked": True, "fee": {"before": "30.00", "after": "0.00"}}], result.changes assert _row(page, 1) == ("DCONS", False, "0.00") assert _row(page, 0) == ("D0120", True, "45.00"), "D0120 untouched" @case def j2001_is_unchecked_and_zeroed_on_the_dental_screen(page): page.goto(FIXTURE.as_uri()) _add_row(page, "J2001", fee="12.00") data = claim_form.extract(page) result = j2930_j2001_update.apply(page, "C1", data) assert result.changed is True, result assert _row(page, 2) == ("J2001", False, "0.00") # ── run_all on a Dental claim ──────────────────────────────────────────────── def _dental_data(page, payer="DentaQuest", note="Routine dental visit."): data = claim_form.extract(page) data["insurance"] = [{"Name": payer}] data["progress_notes"] = {"opened": "tab", "text": note} return data @case def run_all_on_a_dental_claim_runs_the_all_payer_conditions(page): page.goto(FIXTURE.as_uri()) _add_row(page, "J2001", fee="12.00") _add_row(page, "D1110", fee="0.00") report = {} results = run_all(page, "C1", _dental_data(page), report=report) names = [r.condition_name for r in results] for name in ("dummy_codes", "j2930_j2001_update", "zero_fee_uncheck"): assert name in names, (name, names, report) assert report["failed"] == [] and report["review"] == [], report assert _row(page, 1)[1:] == (False, "0.00") assert _row(page, 2)[1:] == (False, "0.00") assert _row(page, 3)[1] is False, "zero-fee line unchecked" assert _row(page, 0) == ("D0120", True, "45.00") @case def a_fix_the_dental_screen_cannot_make_goes_to_review(page): """ Operator, 2026-10-12: the Dental grid has no POS and no modifier columns, so telehealth's POS 2 + modifier cannot be written — the claim is Review with the reason, never a silent skip. """ page.goto(FIXTURE.as_uri()) data = _dental_data(page, note="Session Setting (PoS): TeleHealth. " "Audio and video telehealth visit.") report = {} run_all(page, "C1", data, report=report) reasons = {r["name"]: r["reason"] for r in report["review"]} assert "telehealth" in reasons, report assert "Dental" in reasons["telehealth"], reasons assert "telehealth" not in report["changed"], report @case def depression_pointer_is_retagged_on_the_dental_icd_fields(page): """#6 on web_icd1-4: Z13.31 only on G8510, taken off D0120.""" page.goto(FIXTURE.as_uri()) page.evaluate("""() => { const body = document.querySelector('#addTable tbody'); const tr = body.rows[0].cloneNode(true); tr.cells[0].textContent = '2'; tr.cells[1].querySelector('input').value = 'Z13.31'; tr.cells[2].textContent = 'Encounter for screening for depression'; body.rows[0].after(tr); document.querySelector('[data-fieldname="web_icd2"]').value = '2'; }""") _add_row(page, "G8510", fee="0.00", icd1="1") report = {} run_all(page, "C1", _dental_data(page), report=report) assert "depression_dx_pointer" in report["changed"], report icd = lambda i, n: page.locator(sel.SEL_CPT_ROWS).nth(i).locator( sel.SEL_CPT_ICD[n]).first.input_value() assert [icd(0, n) for n in range(4)] == ["1", "", "", ""], \ "Z13.31 (pointer 2) taken off D0120" assert icd(2, 0) == "2", "G8510 carries Z13.31" @case def every_condition_that_needs_pos_modifiers_or_new_lines_declares_it(): for module in (telehealth, medicare_telehealth, vaccine_admin_codes): reason = getattr(module, "DENTAL_UNSUPPORTED", "") assert reason and "Dental" in reason, module.NAME @case def bh_h_code_modifier_path_is_review_on_dental_but_non_bh_unchecks(page): page.goto(FIXTURE.as_uri()) _add_row(page, "H0023", fee="50.00") report = {} run_all(page, "C1", _dental_data(page, payer="APM2 Medicaid"), report=report) assert "bh_h_code_modifier" in report["changed"], report assert _row(page, 2)[1:] == (False, "0.00") # A BH payer's H code with a modifier: the Dental grid has no modifier # column, so there is nothing to read and nothing fires. page.goto(FIXTURE.as_uri()) _add_row(page, "H0023", fee="50.00") report = {} run_all(page, "C1", _dental_data(page, payer="BH COLORADO ACCESS"), report=report) assert "bh_h_code_modifier" not in report["fired"], report assert _row(page, 2)[1:] == (True, "50.00") def main() -> int: if not FIXTURE.exists(): print(f" FAIL fixture missing: {FIXTURE}") return 1 from playwright.sync_api import sync_playwright failures = 0 with sync_playwright() as pw: browser = pw.chromium.launch(headless=True) page = browser.new_page() for fn in CASES: name = fn.__name__.replace("_", " ") try: if len(inspect.signature(fn).parameters) == 0: fn() else: fn(page) print(f" ok {name}") except AssertionError as exc: print(f" FAIL {name}: {exc}") failures += 1 except Exception as exc: print(f" ERROR {name}: {type(exc).__name__}: {exc}") failures += 1 browser.close() print(f"\n{len(CASES) - failures}/{len(CASES)} passed") return 1 if failures else 0 if __name__ == "__main__": sys.exit(main())