Files
HealthLog/e2e
Marc-André Bombeck e406b9c7ab fix(coach): calm the answer column, its replies and its focus marks
The running status line now carries its seconds right after the text, in
the line's own muted tone, instead of at the far edge of the column. The
live count and every finished round read "4 s", the same spacing as the
settled summary, with a no-break space so a round never wraps between
number and unit.

Reply pills (follow-ups, clarifying choices, memory and plan decisions)
sit directly under the answer, and the action row is the last thing in
the column. Beside a pointer the row stays invisible until hover or
focus; above the pills it left an empty band between an answer and its
replies. Hovering or focusing the message still reveals the row without
moving anything.

Keyboard focus in the Coach panel is a solid ring in the neutral
text-field focus tone, never the purple ring: the pills, Undo and Change
merge it over the button primitive, and the hand-built controls carry it
directly. A structural test keeps the purple ring out of the panel.

A disabled native select now looks disabled, like Input and Select, so a
thinking depth locked by the operator no longer reads as a live choice.
In Settings, thinking depth takes the shape of Tone and Reply length
beside it; a memory entry's Forget is an icon like its edit; the
operator's highest-depth label sits on the switches' left edge.
2026-10-06 21:24:24 +02:00
..

e2e/

End-to-end browser tests. Playwright 1.60 drives a production build of the app against a real PostgreSQL, with @axe-core/playwright for accessibility assertions. This is the heaviest test tier; CI runs it on every PR, and locally it is worth running when a change touches a UI flow.

Running

pnpm e2e

The Playwright config (../playwright.config.ts) builds the app (next build) and brings up Postgres before the specs run; setup/global-setup.ts seeds the auth + fixture state. The suite is not part of the fast local gate (typecheck / lint / test) — it surfaces at PR CI, so expect responsive/wizard/nav reworks to flag here first.

Layout

  • setup/ — test.ts (the suite's test + expect entry point), global-setup.ts (auth + DB seeding), test-helpers.ts (shared login + navigation helpers).
  • utils/ — fixtures such as mock-dashboard-snapshot.ts.
  • fixtures/ — synthetic payloads a journey uploads, built in code rather than committed as blobs so the content stays reviewable (apple-health-export.ts).
  • *.spec.ts — one spec per flow: auth/login/redirect, dashboard, charts, the medication-wizard cadences (medications-wizard-*), insights generation + scroll restoration, doctor report, settings, mobile-viewport consistency, locale switch, accessibility (a11y.spec.ts), and the v1427-* regression set.

Conventions

Import test and expect from ./setup/test, never from @playwright/test — types (Page, Route, …) still come from the package. The entry point extends Playwright's test with an automatic fixture that drops route handlers and page listeners after every test, so a handler left in flight cannot fail the test it belonged to once the context closes. src/__tests__/e2e-route-cleanup-guard.test.ts enforces the import boundary.

Assert against stable data-* attributes (data-slot, data-display-step, root display attrs), not viewport-dependent visible text. Responsive sm:hidden UI changes break getByText on desktop while the underlying element is still present — anchoring on data attributes keeps the specs stable across breakpoints. See ../CLAUDE.md.