Skip to content

UI QA script

The manual pass for the three pages after any UI change. The automated part runs first:

node --test "tests/web/*.test.mjs"          # pure page logic (labels, validation, HTML builders escape <x>)
.venv\Scripts\pytest tests\test_web_pages.py tests\test_web_assets.py tests\test_faxes_static.py tests\test_review_ui_api.py tests\test_faxes_api.py tests\test_settings_api.py tests\test_jobs_file_hold.py -q

Then start the app on a sandbox data directory so nothing touches production files:

$env:FAX_DATA_DIR = ".local-qa"; $env:APP_AUTH_ENABLED = "false"
.venv\Scripts\uvicorn faxautomation.main:app --reload

Use synthetic documents only. Never type a patient name, MRN or date of birth into any field.

1. Shell (every page)

  • [ ] /, /loinc-review, /faxes, /settings share the header; the current page is highlighted; the status strip shows the mapper state (and "N setting override(s)" when the Settings page overrides env).
  • [ ] Widths 375, 768 and 1280 px: no horizontal scroll; the review page shows 1, 2 and 3 columns; Tab reaches every control with a visible focus ring.
  • [ ] Browser console: no errors on load; the report-only CSP may list violations, note them for 17.11's enforced policy.
  • [ ] With APP_AUTH_ENABLED=true: delete the session cookie, click Refresh on the review page → the app goes to /login?next=/loinc-review and returns after sign-in.

2. LOINC review

  • [ ] Chips show counts; Open is pressed by default; the count matches the list.
  • [ ] Type in the search box → the list narrows server-side (test name, printed name, code, status, job or case id); Clear restores it.
  • [ ] Open /loinc-review?case=<id> → the case is selected with the list scrolled to it.
  • [ ] A case with a Gemini-renamed row shows Printed on the fax and Gemini read this as in "What the fax showed".
  • [ ] "What the mapper made of it" reads as sentences (reason, closest candidate, What to do).
  • [ ] Candidates: the mapper's best is marked, none is pre-selected; clicking one fills Selected LOINC and marks the row.
  • [ ] Search LOINC: type two letters → results; arrow keys move, Enter picks, Escape closes.
  • [ ] Submit with nothing chosen → the decision field is outlined and focused, "Fix the highlighted field" beside the button, no scroll.
  • [ ] Approve with a short rationale → the rationale field is outlined.
  • [ ] Valid approval → the green line under Submit names the decision and the code and says to publish; the case stays open with a Decided badge; the form locks.
  • [ ] Select the next case → an empty form (reviewer id and name remembered).
  • [ ] Reopen a decided case → Withdraw approval and reopen asks first; afterwards the form is unlocked and prefilled from the withdrawn decision with the banner.
  • [ ] Publish… with nothing eligible → the modal says nothing to publish and Confirm is disabled. With one approval → the modal lists the code; Confirm → toast with the version; the strip's registry version updates.
  • [ ] New correction → modal with human specimen labels; a short "why" is refused inline; success opens the disputed case.
  • [ ] Export CSV downloads a file; with the mapper package missing the toast says so.

3. Extraction harness

  • [ ] Ticking Simulate inbox greys the parser boxes and shows the Path B note; unticking restores them.
  • [ ] Run a synthetic PDF: the status line sits beside the Run button; the stages progress; Cancel mid-run leaves "Cancelled — the server may still finish this job."
  • [ ] Force a stage error (e.g. an unreadable file): only that stage is red, later stages grey, the bar keeps its width.
  • [ ] Results: the scan-quality line, the funnel line with drops, the job expiry line; the labs table sorts on Test/Value/Unit/LOINC/Mapper/Page and filters by text; Details opens the drawer with the LabObservation; Escape closes it.
  • [ ] Wrong code on a coded row lands on /loinc-review?case=….
  • [ ] File to Elation (sandbox): the filing card persists with the report id, Copy report id works, Open in Fax explorer shows the job; a second click asks "File again?".
  • [ ] After the job TTL the export buttons and File to Elation are disabled with the expiry note.
  • [ ] Verdict (plan Part A): set Max pages to 2 on the Settings page → a 3-page upload is refused with "413 … too_many_pages" beside Run. Set Hold only with at least N lab rows to 1 and Hold when the unfiled share reaches to 0.5, run a synthetic lab where the mapper abstains on most rows → the red "Held — not filed" line, the button reads File anyway…, clicking it asks first, filing then succeeds and the card shows. Clear the overrides afterwards.

4. Fax explorer

  • [ ] /faxes lists the run above (source "Harness upload"); search by the job-id prefix, by outcome=parsed, by date.
  • [ ] Each tab renders: Timeline (deltas), Funnel (chain and drops), Filing (segments, note, Read back from Elation after a sandbox filing), Rows (Wrong code), Review cases (links), Logs ("Set GCP_PROJECT_ID…" until set), Retries.
  • [ ] Retry a sandbox inbox item twice (POST /internal/inbox/poll?submit=true against the sandbox, skip_if_processed=false from a script) → Retries shows attempts 1 and 2 and the journey of each.
  • [ ] With auth on: /faxes redirects to login; /api/v1/faxes returns 401.
  • [ ] The Held outcome chip and the Needs communication chip narrow the list; the run held above shows a "Held by verdict" badge and the Filing tab opens with the verdict card (numbers, thresholds, "Hold overridden by …" after File anyway).

5. Settings

  • [ ] /settings lists every key with its three columns (in effect, .env, override); the summary line says "No overrides" on a fresh data directory.
  • [ ] Type a page cap and pick On for Gemini classify → Save overrides → the toast names what changed, the summary says who saved and when, the status strip shows "2 setting overrides", /health → runtime_settings.override_count = 2.
  • [ ] A hold share below the warn share → "The hold share must be at or above the warn share." beside the buttons; nothing saved. "ten" in a number field → the field is named and focused.
  • [ ] Blank a field and save → its row shows the .env badge again. Clear all overrides asks first, then the summary says "No overrides".
  • [ ] With auth on: /settings redirects to login; /api/v1/settings returns 401.

6. Closed page

  • [ ] With FAX_EDGE_MODE=true outside clinic hours / shows the closed page with the force-load form; no status strip; the header colours match the app.