Files
ecw-charge-validation/tests/test_conditions_depression_dx_pointer.py
T
ManikandanandClaude Opus 5.5 ba15a574ab Initial import: eCW Charge Validation bot and results Portal
Snapshot of the working project as of 2026-10-23 (local 2d4d4fc), one
commit with no earlier history: the tracked files were de-identified
first (synthetic claim ids and patient data only; see Context.md
section 7). Credentials, run logs, screenshots, claim reports and client
workbooks are gitignored and not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:38:17 +05:30

629 lines
27 KiB
Python

r"""
conditions/depression_dx_pointer.py — document condition #6.
python tests\test_conditions_depression_dx_pointer.py
Uses hcfa_claim.html rather than ub_claim.html: the real live claim this
condition was built for (9103000) is the professional/HCFA screen, and that
fixture already carries the full scenario (a wrongly-tagged 99213, a
wrongly-tagged G8510, and an untouched J7298) — see its own comments.
test_telehealth_fix.py separately proves the underlying primitive
(`retag_cpt_icd_pointer`) against the UB form's own id scheme.
G8431 (positive depression) has no row of its own in that fixture — only
G8510 — so `_inject_g8431_row()` adds one the same way the
medicare_telehealth tests inject a G2025 row, rather than growing the
shared fixture and risking every other test's row-count assumptions
(`CPT/HCPCS (3)`, `len(cpt) == 3`, ...). G8431 shares the SAME Z13.31
pointer as G8510 — there is no separate ICD code for "positive" depression,
only for the underlying CPT/HCPCS code itself.
"""
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" / "hcfa_claim.html"
from ecw_bot.conditions import depression_dx_pointer # noqa: E402
from ecw_bot.conditions.base import ConditionResult, run_all # noqa: E402
from ecw_bot.pages import claim_form # noqa: E402
from ecw_bot.selectors import claim_form as sel # noqa: E402
CASES = []
def case(fn):
CASES.append(fn)
return fn
_ICD_WITH_DEPRESSION = [
{"#": "1", "Code": "Z30.430", "Name": "Encounter for insertion..."},
{"#": "2", "Code": "Z13.31", "Name": "Negative depression screening"},
]
def _inject_g8431_row(page, icd1="1", checked=False):
"""
hcfa_claim.html has no G8431 row of its own (only G8510) — injected the
same way the medicare_telehealth tests inject a G2025 row, rather than
growing the shared fixture and risking every other test's row-count
assumptions (`CPT/HCPCS (3)`, `len(cpt) == 3`, ...).
"""
page.evaluate(
"""(args) => {
const tbody = document.querySelector(
'#claimCPTCodesTable8888888888888 tbody');
const addRowTr = tbody.querySelector('tr:last-child');
const tr = document.createElement('tr');
tr.id = 'CPTROW_3';
tr.innerHTML =
'<td><input data-fieldname="claimCPTCode" value="G8431" readonly></td>'
+ '<td><input type="checkbox" ng-click="updateBillToIns(3)"'
+ (args.checked ? ' checked' : '') + '></td>'
+ '<td><input data-fieldname="ClaimCPTICD1" value="' + args.icd1 + '"></td>'
+ '<td><input data-fieldname="ClaimCPTICD2" value=""></td>'
+ '<td><input data-fieldname="ClaimCPTICD3" value=""></td>'
+ '<td><input data-fieldname="ClaimCPTICD4" value=""></td>';
tbody.insertBefore(tr, addRowTr);
}""", {"icd1": icd1, "checked": checked})
def _inject_duplicate_target_row(page, code, row_id="CPTROW_3",
icd1="1", checked=True, fee="75.00"):
"""
Injects a SECOND row for a code already on the fixture (G8510, at
CPTROW_2) — or for G8431 alongside `_inject_g8431_row` — to prove the
duplicate-row suppression step: whichever row is later in DOM order is
the one that should get unchecked and fee-zeroed, the first left alone.
Carries a Billed Fee field, unlike `_inject_g8431_row`, since that is
exactly what this step targets.
"""
page.evaluate(
"""(args) => {
const tbody = document.querySelector(
'#claimCPTCodesTable8888888888888 tbody');
const addRowTr = tbody.querySelector('tr:last-child');
const tr = document.createElement('tr');
tr.id = args.rowId;
tr.innerHTML =
'<td><input data-fieldname="claimCPTCode" value="' + args.code + '" readonly></td>'
+ '<td><input type="checkbox" ng-click="updateBillToIns(3)"'
+ (args.checked ? ' checked' : '') + '></td>'
+ '<td><input data-fieldname="ClaimCPTICD1" value="' + args.icd1 + '"></td>'
+ '<td><input data-fieldname="ClaimCPTICD2" value=""></td>'
+ '<td><input data-fieldname="ClaimCPTICD3" value=""></td>'
+ '<td><input data-fieldname="ClaimCPTICD4" value=""></td>'
+ '<td><input data-fieldname="ClaimCPTBilledFee" value="' + args.fee + '"></td>';
tbody.insertBefore(tr, addRowTr);
}""", {"code": code, "rowId": row_id, "icd1": icd1,
"checked": checked, "fee": fee})
def _make_claim_already_correct(page):
"""
Puts the fixture into the state live claim 9131000 was already in
before the bot touched it: the first G8510 (CPTROW_2) checked and
carrying nothing but the Z13.31 pointer ("2"), and 99213 no longer
carrying it — so the retag and check steps have nothing left to do on
the fixture's own rows, and anything reported comes from whatever a
test injects on top.
"""
page.evaluate(
"""() => {
const set = (rowId, field, value) => {
document.querySelector(
'#' + rowId + ' [data-fieldname="' + field + '"]').value = value;
};
set('CPTROW_0', 'ClaimCPTICD2', '3');
set('CPTROW_0', 'ClaimCPTICD3', '');
set('CPTROW_2', 'ClaimCPTICD1', '2');
document.querySelector(
'#CPTROW_2 [ng-click*="updateBillToIns("]').checked = true;
}""")
def _count_checkbox_clicks(page, row_id):
"""
Counts clicks on one row's "Assign To Patient" checkbox, read back as
`window.clicksOn[row_id]`. On the live screen that click is what fires
eCW's own `updateBillToIns()`, so a row that must stay excluded should
never receive one at all — not merely end up unchecked again.
"""
page.evaluate(
"""(rowId) => {
window.clicksOn = window.clicksOn || {};
window.clicksOn[rowId] = 0;
document.querySelector('#' + rowId + ' [ng-click*="updateBillToIns("]')
.addEventListener('click', () => { window.clicksOn[rowId] += 1; });
}""", row_id)
@case
def detect_true_when_z13_31_is_on_the_claim():
data = {"icd": _ICD_WITH_DEPRESSION}
assert depression_dx_pointer.detect("C1", data) is True
@case
def detect_false_when_z13_31_is_absent():
data = {"icd": [{"#": "1", "Code": "Z30.430", "Name": "..."}]}
assert depression_dx_pointer.detect("C1", data) is False
@case
def detect_false_with_no_icd_key_at_all():
assert depression_dx_pointer.detect("C1", {}) is False
@case
def apply_retags_g8510_and_strips_99213_on_the_real_claim_shape(page):
"""
The full real scenario (claim 9103000): the ICD-pointer fix on 99213
and G8510, PLUS the separately-reported bug — G8510's checkbox sat
unchecked and needed checking once its pointer was corrected. Three
changes total: two ICD-pointer edits and one checkbox check, both
against G8510's own row.
"""
page.goto(FIXTURE.as_uri())
data = {"icd": _ICD_WITH_DEPRESSION}
result = depression_dx_pointer.apply(page, "9103000", data)
assert isinstance(result, ConditionResult)
assert result.condition_name == "depression_dx_pointer"
assert result.changed is True
assert len(result.changes) == 3, result.changes
icd_changes = [c for c in result.changes if "before" in c]
checkbox_changes = [c for c in result.changes if "before" not in c]
by_code = {c["code"]: c for c in icd_changes}
assert set(by_code) == {"99213", "G8510"}, icd_changes
assert by_code["G8510"]["after"]["icd"] == ["2", "", "", ""]
assert by_code["99213"]["after"]["icd"] == ["1", "3", "", ""]
assert checkbox_changes == [{"row": 2, "code": "G8510"}], checkbox_changes
@case
def apply_retags_g8431_with_the_same_z13_31_pointer_as_g8510(page):
"""
G8510 (negative depression) and G8431 (positive depression) are
different CPT codes but share the SAME one ICD pointer, Z13.31 — there
is no separate "positive depression" ICD code (an earlier attempt to
use Z13.32 for this was the client's own uncertain guess and has been
reverted; only Z13.31 was ever actually given). Both rows end up
carrying pointer "2", and 99213 keeps carrying nothing but its own
diagnosis once the pointer is retagged onto both target rows.
"""
page.goto(FIXTURE.as_uri())
_inject_g8431_row(page, icd1="1", checked=False)
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
assert result.changed is True
icd_changes = [c for c in result.changes if "before" in c]
checkbox_changes = [c for c in result.changes if "before" not in c]
by_code = {c["code"]: c for c in icd_changes}
assert set(by_code) == {"99213", "G8510", "G8431"}, icd_changes
assert by_code["G8510"]["after"]["icd"] == ["2", "", "", ""], by_code
assert by_code["G8431"]["after"]["icd"] == ["2", "", "", ""], by_code
assert by_code["99213"]["after"]["icd"] == ["1", "3", "", ""], by_code
checkbox_codes = {c["code"] for c in checkbox_changes}
assert checkbox_codes == {"G8510", "G8431"}, checkbox_changes
g8431_row = page.locator(sel.SEL_CPT_ROWS).nth(3)
assert [g8431_row.locator(s).first.input_value() for s in sel.SEL_CPT_ICD] \
== ["2", "", "", ""]
assert g8431_row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is True
@case
def apply_suppresses_a_duplicate_g8510_row_keeping_the_first(page):
"""
The client's follow-up: G8510 duplicated on the same claim, both
checked. The first (CPTROW_2, from the fixture) is retagged and left
billed exactly as the base scenario proves; the duplicate (injected,
later in DOM order) gets its ICD pointer retagged too but is then
unchecked and its Billed Fee zeroed — "only one is enough".
"""
page.goto(FIXTURE.as_uri())
_inject_duplicate_target_row(page, "G8510", icd1="1", checked=True, fee="75.00")
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
assert result.changed is True
assert len(result.changes) == 5, result.changes
icd_changes = [c for c in result.changes if "before" in c]
checked_changes = [c for c in result.changes
if "before" not in c and "unchecked" not in c and "fee" not in c]
duplicate_changes = [c for c in result.changes
if "before" not in c and ("unchecked" in c or "fee" in c)]
assert {c["row"] for c in icd_changes} == {0, 2, 3}, icd_changes
assert checked_changes == [{"row": 2, "code": "G8510"}], checked_changes
assert duplicate_changes == [{
"row": 3, "code": "G8510",
"unchecked": True, "fee": {"before": "75.00", "after": "0.00"},
}], duplicate_changes
first_row = page.locator(sel.SEL_CPT_ROWS).nth(2)
assert first_row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is True
assert first_row.locator(sel.SEL_CPT_BILLED_FEE).first.input_value() == "65.00", \
"the first G8510 row must keep its own fee — only the duplicate is zeroed"
duplicate_row = page.locator(sel.SEL_CPT_ROWS).nth(3)
assert duplicate_row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is False
assert duplicate_row.locator(sel.SEL_CPT_BILLED_FEE).first.input_value() == "0.00"
@case
def apply_leaves_a_single_g8510_row_alone_no_duplicate_suppression(page):
"""
No second G8510/G8431 row on the claim — the duplicate step must be a
no-op, proven directly against the base fixture's change count (the
same 3 changes the non-duplicate test already asserts).
"""
page.goto(FIXTURE.as_uri())
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
assert len(result.changes) == 3, result.changes
assert not any("unchecked" in c or "fee" in c for c in result.changes), result.changes
@case
def apply_leaves_an_already_excluded_duplicate_g8510_alone(page):
"""
Live claim 9131000 (Logs\\run_20260929_161613.log): the first G8510 was
already checked and tagged with Z13.31 alone, and a second G8510 further
down sat unchecked at 0.00 — already excluded. The check step used to
check that duplicate and the duplicate step unchecked it again straight
after: no net change to the claim, but it was reported as changed, and
the review box listed "checkbox checked (was excluded from the claim)"
and "checkbox unchecked (duplicate row)" for the same row. There is
nothing to do on this claim at all.
"""
page.goto(FIXTURE.as_uri())
_make_claim_already_correct(page)
_inject_duplicate_target_row(page, "G8510", icd1="2", checked=False, fee="0.00")
_count_checkbox_clicks(page, "CPTROW_3")
result = depression_dx_pointer.apply(page, "9131000", {"icd": _ICD_WITH_DEPRESSION})
duplicate_changes = [c for c in result.changes if c["row"] == 3]
assert duplicate_changes == [], duplicate_changes
assert result.changed is False, result.changes
assert result.changes == [], result.changes
duplicate_row = page.locator(sel.SEL_CPT_ROWS).nth(3)
assert duplicate_row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is False
assert page.evaluate("window.clicksOn['CPTROW_3']") == 0, \
"the excluded duplicate's checkbox was clicked — updateBillToIns() would fire"
@case
def apply_checks_only_the_first_g8510_not_an_excluded_duplicate(page):
"""
The same already-excluded duplicate as above, but with the first G8510
still unchecked (the fixture's own 9103000 shape): that first row is the
one to re-include, and only it. The duplicate — unchecked at 0.00 and
already carrying Z13.31 — is left exactly as it was.
"""
page.goto(FIXTURE.as_uri())
_inject_duplicate_target_row(page, "G8510", icd1="2", checked=False, fee="0.00")
_count_checkbox_clicks(page, "CPTROW_3")
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
checked_changes = [c for c in result.changes
if "before" not in c and "unchecked" not in c and "fee" not in c]
assert checked_changes == [{"row": 2, "code": "G8510"}], checked_changes
assert [c for c in result.changes if c["row"] == 3] == [], result.changes
rows = page.locator(sel.SEL_CPT_ROWS)
assert rows.nth(2).locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is True
assert rows.nth(3).locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked() is False
assert rows.nth(3).locator(sel.SEL_CPT_BILLED_FEE).first.input_value() == "0.00"
assert page.evaluate("window.clicksOn['CPTROW_3']") == 0, \
"the excluded duplicate's checkbox was clicked — updateBillToIns() would fire"
# =============================================================================
# Which row is kept per code — the ONE shared helper both the re-include and
# the duplicate step use (operator ruling, 2026-09-30)
# =============================================================================
@case
def kept_row_is_the_first_row_for_a_code_when_it_is_priced():
rows = [(2, "G8510", "65.00"), (3, "G8510", "75.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8510": 2}
@case
def kept_row_skips_zero_fee_copies_for_the_first_priced_one():
rows = [(2, "G8510", "0.00"), (3, "G8510", ""), (4, "G8510", "65.00"),
(5, "G8510", "75.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8510": 4}
@case
def kept_row_is_the_first_by_position_when_every_copy_is_zero_fee():
rows = [(2, "G8510", "0.00"), (3, "G8510", ""), (4, "G8510", "$0.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8510": 2}
@case
def kept_row_counts_a_row_with_no_fee_input_as_eligible():
# None: no Billed Fee input at all — unknown, not zero.
rows = [(2, "G8510", "0.00"), (3, "G8510", None), (4, "G8510", "65.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8510": 3}
@case
def kept_row_counts_a_non_numeric_fee_as_eligible():
# is_zero_fee("N/A") is False — an unreadable fee is not zero.
rows = [(2, "G8510", "0.00"), (3, "G8510", "N/A"), (4, "G8510", "65.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8510": 3}
@case
def kept_row_is_chosen_per_code():
rows = [(1, "G8431", "0.00"), (2, "G8510", "65.00"), (3, "G8431", "40.00"),
(4, "G8510", "0.00")]
assert claim_form.kept_cpt_row_per_code(rows) == {"G8431": 3, "G8510": 2}
@case
def kept_row_of_no_rows_is_empty():
assert claim_form.kept_cpt_row_per_code([]) == {}
def _set_fixture_g8510(page, *, checked=None, fee=None):
"""Sets the fixture's own G8510 (CPTROW_2) checkbox and/or Billed Fee."""
page.evaluate(
"""(a) => {
const tr = document.getElementById('CPTROW_2');
if (a.checked !== null)
tr.querySelector('[ng-click*="updateBillToIns("]').checked = a.checked;
if (a.fee !== null)
tr.querySelector('[data-fieldname="ClaimCPTBilledFee"]').value = a.fee;
}""", {"checked": checked, "fee": fee})
def _state(page, index):
row = page.locator(sel.SEL_CPT_ROWS).nth(index)
return (row.locator(sel.SEL_CPT_ASSIGN_TO_PATIENT).first.is_checked(),
row.locator(sel.SEL_CPT_BILLED_FEE).first.input_value())
@case
def apply_keeps_the_priced_g8510_when_the_first_copy_is_zero_fee(page):
"""
Operator ruling (2026-09-30): the G8510 kept is the first whose fee is
not zero. The fixture's G8510 (unchecked) is set to 0.00 and a later
G8510 sits unchecked at 65.00 — that one is re-included, and the 0.00
copy is left exactly as it is: already unchecked, already 0.00, never
clicked. Before, the re-include step skipped the 0.00 first copy and
no G8510 was billed at all.
"""
page.goto(FIXTURE.as_uri())
_set_fixture_g8510(page, fee="0.00")
_inject_duplicate_target_row(page, "G8510", icd1="1", checked=False, fee="65.00")
_count_checkbox_clicks(page, "CPTROW_2")
_count_checkbox_clicks(page, "CPTROW_3")
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
not_retags = [c for c in result.changes if "before" not in c]
assert not_retags == [{"row": 3, "code": "G8510"}], result.changes
assert (_state(page, 2), _state(page, 3)) == ((False, "0.00"), (True, "65.00"))
assert page.evaluate("window.clicksOn") == {"CPTROW_2": 0, "CPTROW_3": 1}
@case
def apply_unchecks_a_checked_zero_fee_first_copy_as_the_duplicate(page):
"""
The same ruling from the other side: the first G8510 checked at 0.00,
a later one checked at 75.00. The 75.00 copy is kept and keeps its fee;
the 0.00 first copy is now the duplicate, unchecked by the duplicate
step (its fee is already 0.00, so it is not written). Called straight
here — in a real run zero_fee_uncheck has unchecked it first
(test_conditions_zero_fee_uncheck.py).
"""
page.goto(FIXTURE.as_uri())
_set_fixture_g8510(page, checked=True, fee="0.00")
_inject_duplicate_target_row(page, "G8510", icd1="1", checked=True, fee="75.00")
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
not_retags = [c for c in result.changes if "before" not in c]
assert not_retags == [{"row": 2, "code": "G8510", "unchecked": True}], result.changes
assert (_state(page, 2), _state(page, 3)) == ((False, "0.00"), (True, "75.00"))
@case
def apply_never_checks_a_zero_fee_g8510_even_when_every_copy_is_zero_fee(page):
# Every copy at zero: the first by position is the one kept, and it is
# still never checked — a line billed at zero is never billed.
page.goto(FIXTURE.as_uri())
_set_fixture_g8510(page, fee="0.00")
_inject_duplicate_target_row(page, "G8510", icd1="1", checked=False, fee="0.00")
_count_checkbox_clicks(page, "CPTROW_2")
_count_checkbox_clicks(page, "CPTROW_3")
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
assert [c for c in result.changes if "before" not in c] == [], result.changes
assert (_state(page, 2), _state(page, 3)) == ((False, "0.00"), (False, "0.00"))
assert page.evaluate("window.clicksOn") == {"CPTROW_2": 0, "CPTROW_3": 0}
@case
def re_include_and_duplicate_steps_always_agree_on_the_kept_row(page):
"""
`ensure_cpt_rows_checked()` and `zero_and_uncheck_duplicate_cpt_rows()`
decide "which G8510 is kept" through the one shared helper, so across
every shape the row the first may check is never a row the second
unchecks — claim 9131000's toggle can not come back through them
disagreeing. `(first checked, first fee, later checked, later fee)` ->
the row kept.
"""
shapes = [
((True, "65.00", False, "0.00"), 2), # live claim 9131000
((False, "65.00", False, "0.00"), 2),
((False, "0.00", False, "65.00"), 3),
((True, "0.00", True, "65.00"), 3),
((False, "", True, "75.00"), 3),
((True, "65.00", True, "75.00"), 2),
((False, "0.00", False, "0.00"), 2), # every copy zero: first by position
]
for (first_checked, first_fee, later_checked, later_fee), kept in shapes:
page.goto(FIXTURE.as_uri())
_set_fixture_g8510(page, checked=first_checked, fee=first_fee)
_inject_duplicate_target_row(page, "G8510", checked=later_checked,
fee=later_fee)
before = {2: _state(page, 2), 3: _state(page, 3)}
shape = (first_checked, first_fee, later_checked, later_fee)
checked = claim_form.ensure_cpt_rows_checked(page, {"G8510", "G8431"})
duplicate = claim_form.zero_and_uncheck_duplicate_cpt_rows(
page, {"G8510", "G8431"})
assert {c["row"] for c in checked} <= {kept}, (shape, checked)
assert kept not in {c["row"] for c in duplicate}, (shape, duplicate)
other = 5 - kept
other_checked, other_fee = _state(page, other)
assert other_checked is False and claim_form.is_zero_fee(other_fee), \
(shape, "the other copy must end excluded", _state(page, other))
assert _state(page, kept)[1] == before[kept][1], \
(shape, "the kept row's fee must never be written")
@case
def apply_logs_why_when_the_claim_is_already_correct(page):
"""
Live claim 9132000: Z13.31 was already only on G8431, so apply()
returned ConditionResult.none — but the log's last word on it was
"1 condition(s) matched — about to apply: depression_dx_pointer", which
reads as a silent failure. Other conditions name their own "nothing
to ..." reason; this one does too, and only on that path — not when
the claim did change, and not when there is no Z13.31 to act on.
"""
page.goto(FIXTURE.as_uri())
_make_claim_already_correct(page)
out = io.StringIO()
with contextlib.redirect_stdout(out):
result = depression_dx_pointer.apply(page, "9132000", {"icd": _ICD_WITH_DEPRESSION})
assert result.changed is False, result.changes
logged = out.getvalue()
assert "[COND depression_dx_pointer 9132000]" in logged, logged
assert "nothing to change" in logged, logged
page.goto(FIXTURE.as_uri())
out = io.StringIO()
with contextlib.redirect_stdout(out):
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
assert result.changed is True, result.changes
assert "nothing to change" not in out.getvalue(), out.getvalue()
page.goto(FIXTURE.as_uri())
out = io.StringIO()
with contextlib.redirect_stdout(out):
depression_dx_pointer.apply(
page, "9103000", {"icd": [{"#": "1", "Code": "Z30.430", "Name": "..."}]})
assert "nothing to change" not in out.getvalue(), out.getvalue()
@case
def apply_is_a_no_op_when_the_claim_has_no_depression_dx(page):
page.goto(FIXTURE.as_uri())
data = {"icd": [{"#": "1", "Code": "Z30.430", "Name": "..."}]}
result = depression_dx_pointer.apply(page, "9103000", data)
assert result.changed is False
assert result.changes == []
@case
def describe_names_each_retagged_row(page):
page.goto(FIXTURE.as_uri())
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
text = depression_dx_pointer.describe(result)
assert "G8510" in text and "99213" in text, text
@case
def describe_names_g8431_too_when_it_is_on_the_claim(page):
page.goto(FIXTURE.as_uri())
_inject_g8431_row(page, icd1="1", checked=False)
result = depression_dx_pointer.apply(page, "9103000", {"icd": _ICD_WITH_DEPRESSION})
text = depression_dx_pointer.describe(result)
assert "G8431" in text, text
@case
def run_all_fires_depression_dx_pointer_alongside_telehealth_independently(page):
"""
Against the REAL registry, not fakes - proves this condition is wired
into conditions.CONDITIONS and does not collide with the telehealth
conditions, which key off progress_notes/insurance, not icd.
"""
page.goto(FIXTURE.as_uri())
data = {"icd": _ICD_WITH_DEPRESSION}
results = run_all(page, "9103000", data)
assert len(results) == 1, results
assert results[0].condition_name == "depression_dx_pointer", results
def _run_cases() -> int:
if not FIXTURE.exists():
print(f" FAIL fixture missing: {FIXTURE}")
return 1
try:
from playwright.sync_api import sync_playwright
except ImportError:
print(" SKIP playwright is not installed")
return 0
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:
from ecw_bot import settings as _cfg
# These cases exercise eCW's own click and Add flow, as a LIVE-WRITE run
# does. VERIFY clicks no box and adds no row (eCW saves both at once,
# 2026-10-16): that is tests/test_verify_no_live_writes.py.
orig = _cfg.SAVE_CORRECTIONS
_cfg.SAVE_CORRECTIONS = True
try:
return _run_cases()
finally:
_cfg.SAVE_CORRECTIONS = orig
if __name__ == "__main__":
sys.exit(main())