r""" conditions/medicare_vaccine_a6.py — document #19: a Medicare claim billing G0008 or G0009 carries condition code A6 (operator, 2026-10-16: those two codes only, not #18's vaccine list; the bot does not add G0008 / G0009). python tests\test_conditions_medicare_vaccine_a6.py Uses tests/fixtures/ub_claim.html — its Condition Codes boxes (FL 18-28) are uBClaimCondtnCode1..11 as on the real form, set per case with setConditionCodes. """ import io import sys import pathlib import inspect import contextlib ROOT = pathlib.Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "src")) FIXTURE = pathlib.Path(__file__).resolve().parent / "fixtures" / "ub_claim.html" HCFA_FIXTURE = (pathlib.Path(__file__).resolve().parent / "fixtures" / "hcfa_claim.html") from ecw_bot.conditions import medicare_vaccine_a6 as cond # noqa: E402 from ecw_bot.conditions import CONDITIONS # noqa: E402 from ecw_bot.conditions.base import (CPT_TAB_NOT_CONFIRMED, # noqa: E402 ConditionResult, run_all) from ecw_bot.core import charge_summary as cs # noqa: E402 from ecw_bot.pages import claim_form # noqa: E402 CASES = [] def case(fn): CASES.append(fn) return fn def _quiet(fn, *a, **k): with contextlib.redirect_stdout(io.StringIO()) as out: result = fn(*a, **k) return result, out.getvalue() MEDICARE = "HCFA Medicare" def _row(code, billed=True, fee="40.00"): return {"code": code, "billed": billed, "billed_fee": fee, "units": "1"} def _data(cpt, payer=MEDICARE, screen="ub", codes=None): return {"screen": screen, "insurance": [{"Name": payer}] if payer is not None else [], "cpt": cpt, "condition_codes": ([""] * 11 if codes is None else codes) if screen == "ub" else None} # ── detect / needs_review (no browser) ─────────────────────────────────────── @case def g0008_or_g0009_on_medicare_without_a6_fires(): for code in ("G0008", "G0009", " g0009 "): assert cond.detect("C1", _data([_row("99213"), _row(code)])), code @case def a6_already_there_does_not_fire(): codes = ["", "", "a6"] + [""] * 8 data = _data([_row("G0008")], codes=codes) assert cond.detect("C1", data) is False assert cond.needs_review("C1", data) is None @case def not_medicare_or_no_trigger_does_not_fire(): for data in (_data([_row("G0008")], payer="BH COLORADO ACCESS"), _data([_row("G0008")], payer=""), _data([_row("90656"), _row("90732"), _row("G0010")]), _data([_row("G0008", billed=False, fee="0.00")]), _data([_row("G0009", fee="0.00")]), _data([_row("G0009", billed=None, fee="0.00")])): assert cond.detect("C1", data) is False, data assert cond.needs_review("C1", data) is None, data @case def an_unchecked_priced_trigger_counts_priced_line_check_checks_it(): """Review, 2026-10-19: priced_line_check, last, checks an unchecked G0008 with a fee — so it is billed, and needs A6 like a checked one.""" data = _data([_row("99213"), _row("G0008", billed=False, fee="40.00")]) assert cond.detect("C1", data) is True assert cond.billed_trigger_codes(data["cpt"]) == ["G0008"] @case def a_trigger_billed_twice_is_named_once(): data = _data([_row("G0009"), _row("G0009")], screen="hcfa") assert cond.needs_review("C1", data).startswith("G0009 on Medicare") @case def hcfa_or_dental_medicare_claim_is_review_by_hand(): for screen in ("hcfa", "dental"): data = _data([_row("G0009"), _row("G0008")], screen=screen) assert cond.detect("C1", data) is False, screen why = cond.needs_review("C1", data) assert why and "A6 by hand" in why and "G0009, G0008" in why, why @case def a_ub_read_without_condition_codes_is_review(): data = _data([_row("G0008")]) data["condition_codes"] = None assert cond.detect("C1", data) is False assert "A6 by hand" in cond.needs_review("C1", data) # ── apply (browser) ────────────────────────────────────────────────────────── def _fresh(page, codes=None): page.goto(FIXTURE.as_uri()) if codes is not None: page.evaluate("c => window.setConditionCodes(c)", codes) def _codes(page): return claim_form.extract(page)["condition_codes"] @case def extract_reads_the_eleven_boxes(page): _fresh(page, ["09", "", "40"]) assert _codes(page) == ["09", "", "40"] + [""] * 8 @case def apply_types_a6_into_the_first_empty_box(page): _fresh(page, ["09", "", "40"]) result, out = _quiet(cond.apply, page, "C1", _data([_row("G0008")])) assert result.changed is True and result.review == "", (result, out) assert _codes(page) == ["09", "A6", "40"] + [""] * 8 c = result.changes[0] assert c["box"] == 2 and c["fl"] == 19, c assert cond.summary_comment(result) == \ "Condition code A6 added (G0008 on Medicare)" assert "FL 19" in cond.describe(result) @case def a_hidden_ub_form_left_in_the_dom_is_not_read(page): """eCW leaves closed forms in the DOM: a hidden UB form must not answer for the claim on screen (review, 2026-10-19).""" _fresh(page, ["A6"]) page.evaluate("() => { document.getElementById(" "'UBClaimDiv9999999999999').style.display = 'none'; }") assert _codes(page) is None data = _data([_row("G0008")]) data["condition_codes"] = None assert "A6 by hand" in cond.needs_review("C1", data) result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0008")])) assert result.changed is False assert "Condition Codes boxes not found" in result.review, result @case def a_box_marked_invalid_is_changed_and_review(page): """Typed, but eCW's directive marks it invalid: the box IS touched, so the result is changed (the review box shows it) AND Review.""" _fresh(page) page.evaluate("() => { window.conditionCodeInvalid = true; }") result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0008")])) assert result.changed is True, result assert "marked it invalid" in result.review, result assert "add A6 by hand" in result.review assert result.changes[0]["box"] == 1 assert "NOT added" in cond.summary_comment(result) assert "read back 'A6'" in cond.describe(result) @case def a_box_whose_angular_model_did_not_take_is_review(page): """The box shows A6 but its model (what OK saves) does not hold it.""" _fresh(page) page.evaluate("""() => { window.angular = { element: () => ({ scope: () => ({ searchRecord: '' }), isolateScope: () => ({ searchRecord: '' }) }) }; }""") result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0009")])) assert result.changed is True and "model holds ''" in result.review, result @case def a_box_whose_angular_model_took_is_ok(page): _fresh(page) page.evaluate("""() => { window.angular = { element: el => ({ scope: () => ({ searchRecord: el.value }) }) }; }""") result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0009")])) assert result.changed is True and result.review == "", result @case def apply_leaves_a6_already_there(page): _fresh(page, ["09", "", "A6"]) result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0009")])) assert result == ConditionResult.none(cond.NAME), result assert _codes(page) == ["09", "", "A6"] + [""] * 8 @case def all_boxes_full_is_review_and_nothing_overwritten(page): full = [f"{n:02d}" for n in range(1, 12)] _fresh(page, full) result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0008")])) assert result.changed is False assert "all 11 Condition Code boxes are full" in result.review, result assert "add A6 by hand" in result.review assert _codes(page) == full @case def apply_declines_when_the_cpt_tab_cannot_open(page): real = claim_form.open_cpt_hcpcs_tab def raises(_page): raise RuntimeError("simulated") claim_form.open_cpt_hcpcs_tab = raises try: result, _ = _quiet(cond.apply, page, "C1", _data([_row("G0008")])) finally: claim_form.open_cpt_hcpcs_tab = real assert result == ConditionResult.declined(cond.NAME, CPT_TAB_NOT_CONFIRMED) @case def run_all_adds_a6_and_the_summary_says_so(page): _fresh(page) page.evaluate("""() => { document.getElementById('uBClaimCPTCode0').value = 'G0008'; document.querySelector('#UBClaimTbl3 [ng-bind="insurance.InsName"]') .textContent = 'HCFA Medicare'; }""") data = claim_form.extract(page) assert data["screen"] == "ub" and data["condition_codes"] == [""] * 11 data["progress_notes"] = {"opened": "modal", "text": "Office visit."} report = {} results, out = _quiet(run_all, page, "C1", data, report=report) assert "medicare_vaccine_a6" in [r.condition_name for r in results], out assert _codes(page)[0] == "A6" data["_conditions"] = {"fired": [r.condition_name for r in results], "saved": False, "failed": report["failed"], "review": report["review"], "comments": report["comments"]} outcome = cs.claim_outcome(True, data) assert "Condition code A6 added (G0008 on Medicare)" in \ outcome["Comments"], outcome @case def hcfa_claim_read_through_run_all_is_review(page): """End to end on the HCFA fixture: no Condition Codes are read there, so a Medicare claim billing G0008 is Review, nothing typed.""" page.goto(HCFA_FIXTURE.as_uri()) page.evaluate("""() => { document.getElementById('claimCPTCode0').value = 'G0008'; document.querySelectorAll('[ng-bind="insurance.InsName"]') .forEach(e => { e.textContent = 'HCFA Medicare'; }); }""") data = claim_form.extract(page) assert data["condition_codes"] is None, data["screen"] data["progress_notes"] = {"opened": "modal", "text": "Office visit."} report = {} results, out = _quiet(run_all, page, "C1", data, report=report) assert "medicare_vaccine_a6" not in [r.condition_name for r in results] reasons = " | ".join(str(r) for r in report["review"]) assert "check condition code A6 by hand" in reasons, report["review"] @case def it_is_registered_between_the_common_rule_halves(): names = [m.NAME for m in CONDITIONS] i = names.index("medicare_vaccine_a6") assert names.index("zero_fee_uncheck") < i < names.index( "priced_line_check"), names def _run_cases() -> int: 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 def main() -> int: """shot() writes into the operator's Screenshots\\ folder; not here.""" import tempfile from ecw_bot import settings as _cfg orig = _cfg.SCREENSHOTS with tempfile.TemporaryDirectory() as tmp: _cfg.SCREENSHOTS = pathlib.Path(tmp) try: return _run_cases() finally: _cfg.SCREENSHOTS = orig if __name__ == "__main__": sys.exit(main())