Three properties, each with a mutation-verified guard: The chip and the line run on DIFFERENT clocks and must keep doing so. The chip expires after three hours; the line stands for the rest of the local day. Collapsing them onto one clock reads like a simplification and silently deletes the day's read at lunchtime. Degradation is the headline. For every reason a line can fail to exist — no provider, no consent, an exhausted budget, a dead provider, an unusable output — the row stays line-less, the reservation is reconciled, and the chip and the provisional-to-final flip still work. The degraded digest is built through the real composer rather than a hand-shaped fixture, so the assertions cannot agree with themselves. The server pass carries no wall-clock time. The hero paints on the SSR pass because it is the LCP element, so a locale-formatted time inside it would differ from the browser's — React #418. The tests render through the server snapshot, which is exactly the pass that must stay clock-free. The seeded end-to-end spec lands a sleep batch through the real ingest route, writes the arrival marker, and asserts the chip and the phase flip in place on a refetch trigger the digest hook already declares — no reload, no new cadence.
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/—global-setup.ts(auth + DB seeding),test-helpers.ts(shared login + navigation helpers).utils/— fixtures such asmock-dashboard-snapshot.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 thev1427-*regression set.
Convention
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.