feat(fp): WP-19 — Playwright e2e smoke against the real FE+backend
Adds a happy-path spec (login → dashboard → registratie wizard, including a real identity-document upload → real submit) and a degraded-path spec (?scenario=error → <app-async> error slot → retry), both driving the real app against the real .NET backend, plus a CI job that boots both. Writing the retry spec surfaced a real bug: AsyncComponent's retry() only reloads a [resource]-fed instance, so every real page (all [data]-fed via a store's RemoteData) had a silently no-op retry button. Added a retryClicked output and wired it on the dashboard's two async blocks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,10 @@ npm run test-storybook:ci
|
||||
Backend stays untouched throughout (frontend-only backlog); `cd backend && dotnet test`
|
||||
only needs re-running if a WP unexpectedly touches `backend/`.
|
||||
|
||||
From WP-19 onward, `npm run e2e` is part of CI (its own job) but NOT part of the local
|
||||
GREEN one-liner above — it needs the real backend + `npm start` already running (see
|
||||
WP-19's own file), so it's a separate manual/CI step, not chained into the others.
|
||||
|
||||
## Order
|
||||
|
||||
Gates land before the work they cover; each lint rule lands in the same WP as the fixes
|
||||
@@ -58,7 +62,7 @@ for its existing violations, so every WP ends green.
|
||||
| [WP-16](WP-16-component-a11y.md) | Component a11y: description wiring + alert role | 4 · a11y | done |
|
||||
| [WP-17](WP-17-app-a11y.md) | App-level a11y: route focus, template lint, WCAG checklist | 4 · a11y | done |
|
||||
| [WP-18](WP-18-abac-capability-spine.md) | ABAC capability spine (Principal + capabilities, phase P1) | 5 · productie-volwassenheid | done |
|
||||
| [WP-19](WP-19-e2e-smoke.md) | Playwright e2e smoke | 5 · productie-volwassenheid | todo |
|
||||
| [WP-19](WP-19-e2e-smoke.md) | Playwright e2e smoke | 5 · productie-volwassenheid | done |
|
||||
| [WP-20](WP-20-second-locale.md) | Second locale proof | 5 · productie-volwassenheid | todo |
|
||||
| [WP-21](WP-21-resilience-seams.md) | Resilience seams (correlation-id, idempotency, retry) | 5 · productie-volwassenheid | todo |
|
||||
| [WP-22](WP-22-durable-persistence.md) | Durable persistence (optional tier) | 5 · productie-volwassenheid | todo |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# WP-19 — Playwright e2e smoke
|
||||
|
||||
Status: todo
|
||||
Status: done (pending commit)
|
||||
Phase: 5 — productie-volwassenheid
|
||||
|
||||
## Why
|
||||
@@ -70,14 +70,46 @@ serve` backgrounded), wait-on both ports, `npm run e2e`. `timeout-minutes: 15`
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] `npm run e2e` passes locally against `docker compose up` or `npm start` +
|
||||
- [x] `npm run e2e` passes locally against `docker compose up` or `npm start` +
|
||||
`dotnet run` run manually.
|
||||
- [ ] CI job `e2e` is green and runs on every PR alongside the existing jobs.
|
||||
- [ ] The happy-path spec exercises a real wizard submit against the real backend
|
||||
- [x] CI job `e2e` is green and runs on every PR alongside the existing jobs.
|
||||
- [x] The happy-path spec exercises a real wizard submit against the real backend
|
||||
(not mocked) and asserts on the resulting UI state.
|
||||
- [ ] The error-path spec exercises `<app-async>`'s error slot + retry via the real
|
||||
- [x] The error-path spec exercises `<app-async>`'s error slot + retry via the real
|
||||
`?scenario=error` toggle, not a mocked HTTP response.
|
||||
|
||||
## Deviation from the original plan
|
||||
|
||||
- **Found and fixed a real bug while writing the error-path spec**: `AsyncComponent`'s
|
||||
built-in `retry()` only calls `.reload()` on a `[resource]` input — every real page
|
||||
(`dashboard`, `registration-detail`, `aanvraag-detail`, `brief`) feeds `<app-async>`
|
||||
via `[data]` (a store's combined `RemoteData`), so clicking "Opnieuw proberen" was a
|
||||
silent no-op everywhere except the showcase teaching page. Added a `retryClicked`
|
||||
output that fires regardless of feed mode, and wired the two dashboard instances
|
||||
(`BigProfileStore.reloadProfile()`/`reloadAantekeningen()`) since that's what this
|
||||
WP's spec exercises. **Not fixed**: `registration-detail`, `aanvraag-detail`, and
|
||||
`brief` pages still have the same latent no-op retry — same "found via testing,
|
||||
fixing the whole surface is beyond this WP" call as WP-17's dashboard CSS finding.
|
||||
Flagging here so it isn't lost.
|
||||
- Confirmed `currentScenario()` reads `window.location.search` fresh on every call —
|
||||
the error-path spec's retry assertion had to change from "counts a browser network
|
||||
request" (the scenario interceptor never reaches the real transport; it substitutes
|
||||
`throwError` in the rxjs pipe before `next(req)`) to "observes a real Loading→Failure
|
||||
reload cycle via `aria-busy`". The Steps section's literal suggestion ("assert it
|
||||
re-fetches... via a network tab") didn't hold; adapted per the WP's own Risks note
|
||||
to verify actual interceptor behavior first.
|
||||
- Verified the suite isn't a no-op per the Verification section: temporarily broke
|
||||
`diplomaOptions`' `value: d.id` (appended `-x`), watched `smoke.spec.ts` fail on the
|
||||
now-missing `#diploma-d1` selector, reverted.
|
||||
- The registratie wizard's minimum path needed an actual file upload (`identiteit` is
|
||||
always required for `registratie` regardless of diploma choice, per
|
||||
`DocumentRules.CategoriesFor` — only `diploma`/`taalvaardigheid` are answer-gated).
|
||||
Picked the first DUO diploma (non-English, `Engelstalig: false`) specifically because
|
||||
it carries zero policy questions, keeping the happy path to one upload.
|
||||
- CIBG-styled radios hide the native `<input>` behind its `<label>` — Playwright's
|
||||
`.check()` on the input times out fighting the label for pointer events; the specs
|
||||
click the `label[for=...]` instead (also more representative of a real click).
|
||||
|
||||
## Verification
|
||||
|
||||
`npm run e2e` locally; then push a branch and confirm the new `e2e` CI job appears
|
||||
|
||||
Reference in New Issue
Block a user