2026-08-11 15:42:21 UTC · branch master at 7333e37 · Mac156.local · triggered by console:mac156
Pure in-process tests — no database. These use the repo's `_FakeDB` or call functions directly, so they prove logic, not wiring.
Tests that drive the mounted FastAPI app against a real Mongo. These are the ones that prove a route exists, is reachable, and is authorised — the class of defect unit tests have repeatedly passed straight through.
Node's built-in runner over the pure logic extracted into `lib/`. Fast and exhaustive over what it sees; it does not render a component or touch a route.
674 tests · 674 passed · 4.0 s
Renders real React components and asserts on the produced markup — the tier that can catch a screen that never reaches its data or an overlay that is not a dialog.
Drives a real browser against a running frontend and backend. Opt-in: it needs both servers up, and a tier that cannot reach them is reported as an error, never as a pass.
ruff, mypy and the TypeScript compiler — findings that need no test to run.
6,594 of 6,649 statements · branches 90.4%. The vertical rule marks the 90% target.
Read this percentage with its scope. This runner measures only the files a test imported — an untested module is absent from the denominator rather than scored 0%, so this number cannot fall when untested code is added. File reach is the honest headline: 63 of 493 source files reached (13%).
No route measurement in this run — the backend tier did not execute, so nothing can be said about which endpoints are exercised.
A trend needs at least two runs. This is run 1 — the line appears once there is something to compare.
No test failed and none errored. Note that this is a statement about the tiers that ran — check the tier list above for any marked “could not run”.
| Test | Outcome | Time | Tier |
|---|---|---|---|
| lib/a11y-structure.test.ts::the scan finds the pages — otherwise everything below passes vacuously | passed | 147 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the dashboard offers a skip link to a real target | passed | 1 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the skip link is reachable by keyboard but not visible by default | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::every navigation landmark is named | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::no page renders a select with neither a label nor an aria-label | passed | 523 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the unlabelled-select allow-list has no stale entries | passed | 589 ms | Frontend · unit |
| lib/a11y-structure.test.ts::every select in the app has an accessible name | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the select scanner actually finds selects | passed | 281 ms | Frontend · unit |
| lib/a11y-structure.test.ts::a rendered failure banner is announced, not just coloured | passed | 245 ms | Frontend · unit |
| lib/a11y-structure.test.ts::no page hangs a click handler on a plain div or span | passed | 235 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the clickable-non-control list has no stale entries | passed | 240 ms | Frontend · unit |
| lib/a11y-structure.test.ts::no form control draws its boundary with the decorative border token | passed | 245 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the form-control border scanner actually finds controls | passed | 238 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the comment stripper leaves comment-like text inside strings alone | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the comment stripper removes both comment forms | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the comment stripper keeps a comment marker inside a template literal | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::an escaped quote does not end the string | passed | 0 ms | Frontend · unit |
| lib/a11y-structure.test.ts::every form control has a programmatic accessible name | passed | 267 ms | Frontend · unit |
| lib/a11y-structure.test.ts::the unnamed-control allow-list has no stale entries | passed | 264 ms | Frontend · unit |
| lib/a11y-structure.test.ts::a placeholder is not accepted as an accessible name | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::the console does not offer to create a platform admin | passed | 2 ms | Frontend · unit |
| lib/account-kinds.test.ts::no option names a raw hanType | passed | 1 ms | Frontend · unit |
| lib/account-kinds.test.ts::every option explains what the account can do | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::email is normalised the same way the server normalises it | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::a clinician account asks for the role that decides billing | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::the form states one reason at a time, in filling order | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::a kind the console cannot create is refused before it is sent | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::a reused account is never reported as created | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::an account created without its invite says so | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::the happy path is the only outcome that claims the invite went | passed | 0 ms | Frontend · unit |
| lib/account-kinds.test.ts::a response that created nothing is not dressed up as progress | passed | 1 ms | Frontend · unit |
| lib/account-kinds.test.ts::kindLabel never renders an internal token to a user | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::every spelling of an account type resolves the same way | passed | 2 ms | Frontend · unit |
| lib/account-type.test.ts::an unrecognised code holds nothing rather than the nearest match | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::a session carrying only `role` is still recognised | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::hanType wins when both claims are present | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::staff are not owners and the owner-only nav stays hidden | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::globalAdmin grants business administration but not the platform | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::a patient holds nothing | passed | 0 ms | Frontend · unit |
| lib/account-type.test.ts::the client and server capability tables agree on the shape | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::an address is required, and so is a branch | passed | 2 ms | Frontend · unit |
| lib/affiliation.test.ts::a malformed address is refused before the round-trip | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::a well-formed invitation passes | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::addresses are normalised so one person is one affiliation | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::an existing affiliation at ANOTHER branch does not block this one | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::re-inviting somebody with a pending invitation is allowed and recognised | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::a pending invitation is never counted as a provider | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::removing an accepted affiliation and revoking an invitation are different acts | passed | 0 ms | Frontend · unit |
| lib/affiliation.test.ts::the empty state says what would fill it, and counts what is waiting | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::alerts and escalations are counted separately | passed | 6 ms | Frontend · unit |
| lib/alert-metrics.test.ts::an escalation is counted from either producer | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::patient counts are the caseload, not the volume | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::alerts outside the month are excluded | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::a branch filter narrows the report | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::addressed and unaddressed always sum to the total | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::the report names who to look at, worst first | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::an empty month reports zeros rather than blanks | passed | 1 ms | Frontend · unit |
| lib/alert-metrics.test.ts::monthKey and monthBounds round-trip | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::the CSV quotes anything that could break a column | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::the CSV states the ladder breakdown, not just a total | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::a reading with no breach gets no highlight at all | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::a critical breach is red and says so in words | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::low and high are distinguished by words, not by shade | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::every tone carries a text label and a description | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::the severity vocabularies from the different ingest paths all normalise | passed | 0 ms | Frontend · unit |
| lib/alert-metrics.test.ts::direction comes from the rule relation, and MAX wins a mixed breach | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::the patient scope is read from the query string | passed | 2 ms | Frontend · unit |
| lib/alerts-scope.test.ts::an encoded patient id round-trips | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::scoping keeps only that patient's alerts | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::both id fields are matched, because the two producers disagree | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::no scope means no filtering at all | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::the banner names the patient, falling back to a readable id | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::clearing the scope preserves the rest of the query state | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::patient ids render readably | passed | 0 ms | Frontend · unit |
| lib/alerts-scope.test.ts::the empty state says which question it is answering | passed | 1 ms | Frontend · unit |
| lib/automation-audit.test.ts::modeTone / modeLabel map the three modes | passed | 21 ms | Frontend · unit |
| lib/automation-audit.test.ts::groupByArea preserves area order and groups items | passed | 2 ms | Frontend · unit |
| lib/billing-provider.test.ts::a branch with billing providers lists them | passed | 3 ms | Frontend · unit |
| lib/billing-provider.test.ts::the row states why it qualifies | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::a row from an older backend says what it knows, not more | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::no providers and no billable providers are different states | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::an empty branch offers no busywork | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::a gap always carries the action that closes it | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::a mixed branch reports both counts | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::singular and plural both read correctly | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::billable requires BOTH an NPI and a taxonomy | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::undefined from the server is not a crash | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::clinical staff are never described as providers | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::an employed clinician who may render is surfaced, not hidden | passed | 0 ms | Frontend · unit |
| lib/billing-provider.test.ts::a provider row states either its basis or its gap, never nothing | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::the global option comes first and is the empty value | passed | 31 ms | Frontend · unit |
| lib/branch-filter.test.ts::the global label is the same string everywhere | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::archived branches are never offered | passed | 2 ms | Frontend · unit |
| lib/branch-filter.test.ts::same-named branches are disambiguated, not collapsed | passed | 20 ms | Frontend · unit |
| lib/branch-filter.test.ts::a branch with no name falls back to its id, never to blank | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::options are sorted so the list is scannable | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::an empty branch list yields just the global option | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::global matches every row; a branch matches only its own | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::a row with no branch is excluded by a specific branch filter | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::shortId is stable and short enough to read | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::an empty branch list explains itself instead of rendering nothing | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::same-named branches are told apart by CITY, not by an id suffix | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::the id suffix survives where the city cannot disambiguate | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::a city is read from either shape the record carries it in | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::a unique name is never decorated | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::duplicate names are reported so a human can resolve them | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::an archived branch is not counted as a duplicate | passed | 0 ms | Frontend · unit |
| lib/branch-filter.test.ts::branches with no name at all are not reported as duplicates of each other | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::dormant and at-risk are the bands that read as urgent | passed | 12 ms | Frontend · unit |
| lib/call-list.test.ts::a clinic never called says so rather than rendering a dash | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::last-called wording is relative and plain | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::an overdue next-call says how overdue | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::filter matches contact names and talking points, not just the clinic | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::filter ANDs terms so two words narrow rather than widen | passed | 0 ms | Frontend · unit |
| lib/call-list.test.ts::tel href strips formatting so the click actually dials | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::consent item is a communication gate | passed | 4 ms | Frontend · unit |
| lib/care-autopilot.test.ts::careplan item is a clinical gate with a friendly plan label | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::ops_comm surfaces the cadence label + subject | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::monitoring escalation shows severity + reading type | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::recruit is a communication invite | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::careteam item is a clinical one-click team assignment (P1) | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::adherence nudge is a communication item (P2) | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::BHI screening is a communication item (Phase B) | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::billing item summarizes plan/month/codes/route and sits in the billing gate | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::route + adapter labels are human-readable | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::planLabel humanizes the combined plan | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::gateOf prefers the backend-stamped gate | passed | 0 ms | Frontend · unit |
| lib/care-autopilot.test.ts::splitByGate routes items into three columns (incl. careteam + adherence) | passed | 1 ms | Frontend · unit |
| lib/care-autopilot.test.ts::level helpers describe the manual→autopilot ramp | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::an ineligible clinician is listed and disabled, never hidden | passed | 2 ms | Frontend · unit |
| lib/care-ownership.test.ts::an eligible clinician is selectable and carries no warning | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::the owner list has no credential gate — that is why the role exists | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::no eligible supervisor anywhere is a different problem from none assigned | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::billable says so plainly | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::not billable always carries the next step | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::a missing billing payload is treated as not billable, not as billable | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::escalation always names somebody, or says plainly that nobody is named | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::a fallback to the supervisor SAYS it is a fallback | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::an unknown repId still renders — the id beats a blank line | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::assigning one role does not clear the other | passed | 1 ms | Frontend · unit |
| lib/care-ownership.test.ts::clearing a role is expressible, and distinct from not touching it | passed | 0 ms | Frontend · unit |
| lib/care-ownership.test.ts::both roles can be set in one call | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::roleOptions filters the provisioned roster by role, case-insensitively | passed | 2 ms | Frontend · unit |
| lib/care-team-options.test.ts::a saved member missing from the roster is KEPT, not dropped | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::a saved member still on the roster is not duplicated or flagged | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::an unknown saved id still renders rather than disappearing | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::stale options say why they are unusual | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::seedFromRows rehydrates a single saved plan | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::bulk edit seeds only the fields every selected row agrees on | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::conflicting care plans leave the plan unset rather than guessing | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::an unprovisioned branch offers NO ONE — no corp-staff fallback | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::the hard block does not erase an assignment already on the record | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::seedFromRows tolerates empty input and missing team | passed | 0 ms | Frontend · unit |
| lib/care-team-options.test.ts::staleAssignments names the roles the roster can no longer supply | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::consent state is derived from the onboardFlow stamps | passed | 1 ms | Frontend · unit |
| lib/consent-gate.test.ts::a declined consent outranks an earlier signature | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::assignment is refused outright when nobody in the selection consented | passed | 3 ms | Frontend · unit |
| lib/consent-gate.test.ts::an empty selection is refused with a different message | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::a consented patient may be assigned, silently | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::a mixed batch proceeds with the consented rows and names the skipped count | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::an id with no matching row is skipped, not assumed consented | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::once consent is recorded, sending and uploading both close | passed | 30 ms | Frontend · unit |
| lib/consent-gate.test.ts::a merely sent consent leaves both actions open | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::a manual upload counts as consent for the lockout | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::refMedia is recognised whether it is a list or a single value | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::single and bulk assignment land on the same dedicated page | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::the ids survive the round trip through the query string | passed | 0 ms | Frontend · unit |
| lib/consent-gate.test.ts::a malformed or absent ids param yields nothing rather than a phantom row | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::reads the single-object refMedia the upload handler writes | passed | 2 ms | Frontend · unit |
| lib/consent-media.test.ts::reads the legacy CRefWithMedia list shape too | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::skips malformed entries rather than returning a broken link | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::a stored document links to the served file | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::a digital e-consent links to the signed record instead | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::ids are encoded | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::the link label reflects what will actually open | passed | 0 ms | Frontend · unit |
| lib/consent-media.test.ts::a failed consent fetch says WHY, not just that it failed | passed | 0 ms | Frontend · unit |
| lib/consent-validation.test.ts::validateConsentFile rejects a missing file (Ticket 1.1) | passed | 1 ms | Frontend · unit |
| lib/consent-validation.test.ts::validateConsentFile rejects an empty file | passed | 0 ms | Frontend · unit |
| lib/consent-validation.test.ts::validateConsentFile accepts a PDF by MIME type | passed | 0 ms | Frontend · unit |
| lib/consent-validation.test.ts::validateConsentFile accepts a JPEG by extension when type is blank | passed | 0 ms | Frontend · unit |
| lib/consent-validation.test.ts::validateConsentFile rejects a non-PDF/JPEG document | passed | 0 ms | Frontend · unit |
| lib/constitution-faq.test.ts::the constitution is reachable from the frontend repo | passed | 1 ms | Frontend · unit |
| lib/constitution-faq.test.ts::the register parses and is not empty | passed | 2 ms | Frontend · unit |
| lib/constitution-faq.test.ts::every defect names a frontend test that exists | passed | 3 ms | Frontend · unit |
| lib/constitution-faq.test.ts::every defect names a frontend test that actually contains tests | passed | 10 ms | Frontend · unit |
| lib/constitution-faq.test.ts::no defect leaves either side blank | passed | 1 ms | Frontend · unit |
| lib/constitution-faq.test.ts::defect ids are unique | passed | 0 ms | Frontend · unit |
| lib/constitution-faq.test.ts::every row describes what went wrong, not what is now fine | passed | 1 ms | Frontend · unit |
| lib/contact-patient.test.ts::a bound patient is used immediately, with no picking step | passed | 2 ms | Frontend · unit |
| lib/contact-patient.test.ts::a bound patient is never widened into a pick-list | passed | 2 ms | Frontend · unit |
| lib/contact-patient.test.ts::without a bound patient, a supplied list is offered | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::precedence falls through fetched then seed | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::an empty fetch falls back rather than leaving the modal blank | passed | 1 ms | Frontend · unit |
| lib/contact-patient.test.ts::rows without an id are discarded, not shown as blank entries | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::a bound patient with no id does not lock an empty context | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::the active patient is the bound one, whatever the list says | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::a stale selection resolves to null rather than to someone else | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::the modal has exactly the two tabs QA specified, in order | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::names come from either the row or its demog block | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::a nameless row shows its id, and an anonymous row says Patient | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::ids are read from any of the three key names in use | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::a missing phone stays empty instead of inheriting a demo number | passed | 0 ms | Frontend · unit |
| lib/contact-patient.test.ts::toContact produces exactly what the modal needs | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::the palette parses — otherwise every check below passes vacuously | passed | 3 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::body text meets 4.5:1 on both surfaces | passed | 2 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::the primary colour works as TEXT, which is how links use it | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::a white label ON the primary colour also meets 4.5:1 | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::destructive actions are legible in both directions | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::form field boundaries meet the 3:1 non-text threshold | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::the focus ring is visible against the surfaces it appears on | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::large text still needs 3:1 and headings clear it comfortably | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::the ratio is order-independent and bounded, as WCAG defines it | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::relative luminance matches the known anchors | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::oklch converts to the sRGB a browser would render | passed | 0 ms | Frontend · unit |
| lib/contrast-tokens.test.ts::an unparseable colour scores 0 rather than passing | passed | 0 ms | Frontend · unit |
| lib/conveyor.test.ts::toneFor maps statuses to colour tones | passed | 1 ms | Frontend · unit |
| lib/conveyor.test.ts::statusLabel is human-readable | passed | 0 ms | Frontend · unit |
| lib/conveyor.test.ts::conveyorPercent computes progress | passed | 0 ms | Frontend · unit |
| lib/conveyor.test.ts::needsApproval flags pending human steps | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::a signed-out visitor gets labelled sample data | passed | 2 ms | Frontend · unit |
| lib/data-state.test.ts::a signed-in user with real rows sees them and no banner | passed | 1 ms | Frontend · unit |
| lib/data-state.test.ts::a signed-in user with NO rows is told so — never given sample rows | passed | 1 ms | Frontend · unit |
| lib/data-state.test.ts::a failed fetch surfaces an error and a retry — never sample rows | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::an error outranks whatever rows happened to be in hand | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::a signed-in session can NEVER be shown sample rows | passed | 1 ms | Frontend · unit |
| lib/data-state.test.ts::a signed-out visitor with no sample data is told to sign in | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::the empty message names something the user can actually do | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::without a hint, the empty message still names the screen | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::an expired session says to sign in again, not 'error 401' | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::a server fault and a client fault read differently | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::a rate limit tells the user to wait rather than to retry now | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::a network failure points at the connection | passed | 0 ms | Frontend · unit |
| lib/data-state.test.ts::an unrecognised error never leaks a stack or a bare code | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::a complete record raises nothing | passed | 2 ms | Frontend · unit |
| lib/demographics-quality.test.ts::a pre-1970 date of birth is NOT an issue | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::a missing identity blocks; missing detail only warns | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::a nameless record cannot be assigned to | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::issues name the patient so the user knows who to fix | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::summary distinguishes blocked from merely incomplete | passed | 0 ms | Frontend · unit |
| lib/demographics-quality.test.ts::raw epoch detection recognises an unformatted timestamp | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::a device is findable by the patient holding it | passed | 2 ms | Frontend · unit |
| lib/device-filter.test.ts::the hardware fields still search as before | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::search is case- and whitespace-insensitive | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::an unassigned device does not crash the patient-name search | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::the placeholder names every field actually searched | passed | 1 ms | Frontend · unit |
| lib/device-filter.test.ts::the branch filter narrows to that branch | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::'all' and an absent filter both mean no branch narrowing | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::a device with no branch is excluded by a specific branch, not by 'all' | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::filters compose — branch AND text together | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::the category tab narrows by device group | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::a device with no received date is excluded from a dated window | passed | 1 ms | Frontend · unit |
| lib/device-filter.test.ts::the window is bounded at both ends | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::patients filter by name, email, device status and branch | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::status 'all' keeps everyone regardless of device count | passed | 0 ms | Frontend · unit |
| lib/device-filter.test.ts::the row type survives filtering, so callers keep their own fields | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::an empty inventory says so rather than showing a row of zeros | passed | 1 ms | Frontend · unit |
| lib/device-stock.test.ts::the headline states each category it actually has | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::stock nobody has allocated is named, not silently absent | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::a partial allocation reads differently from a total one | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::a device out with a patient names the patient and the reason | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::a retired device is not moved | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::moving a device where it already is is refused before the request | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::no destination chosen asks for one rather than failing silently | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::an available device moves | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::a branch holding nothing says so | passed | 0 ms | Frontend · unit |
| lib/device-stock.test.ts::unallocated stock sorts last, real branches by name | passed | 13 ms | Frontend · unit |
| lib/device-stock.test.ts::the totals a screen renders are the ones the server sent | passed | 0 ms | Frontend · unit |
| lib/dicom-metadata.test.ts::canEditDicom: clinician/owner/admin yes; patient/staff no; globalAdmin override | passed | 5 ms | Frontend · unit |
| lib/dicom-metadata.test.ts::cleanOverrides: only whitelisted + changed + trimmed non-empty | passed | 1 ms | Frontend · unit |
| lib/dicom-metadata.test.ts::cleanOverrides: nothing changed → empty object | passed | 0 ms | Frontend · unit |
| lib/dicom-metadata.test.ts::correctedSet: from meta.corrected | passed | 0 ms | Frontend · unit |
| lib/dicom-metadata.test.ts::seedForm: every editable tag present, stringified, blanks for missing | passed | 0 ms | Frontend · unit |
| lib/dur-alerts.test.ts::severityTone maps severity to tone | passed | 1 ms | Frontend · unit |
| lib/dur-alerts.test.ts::rankAlerts orders most-severe first | passed | 1 ms | Frontend · unit |
| lib/dur-alerts.test.ts::alertSummary + blocksSubmit | passed | 0 ms | Frontend · unit |
| lib/dur-alerts.test.ts::hasContra: only absolute contraindications | passed | 0 ms | Frontend · unit |
| lib/dur-alerts.test.ts::highCodes: codes of high-severity alerts only | passed | 0 ms | Frontend · unit |
| lib/dur-alerts.test.ts::alertText: prefers message, then detail/title/code | passed | 0 ms | Frontend · unit |
| lib/ein.test.ts::formatEin inserts the dash after 2 digits | passed | 4 ms | Frontend · unit |
| lib/ein.test.ts::isValidEinFormat requires 9 digits | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::eligibility and consent are never collapsed into one answer | passed | 1 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::both present is the only ready state | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::a received paper consent counts as consent | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::unchecked coverage is not reported as ineligible | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::a decline outranks everything else | passed | 3 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::consent in flight reads differently from consent never sent | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::both outstanding names both, and the action depends on which kind | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::status matching is case and whitespace tolerant | passed | 1 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::the summary names what is blocking, not just how many | passed | 5 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::every patient lands in exactly one bucket | passed | 1 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::an empty pipeline says so rather than showing zeros | passed | 0 ms | Frontend · unit |
| lib/enrolment-readiness.test.ts::the merge keeps every lens the four screens offered | passed | 0 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::no drill-down target is linked with a bare, context-free href | passed | 4 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::the guard is actually reading a page with links in it | passed | 0 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::an up-navigation link is not required to carry context | passed | 0 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::no detail page carries a corporate id in a link | passed | 0 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::no screen reads carried context from window.location in a state initialiser | passed | 3 ms | Frontend · unit |
| lib/entity-context-carried.test.ts::the representatives screen reads its branch from the router | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::a branch drilled into is readable on the next screen | passed | 3 ms | Frontend · unit |
| lib/entity-context.test.ts::no context reads as no context, not as an empty one | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::a corporate is NEVER carried in a link | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::carrying a context replaces any context already on the href | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::switching entity kind does not leave the previous kind behind | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::clearing context removes only the context | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::an unresolved name shows the identifier, never blank | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::screens whose actions change someone's standing are marked | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::every carriable kind has a distinct parameter name | passed | 0 ms | Frontend · unit |
| lib/entity-context.test.ts::a href with no query survives a null context unchanged | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::a pre-1970 date of birth formats instead of rendering a dash | passed | 52 ms | Frontend · unit |
| lib/epoch-date.test.ts::post-1970 dates still format | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::numeric strings are accepted, as the API sometimes returns them | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::genuinely absent values render the fallback | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::ISO date strings still work | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::date input keeps the local calendar day | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::date input is empty, never a bogus date, when absent | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::age is computed from a pre-1970 birth | passed | 0 ms | Frontend · unit |
| lib/epoch-date.test.ts::age is null rather than a wrong number when unknown | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the dashboard has an error boundary | passed | 1 ms | Frontend · unit |
| lib/error-boundary.test.ts::the error boundary is a Client Component | passed | 1 ms | Frontend · unit |
| lib/error-boundary.test.ts::the error boundary offers recovery through unstable_retry | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the headline says the screen failed, not that records are absent | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the error boundary explicitly separates 'failed' from 'none' | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the error boundary states plainly that nothing was changed | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the error boundary surfaces the digest for support | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the dashboard has route-level loading UI | passed | 0 ms | Frontend · unit |
| lib/error-boundary.test.ts::the loading skeleton announces itself to assistive technology | passed | 2 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the default ladder is three rungs | passed | 1 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the selectable lengths come from the server's bounds, not from guesses | passed | 1 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the consequence is stated in DAYS, which is the clinician's unit | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the consequence names the window the breach-days are counted in | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the window is the server's number, never recomputed here | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::same-day readings counting once is said, not assumed | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::a one-rung ladder is refused with the clinical reason, not a range | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::an over-long ladder is refused because it reads as switched off | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::a value inside the range has no complaint | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::the top rung is labelled as the top | passed | 0 ms | Frontend · unit |
| lib/escalation-ladder.test.ts::a non-default policy is flagged as deliberate | passed | 0 ms | Frontend · unit |
| lib/escalation.test.ts::slaTone maps SLA status to colour | passed | 4 ms | Frontend · unit |
| lib/escalation.test.ts::slaLabel reads clearly in each state | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::Tab wraps from the last element back to the first | passed | 2 ms | Frontend · unit |
| lib/focus-trap.test.ts::Shift+Tab wraps from the first element to the last | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::mid-list Tab is left to the browser | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::focus outside the dialog is pulled back to the right edge | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::a single focusable keeps focus on itself in both directions | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::an empty dialog does not intercept Tab | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::Tab can never land outside the dialog | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::focus starts on the first focusable | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::data-autofocus wins when present | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::an out-of-range autofocus falls back rather than focusing nothing | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::a dialog with no focusable content yields null so the panel takes focus | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::the selector excludes tabindex=-1 | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::the selector excludes disabled controls | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::the selector covers the interactive elements this app actually uses | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::a dialog is labelled by an id derived from its own | passed | 0 ms | Frontend · unit |
| lib/focus-trap.test.ts::dialog ids are stable and sequential, not random | passed | 0 ms | Frontend · unit |
| lib/global-search.test.ts::empty query returns nothing | passed | 4 ms | Frontend · unit |
| lib/global-search.test.ts::matches label + href, multi-term AND | passed | 0 ms | Frontend · unit |
| lib/guest-join.test.ts::isPinFormat: 4-8 digits only | passed | 1 ms | Frontend · unit |
| lib/guest-join.test.ts::msUntil + expiryLabel | passed | 0 ms | Frontend · unit |
| lib/guest-join.test.ts::joinUrl: no double slash | passed | 0 ms | Frontend · unit |
| lib/guest-join.test.ts::guestStep: loading/pin/ready/joined | passed | 0 ms | Frontend · unit |
| lib/lead-funnel.test.ts::buildFunnel counts stages + win rate | passed | 2 ms | Frontend · unit |
| lib/lead-funnel.test.ts::buildFunnel handles empty | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::a round trip through the pickers preserves the instant | passed | 10 ms | Frontend · unit |
| lib/manual-reading.test.ts::an unparseable value yields empty pickers rather than NaN | passed | 1 ms | Frontend · unit |
| lib/manual-reading.test.ts::a missing date or time is refused with which one is missing | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::31 February is refused, not rolled forward into March | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::a reading cannot be recorded in the future | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::a reading taken earlier today is accepted | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::the picker's max is today, so the future is unreachable by mouse | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::malformed shapes are refused rather than coerced | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::a patient label reads either roster key | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::a patient with no name is never labelled with their raw id | passed | 0 ms | Frontend · unit |
| lib/manual-reading.test.ts::the DOB disambiguates two patients with the same name | passed | 0 ms | Frontend · unit |
| lib/modal-a11y.test.ts::the dialog primitives declare full dialog semantics | passed | 6 ms | Frontend · unit |
| lib/modal-a11y.test.ts::the primitives contain Tab and restore focus on close | passed | 1 ms | Frontend · unit |
| lib/modal-a11y.test.ts::no NEW overlay ships without dialog semantics | passed | 47 ms | Frontend · unit |
| lib/modal-a11y.test.ts::the frozen list does not outlive the overlays it names | passed | 21 ms | Frontend · unit |
| lib/modal-a11y.test.ts::the not-a-dialog exemptions still name real overlay-shaped regions | passed | 20 ms | Frontend · unit |
| lib/modal-a11y.test.ts::every hand-rolled overlay has been migrated | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::no standalone Ops heading survives in the business sidebar | passed | 2 ms | Frontend · unit |
| lib/nav.test.ts::the care programme is one module ordered by the patient journey | passed | 1 ms | Frontend · unit |
| lib/nav.test.ts::clinical and operational screens sit in the SAME module | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::the Rules Engine is reachable from the business sidebar | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::every business href is still reachable and unique | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::staff still lose exactly the owner-only surfaces, nothing more | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::the permission-derived nav mirrors the same structure | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::regrouping the permission nav granted no new page | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::no duplicate hrefs within a single role's menu | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::the Care-Time redirect is not offered as its own menu item | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::Communications is a parent group, not a loose sidebar item | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::Contact Patient sits inside Communications, not on its own | passed | 0 ms | Frontend · unit |
| lib/nav.test.ts::there is no second ops module beside Care Program | passed | 0 ms | Frontend · unit |
| lib/no-raw-api-fetch.test.ts::the scanner sees the files it is meant to scan | passed | 37 ms | Frontend · unit |
| lib/no-raw-api-fetch.test.ts::no new screen calls the API with a bare fetch | passed | 98 ms | Frontend · unit |
| lib/no-raw-api-fetch.test.ts::the frozen list carries no stale entries | passed | 79 ms | Frontend · unit |
| lib/no-raw-api-fetch.test.ts::apiFetch is exported for them to migrate onto | passed | 2 ms | Frontend · unit |
| lib/no-raw-api-fetch.test.ts::the shared client applies a deadline | passed | 1 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::clinical, billing and privacy screens NEVER seed on failure | passed | 17 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::these screens use the shared data-state rule | passed | 4 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::no NEW screen starts seeding on failure | passed | 147 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::the frozen list does not outlive the screens it names | passed | 181 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::the settings form cannot save what it could not load | passed | 1 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::the widened scanner catches the lowercase-seed shape it was written for | passed | 0 ms | Frontend · unit |
| lib/no-seed-on-failure.test.ts::the scanner does not flag an ordinary length check | passed | 0 ms | Frontend · unit |
| lib/no-unguarded-refetch.test.ts::the scanner finds effects at all | passed | 60 ms | Frontend · unit |
| lib/no-unguarded-refetch.test.ts::patient-identified screens drop stale responses | passed | 71 ms | Frontend · unit |
| lib/no-unguarded-refetch.test.ts::a patient-identified screen may never be added to the frozen list | passed | 0 ms | Frontend · unit |
| lib/no-unguarded-refetch.test.ts::no new unguarded refetch appears | passed | 43 ms | Frontend · unit |
| lib/no-unguarded-refetch.test.ts::the frozen list carries no stale entries | passed | 42 ms | Frontend · unit |
| lib/npi.test.ts::the check digit is computed over the 80840 issuer prefix | passed | 1 ms | Frontend · unit |
| lib/npi.test.ts::a valid NPI is accepted | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a transposed pair is caught — the whole reason this runs at the keyboard | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a repdigit string is refused even when it passes Luhn | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::punctuation is stripped, so a pasted 123-456-7893 works | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::an empty NPI is not an error — people are hired before the NPI arrives | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a wrong length says how many digits were given | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a taxonomy code may carry letters anywhere — 363LP2300N is real | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a taxonomy code of the wrong length is refused | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::eligibility needs BOTH an NPI and a taxonomy, and says which is missing | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::every ineligible answer carries a next step | passed | 0 ms | Frontend · unit |
| lib/npi.test.ts::a stored NPI that fails its check digit is reported, not silently ignored | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::a blood-pressure reading yields all three of its metrics | passed | 18 ms | Frontend · unit |
| lib/patient-detail.test.ts::each device family contributes its own metrics | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::a reading with no recognised payload contributes nothing | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::a non-numeric value is dropped, not coerced | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::the summary reports count, highest, lowest and average per metric | passed | 2 ms | Frontend · unit |
| lib/patient-detail.test.ts::averages are rounded to one decimal | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::trend points come out chronological, whatever order they arrived in | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::a reading with no timestamp is excluded from the trend | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::an over-long range is clamped and says so | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::a range inside the cap is left exactly alone | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::the default range is the last 30 days | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::inRange is inclusive of both ends | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::the CSV has one row per metric reading and quotes defensively | passed | 13 ms | Frontend · unit |
| lib/patient-detail.test.ts::the patient header never renders a blank cell | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::age is computed in whole years and omitted when unknowable | passed | 0 ms | Frontend · unit |
| lib/patient-detail.test.ts::readingTime accepts either timestamp field | passed | 0 ms | Frontend · unit |
| lib/pdf-sign.test.ts::placement: each corner, inset by margin, origin bottom-left | passed | 2 ms | Frontend · unit |
| lib/pdf-sign.test.ts::placement: clamps a box bigger than the page to 0 | passed | 0 ms | Frontend · unit |
| lib/pdf-sign.test.ts::signatureBlock: name + date, reason only when present | passed | 0 ms | Frontend · unit |
| lib/pdf-sign.test.ts::clampPage: in-range, over, under/NaN → last | passed | 0 ms | Frontend · unit |
| lib/pdf-sign.test.ts::receiptId: stable format ES-XXXXXX-YYYY | passed | 0 ms | Frontend · unit |
| lib/pdf-sign.test.ts::CORNERS covers all four | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::the country code is rendered, not stripped | passed | 9 ms | Frontend · unit |
| lib/phone-format.test.ts::a stored number with no country code assumes US rather than rendering unusable | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::a country code already inside the number is not doubled | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::non-US numbers keep their own code and are not forced into US grouping | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::an absent number shows the fallback, never a stray '+1' | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::tel href carries the country code so mobile dialers accept it | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::country code normalizes from any stored spelling | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::digits are extracted from any formatting | passed | 0 ms | Frontend · unit |
| lib/phone-format.test.ts::record helper accepts the field spellings actually stored | passed | 0 ms | Frontend · unit |
| lib/rbac.test.ts::isBusinessAdmin: owner (B) and admin (A) pass; staff/clinician/patient fail | passed | 12 ms | Frontend · unit |
| lib/rbac.test.ts::isBusinessAdmin: an explicit globalAdmin flag grants access regardless of hanType | passed | 1 ms | Frontend · unit |
| lib/rbac.test.ts::filterOwnerOnly hides owner-only items from staff, keeps them for admin | passed | 8 ms | Frontend · unit |
| lib/rbac.test.ts::pageAccessFor: staff readonly on Manage Business/Branches, denied on owner-only | passed | 0 ms | Frontend · unit |
| lib/rbac.test.ts::canAccessHref blocks staff from owner-only surfaces only | passed | 0 ms | Frontend · unit |
| lib/rcm-billing.test.ts::engine choices: the three the UI offers, deterministic default listed first | passed | 3 ms | Frontend · unit |
| lib/rcm-billing.test.ts::footingStatus: foots vs does-not-foot with a specific mismatch reason | passed | 17 ms | Frontend · unit |
| lib/rcm-billing.test.ts::engineNote: null when honored; explains a fallback | passed | 0 ms | Frontend · unit |
| lib/rcm-billing.test.ts::money: two-decimal currency; em-dash for null | passed | 0 ms | Frontend · unit |
| lib/rcm-billing.test.ts::pdfsOnly: keeps only PDFs from a directory selection | passed | 0 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::rowText: flattens nested objects + arrays, lowercased | passed | 1 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::rowText: null/undefined values are skipped, no throw | passed | 0 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::filterRows: empty query returns all rows unchanged | passed | 0 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::filterRows: single term substring match on nested field | passed | 0 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::filterRows: multiple terms are AND-ed | passed | 0 ms | Frontend · unit |
| lib/rcm-flatview.test.ts::matchLabel: total when all shown, 'n of m' when filtered | passed | 0 ms | Frontend · unit |
| lib/rcm-remit.test.ts::eraPullSummary: error / empty / posted | passed | 1 ms | Frontend · unit |
| lib/rcm-remit.test.ts::priorAuthTone: approved / denied / pended | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::chart actions are gated on registration, not disabled outright | passed | 1 ms | Frontend · unit |
| lib/registry-actions.test.ts::message to doctor needs a registered, affiliated patient | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::free patients cannot be contacted without consent | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::contact needs at least one channel | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::move to onboarding only on the Qualified tab for qualifying patients | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::the synthetic rpm.patientmd.com handle never renders as an address | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::CSV upload accepts any .csv, not one exact filename | passed | 0 ms | Frontend · unit |
| lib/registry-actions.test.ts::CSV validation is on columns, with header aliases | passed | 21 ms | Frontend · unit |
| lib/registry-insurance.test.ts::isSelfPay: explicit self_pay type | passed | 2 ms | Frontend · unit |
| lib/registry-insurance.test.ts::isSelfPay: explicit insured type wins over blank payer | passed | 0 ms | Frontend · unit |
| lib/registry-insurance.test.ts::isSelfPay: no coverage type + no payer => cash (US default) | passed | 0 ms | Frontend · unit |
| lib/registry-insurance.test.ts::isSelfPay: cash / self-pay free text | passed | 3 ms | Frontend · unit |
| lib/registry-insurance.test.ts::isSelfPay: named payer is insured | passed | 0 ms | Frontend · unit |
| lib/registry-insurance.test.ts::classifyPayer: Medicare vs Medicare Advantage | passed | 0 ms | Frontend · unit |
| lib/registry-insurance.test.ts::classifyPayer: Medicaid / TRICARE / commercial / blank | passed | 0 ms | Frontend · unit |
| lib/registry-insurance.test.ts::coveragePayload: self-pay flag + normalized type | passed | 7 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::board body defaults: 20 per page, no filter params when all='all' | passed | 2 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::branch + doctor cascade map to branchId + ownerUserId | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::consent status maps correctly (incl. not-received → recd:false) | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::consent type + plan + search map through | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::missingQualifiedFields lists the blanks, empty when complete | passed | 1 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::addFormError: branch required, then phone (email OPTIONAL — QA 7/27), then name | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::isValidEmail | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::isValidPhone: NANP for +1 | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::dobError: future + too-old rejected, valid ok, empty allowed | passed | 1 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::pastDateError: last completed appointment cannot be in the future | passed | 0 ms | Frontend · unit |
| lib/registry-onboarding.test.ts::validatePatientForm: phone required, email optional, aggregates field errors | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::representative: requires first name + email | passed | 2 ms | Frontend · unit |
| lib/rep-form.test.ts::representative: every row needs a branch | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::practitioner: clinical role IS the designation (row designation cleared) | passed | 1 ms | Frontend · unit |
| lib/rep-form.test.ts::non-clinical staff: designation is preserved | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::self-as-operator: needs a branch, emits an Operator responsibility, no personal info | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::edit: existing repId is carried through | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::new doctor login: clinician-app portal + temp password toast | passed | 7 ms | Frontend · unit |
| lib/rep-form.test.ts::new staff login: business-app portal + invite-sent when no temp password (prod) | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::reused account: link message, not a new-login toast | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::care-team count pluralizes | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a fresh Add-representative modal opens empty | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::closing after a save cannot leave the next rep holding the last one's branches | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a default branch is preselected — that is a choice, not leftover state | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::editing an existing rep opens on THEIR values, not blank | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a self-as-operator rep is recognised and its branches gathered | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::the Operator grant is not shown as an editable admin role | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a rep with no responsibilities still opens with one editable row | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::the country code defaults to +1 rather than empty | passed | 3 ms | Frontend · unit |
| lib/rep-form.test.ts::a clinician's NPI and taxonomy reach the payload | passed | 6 ms | Frontend · unit |
| lib/rep-form.test.ts::a pasted NPI is normalised, and a lowercase taxonomy is upper-cased | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a blank credential saves — hiring precedes the NPI | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a transposed NPI is refused BEFORE the round-trip, not after | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a malformed taxonomy is refused | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::a non-clinical person never carries a credential | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::switching to non-clinical does not smuggle a stale credential through | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::self-mode clears the credential explicitly | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::the form opens with the credential already on file | passed | 0 ms | Frontend · unit |
| lib/rep-form.test.ts::reopening for a different person does not retain the previous credential | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::a practitioner's badge names their clinical role | passed | 1 ms | Frontend · unit |
| lib/rep-labels.test.ts::a non-clinical rep says so rather than showing a placeholder | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::NO label ever degrades to a hyphen | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::an uncatalogued value stays readable instead of blank | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::a value the catalog has never heard of is humanized, not echoed raw | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::an empty value yields an empty label, so the badge can be omitted | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::a row lists its designation and admin grants together | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::a directory-only row reads as Staff, which is a real state | passed | 0 ms | Frontend · unit |
| lib/rep-labels.test.ts::multiple admin grants are all shown | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::an ordinary call gets the default deadline | passed | 2 ms | Frontend · unit |
| lib/request-timeout.test.ts::a call may set its own deadline | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::zero or negative disables the deadline deliberately | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::the deadline aborts a request that never answers | passed | 48 ms | Frontend · unit |
| lib/request-timeout.test.ts::dispose stops the timer so a finished request leaves nothing pending | passed | 61 ms | Frontend · unit |
| lib/request-timeout.test.ts::a caller cancelling is NOT reported as a timeout | passed | 5 ms | Frontend · unit |
| lib/request-timeout.test.ts::an already-aborted caller signal aborts immediately | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::with the deadline disabled the caller's signal still passes through | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::with no deadline and no caller signal, fetch gets no signal | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::dispose is safe to call twice | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::the timeout message names the limit in seconds and says what to do | passed | 0 ms | Frontend · unit |
| lib/request-timeout.test.ts::timeouts carry 408 so callers can tell slow from wrong | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::only the server's allowed targets are offered | passed | 3 ms | Frontend · unit |
| lib/role-assignment.test.ts::an account with nowhere to go offers nothing, and says so | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::no targets loaded is distinguished from an empty list of targets | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::an unknown user id is reported as unknown, not as a disallowed move | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::assigning to the current realm is refused with the reason | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::a target outside the server's list is refused even if it is a known realm | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::a permitted move is allowed with no complaint | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::an empty user id asks for one rather than showing a broken form | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::a no-op is reported as a no-op, never as success | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::a real change explains what it does and does not affect | passed | 0 ms | Frontend · unit |
| lib/role-assignment.test.ts::an unknown realm falls back to its raw value, never to blank | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a doctor gets a badge — the defect QA reported | passed | 3 ms | Frontend · unit |
| lib/roster-badges.test.ts::every practitioner role has a human label, not an enum value | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::an unknown role is title-cased rather than rendered raw or dropped | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::clinical identity is listed before duties | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::duties from OTHER branches never appear on this branch's roster | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a duplicated designation is shown once | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a designation echoing the clinical role is not shown twice | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::administrative grants are badged and distinguishable from clinical ones | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a non-clinical staff member still gets their designation | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a missing phone is a stated absence, not an empty cell | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a phone is shown with its country code, normalised to + | passed | 0 ms | Frontend · unit |
| lib/roster-badges.test.ts::a nameless row falls back to the email local-part, never to blank | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::todayYmd is local, not UTC | passed | 4 ms | Frontend · unit |
| lib/rpm-listing.test.ts::an upcoming appointment cannot be in the past | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::Set TMS carries the patient so Care Time opens on them | passed | 1 ms | Frontend · unit |
| lib/rpm-listing.test.ts::alerts deep-link is scoped to the patient | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::alert tone escalates with count | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::branch filter matches the registry's semantics | passed | 1 ms | Frontend · unit |
| lib/rpm-listing.test.ts::care team summary names the lead and counts the rest | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::care team summary handles an empty or roleless team | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::send-document needs a channel to send on | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::view-measurements needs measurements | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::remove-patient needs an enrolment to end | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::the clinical-team hover never renders a raw database id | passed | 0 ms | Frontend · unit |
| lib/rpm-listing.test.ts::a real name still wins over the role placeholder | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::the cascade runs corp → branch → doctor → patient | passed | 15 ms | Frontend · unit |
| lib/rule-scope.test.ts::every level has a label a clinician would recognise | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::each level states what else an edit would change | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::the badge names the NARROWEST level that set anything | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::a rule nobody has overridden reports the protocol default | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::mixed provenance is detectable | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::the per-field breakdown puts the narrowest overrides first | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::field paths are rendered readably, not as dotted keys | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::an unknown level degrades to default rather than rendering raw | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::each level is visually distinct | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::a replacement names the rule it replaced and how much moved | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::an override identical to what it replaced says so | passed | 0 ms | Frontend · unit |
| lib/rule-scope.test.ts::no override at all is stated as the protocol default | passed | 0 ms | Frontend · unit |
| lib/sms-delivery.test.ts::normalizeStatus: lowercase, blank → unknown | passed | 1 ms | Frontend · unit |
| lib/sms-delivery.test.ts::statusTone: good/bad/pending | passed | 0 ms | Frontend · unit |
| lib/sms-delivery.test.ts::statusLabel: Title case, unknown → Queued | passed | 0 ms | Frontend · unit |
| lib/sms-delivery.test.ts::deliveryRateText | passed | 0 ms | Frontend · unit |
| lib/sms-delivery.test.ts::STATUS_FILTERS includes All + delivered + failed | passed | 0 ms | Frontend · unit |
| lib/soap-context.test.ts::noteTs: reads dtAppt, tolerates string dates, 0 when absent | passed | 3 ms | Frontend · unit |
| lib/soap-context.test.ts::latestSoapNote: picks max timestamp | passed | 0 ms | Frontend · unit |
| lib/soap-context.test.ts::latestSoapNote: empty list → null; undated list → first row | passed | 0 ms | Frontend · unit |
| lib/soap-context.test.ts::soapSections: only non-empty sections, charted order, chief complaint first | passed | 1 ms | Frontend · unit |
| lib/soap-context.test.ts::hasSoapContent: false when null or all-blank, true otherwise | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::a fresh guard applies its result | passed | 1 ms | Frontend · unit |
| lib/stale-guard.test.ts::a cancelled guard drops the result | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::cancel is idempotent — React may call cleanup more than once | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::guards are independent — one run cancelling does not affect another | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::the slow response for the PREVIOUS patient never renders | passed | 33 ms | Frontend · unit |
| lib/stale-guard.test.ts::without the guard, the same sequence renders the wrong patient | passed | 32 ms | Frontend · unit |
| lib/stale-guard.test.ts::latestOnly keeps the newest of out-of-order responses | passed | 32 ms | Frontend · unit |
| lib/stale-guard.test.ts::latestOnly passes a lone response through | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::latestOnly discards by identity, not by value | passed | 23 ms | Frontend · unit |
| lib/stale-guard.test.ts::a rejected newer request does not resurrect an older one | passed | 22 ms | Frontend · unit |
| lib/stale-guard.test.ts::a payload naming another patient is refused | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::a payload naming the current patient is accepted | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::an unstamped payload is accepted | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::an empty subjectId is not treated as a claim | passed | 0 ms | Frontend · unit |
| lib/stale-guard.test.ts::subject comparison is by value, not by reference type | passed | 0 ms | Frontend · unit |
| lib/statement-print.test.ts::fmtUSD: two decimals + separators, safe on junk | passed | 18 ms | Frontend · unit |
| lib/statement-print.test.ts::fmtStmtDate: em dash when absent, formats when present | passed | 5 ms | Frontend · unit |
| lib/statement-print.test.ts::statusTone: paid / overdue / open | passed | 0 ms | Frontend · unit |
| lib/statement-print.test.ts::amountDue: positive balance only, else 0 | passed | 0 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::simEnabled requires an explicit true | passed | 1 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::simEnabled fails closed on unknown or failed status | passed | 0 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::clampWindow keeps requests inside the server's bounds | passed | 1 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::clampWindow survives a blank number input | passed | 0 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::clampWindow truncates fractional input | passed | 0 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::runSummary pluralises alerts | passed | 0 ms | Frontend · unit |
| lib/telemetry-sim.test.ts::purgeTotal sums per-collection counts | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::global scope sends no tenant keys at all | passed | 2 ms | Frontend · unit |
| lib/tenant-scope.test.ts::a picked branch and corp are sent; nulls are omitted | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::extra fields survive alongside the scope | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::a JWT is never accepted as a tenant id | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::empty and non-string values are refused | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::forbidden stays distinct from empty | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::rows are counted, failures are failures | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::a non-array success body counts as empty, not as one row | passed | 0 ms | Frontend · unit |
| lib/tenant-scope.test.ts::every outcome has a line, and none of them invents data | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::a sane field passes | passed | 3 ms | Frontend · unit |
| lib/threshold-trends.test.ts::crossed min/max is caught at entry | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::urgent bounds must sit outside the normal band | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::partially-specified fields are fine | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::validateFields reports every bad field, not just the first | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::a trend number of zero is rejected because it silently disables the rule | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::negative trend numbers are rejected | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::a count that cannot fit its window is rejected | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::the protocol defaults themselves validate clean | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::only numeric keys are editable — action is a label, not a number | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::labels and units are human-readable | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::emptied trends are pruned so they do not shadow the default with nothing | passed | 0 ms | Frontend · unit |
| lib/threshold-trends.test.ts::validateOverride covers fields and trends together | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::the suite is gated until a patient is chosen | passed | 1 ms | Frontend · unit |
| lib/tms.test.ts::every child section inherits the one selection | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::an id outside the roster still binds, but names nobody it cannot name | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::no selection means no context for any child to act on | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::care plan drives the activity list | passed | 1 ms | Frontend · unit |
| lib/tms.test.ts::encode then decode is lossless | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::an empty note round-trips as empty, not as the meta string | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::a note containing the separator survives decoding | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::legacy rows with separate fields still decode | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::whenToMs handles both the modern epoch and the legacy object | passed | 1 ms | Frontend · unit |
| lib/tms.test.ts::roleFor labels the actor without echoing the id | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::CPT ladder: 99457 at 20 minutes, 99458 per further 20, capped at two | passed | 1 ms | Frontend · unit |
| lib/tms.test.ts::the PDF patient block carries the associated branch | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::a missing field prints a dash rather than vanishing | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::age is appended only when the DOB parses | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::column widths sum to the usable width, so nothing spills past the margin | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::notes are appended only for the reported patient, in the reported window | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::notes come out in chronological order | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::the window is inclusive of both end dates | passed | 0 ms | Frontend · unit |
| lib/tms.test.ts::the TMS-notes toggle defaults to OFF | passed | 0 ms | Frontend · unit |
Nothing queued. POST /api/runs with a valid token to request a run.
| Started | Status | Tests | Failed | Could not run | BE cov | FE cov | Commit |
|---|---|---|---|---|---|---|---|
| 2026-08-11T15:42:21 | passed | 674 | 0 | 0 | — | 99.2% | 7333e37 |
| 2026-08-11T14:50:31 | passed | 674 | 0 | 0 | — | 99.2% | e18343b |