test(e2e): isolate runs and identities without a new backend endpoint (WP-74)

The three specs shared one mutable backend and said so in their own
comments ("Restart the backend between CI runs"). WP-70 recorded the fix as
a dev-only seed endpoint; it isn't needed. The DB path already routes
through IConfiguration, so playwright.config's webServer hands the backend a
throwaway SQLite file per invocation — the same trick TestWebApplicationFactory
already uses, with zero backend change. And StubIdentityProvider already
honoured X-Subject; the only gap was that nothing sent it. That matters
because the backend has no IsDevelopment() gate anywhere, so a seed endpoint
would have had to invent the codebase's first environment gate.

subjectInterceptor mirrors the existing roleInterceptor and is wired into the
same isDevMode()-only list. Interceptors alone were not enough: the raw XHR
upload and the hand-written letter-preview fetch bypass Angular's chain (as
CLAUDE.md documents), so both now stamp X-Subject explicitly — without that,
every uploaded document still landed under DemoOwner.

reuseExistingServer stays on: flipping it would break local runs for anyone
already serving the docker stack. Each run gets a unique DB filename and
global-setup sweeps only prior runs' leftovers — deleting a fixed path
mid-run risks SQLite silently recreating an empty, unmigrated file under
fullyParallel.

Verified: e2e passes twice back-to-back with no backend restart, and
X-Subject was observed on a real request, not merely wired.

brief-v2.spec.ts keeps the shared identity for now — see the KNOWN GAP note;
a backend staleness bug makes /brief/preview return a sent letter with the
draft watermark for any non-DemoOwner BSN. actors.ts reserves the actor for
whoever fixes it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-08-19 16:32:07 +02:00
co-authored by Claude Sonnet 5
parent 6bc00a917c
commit 42f7bd651d
12 changed files with 319 additions and 21 deletions
+7 -6
View File
@@ -6,13 +6,14 @@ import { Actors, loginAs, SeedRefs } from './support/actors';
// with zero policy questions, so the only required upload is identiteit), submit,
// and see the real confirmation. Not a full wizard-coverage suite — see WP-19.
//
// The backend is in-memory and shared across runs; this test mutates real state
// (creates a registratie application for the fixed demo identity). Restart the
// backend between CI runs — a second run would see a leftover Concept/submitted
// application on the dashboard, which this test doesn't assert against, but a
// stricter future test might.
// This test mutates real state (creates+submits a registratie application), so it
// logs in as its own BSN (`registratieAanvrager`, WP-74) rather than the shared
// `zorgverlener` — a leftover Concept from a previous run lands on THAT BSN's
// dashboard, not this one's, so a rerun (or another spec) never sees it. The
// backend itself also gets a fresh throwaway SQLite file per `npm run e2e`
// invocation (`playwright.config.ts`), so even a from-scratch run starts clean.
test('login → dashboard → registratie wizard → submitted', async ({ page }) => {
await loginAs(page, Actors.zorgverlener);
await loginAs(page, Actors.registratieAanvrager);
await expect(page).toHaveURL(/\/dashboard$/);
await expect(page.getByRole('heading', { level: 1, name: 'Mijn overzicht' })).toBeVisible();