Skip to content

E2E & live smoke

Three Playwright suites and four gated shell scripts. None of them runs as part of npm test, and one of the three runs in CI.

Suite Where Tests In CI? Last measured
Frontend Playwright packages/frontend/e2e/ 19 No 12 on 20 Aug, 7 on 22 Aug
Public-site Playwright packages/public-site/e2e/ 6 No 19 Aug β€” not re-run since
PA-demo Playwright packages/pa-demo/e2e/ 11 Yes β€” azure-pa-demo-acc.yml 29 Aug
Live smoke scripts scripts/*.sh 4 scripts No never run for these pages

The PA-demo suite is covered on its own page β€” see PA-demo suite. It is in CI because it needs no backend, database or Keycloak: Playwright starts its own dev server and that is the whole environment. The other two need a running stack, which is the whole of why they are not there yet.


Frontend Playwright suite

packages/frontend/e2e/, its own playwright.config.ts (npm run test:e2e --workspace=@ronl/frontend). Chromium only, workers: 1.

The single worker is deliberate: two specs race to claim an identically-named task for the same caseworker against the shared local Operaton engine, so the suite trades parallelism for correctness.

The directory holds 19 tests across 7 specs, measured in two groups:

  • 12 tests β€” the caseworker journeys, tenant isolation, role redirects and smoke, measured 20 August against v2026.08.20 in 54.1s. Detailed on Caseworker.
  • 7 tests β€” the two PA cockpit specs, measured 22 August in 18.9s. Detailed on PA cockpit.

What it needs running

docker compose up -d at the repo root (Keycloak + Postgres + Redis), the backend and frontend dev servers, and a sibling linked-data-explorer repo's backend on :3001 β€” the last is required for the Procesbibliotheek journey.

e2e/global-setup.ts checks all of these before any test runs and fails fast with the exact start commands if one is down. It does not start anything itself, which is why this suite is not wired into CI: there is no human to start the stack on a runner. The PA-demo suite has no such dependency and does run in CI β€” the difference is the stack, not the tooling. See Overview β†’ Roadmap for what closing that would take.

Getting JSON output

The config declares list and html reporters, not json. To capture machine -readable results:

PLAYWRIGHT_JSON_OUTPUT_NAME=../../playwright-report/frontend-e2e.json \
  npm run test:e2e --workspace=@ronl/frontend -- --reporter=list,json

Three things will bite otherwise. PLAYWRIGHT_JSON_OUTPUT_NAME resolves against the cwd, which under --workspace is packages/frontend, hence the ../../. Passing --reporter replaces the configured list, so the auto-opening HTML report is lost unless you add it back. And do not redirect stdout to a file: globalTeardown prompts interactively there (Clean up Operaton history…? [y/N]), so the prompt would be swallowed into the file and the terminal would appear to hang.

The HTML report also embeds the same result data, which is where the 20 August figures came from when no JSON reporter was configured.


Public-site Playwright suite

Covered on Public site suite β€” six tests including three axe-core accessibility scans, and the one suite here that starts its own dev server.

Its figures date from 19 August and were not re-run for v2026.08.23.


Live smoke suite (shell scripts, cross-app)

Four gated shell scripts under scripts/, deliberately kept out of npm test β€” they hit real running services over the network, mutate real data in two cases, and need real credentials for some tiers.

These were not run for this page. They are described from their configuration and specs only.

Script Covers Mutates?
test-smoke-live.sh Cross-app health: Operaton, Keycloak, LDE, TriplyDB, CPRMV, media store, eDOCS reach/status, MCP layer No
test-edocs-live.sh eDOCS workspace and document lifecycle β€” see eDOCS β€” Live Testing Yes
test-doccle-live.sh Doccle sender API β€” see Doccle β€” Live Testing Yes β€” not yet live-tested, still DOCCLE_STUB_MODE=true in every run so far
test-m2m-routes.sh M2M decision-evaluation routes against ACC No
bash scripts/test-smoke-live.sh                                     # local, full run
CLIENT_SECRET=<secret> TARGET=acc bash scripts/test-smoke-live.sh   # against ACC
bash scripts/test-edocs-live.sh                                     # eDOCS, mutating
CLIENT_SECRET=<secret> bash scripts/test-doccle-live.sh              # Doccle, mutating
CLIENT_SECRET=<secret> bash scripts/test-m2m-routes.sh               # M2M routes vs ACC

Exit 0 when nothing failed, 1 on any real failure β€” a dependency that is intentionally off (stub mode, no CLIENT_SECRET) skips with a ~ note, never a red fail. curl http://localhost:3002/v1/health | jq ., or the ACC equivalent, is the fastest single check of a running instance's dependency status, independent of the smoke scripts.


Rate limiting will masquerade as an outage

The backend rate-limits per IP. A short authoring journey measures ~21 requests to /v1/pa/*, so two specs back to back can exhaust a low budget, and the UI renders the resulting 429 as "Kon dossiers niet laden" β€” indistinguishable from a backend that is down.

e2e/helpers/rate-limit.ts records the first 429 of a run and fails the test with a message naming the throttle. It deliberately does not retry or wait it out. The shipped default was raised to 1000/min in config.ts; note the limiter keys on IP, so TRUST_PROXY decides whether that budget is per user or per deployment.

The full account of how that was diagnosed β€” including two confident wrong answers before anyone looked at the response codes β€” is on Writing tests.