One-time prettier --write so the new format:check CI gate starts green. .prettierignore excludes generated (api-client.ts, documentation.json), vendored (public/cibg-huisstijl), and backend (dotnet format owns it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
3.6 KiB
Markdown
81 lines
3.6 KiB
Markdown
# WP-01 — Axe-on-every-story CI gate
|
|
|
|
Status: done (97f7de4)
|
|
Phase: 0 — enforcement & gates
|
|
|
|
## Why
|
|
|
|
The Storybook a11y addon (`@storybook/addon-a11y`, configured in `.storybook/preview.ts`
|
|
for `wcag2a, wcag2aa, wcag21a, wcag21aa`) only surfaces violations _interactively_.
|
|
Nothing gates CI. This WP turns "a panel you can look at" into "a check that fails the
|
|
build", so every story added or changed by later WPs is automatically covered.
|
|
|
|
## Read first
|
|
|
|
- `.storybook/main.ts`, `.storybook/preview.ts` (existing a11y config — reuse its tags)
|
|
- `.github/workflows/ci.yml` (job layout to extend)
|
|
- `package.json` (scripts; note `.npmrc` has `legacy-peer-deps=true`)
|
|
|
|
## Decisions (pre-made, don't relitigate)
|
|
|
|
- Mechanism: **`@storybook/test-runner` + `axe-playwright`** against the static build.
|
|
The repo uses `@storybook/angular` on the **webpack** builder, which rules out
|
|
`@storybook/addon-vitest` (Vite-only). Fallback if test-runner doesn't support
|
|
Storybook 10 yet: a hand-rolled Playwright + `axe-core` loop over `storybook-static`
|
|
(same gate semantics — document the swap in this file if taken).
|
|
- Escape hatch: `parameters: { a11y: { disable: true } }` per story, allowed **only** with
|
|
an inline justification comment and a cross-reference to the WP that will fix it
|
|
(WP-16/WP-17).
|
|
|
|
## Files
|
|
|
|
- `package.json` (devDependencies + scripts)
|
|
- `.storybook/test-runner.ts` (new)
|
|
- `.github/workflows/ci.yml` (new job)
|
|
- Possibly a handful of story/component files for triaged violations
|
|
|
|
## Steps
|
|
|
|
1. Check version fit first: `npm view @storybook/test-runner peerDependencies` and pick
|
|
the release matching the installed Storybook 10 (`legacy-peer-deps` absorbs minor lag).
|
|
2. `npm i -D @storybook/test-runner axe-playwright http-server wait-on concurrently`
|
|
(+ `npx playwright install chromium` locally).
|
|
3. `.storybook/test-runner.ts`:
|
|
- `preVisit`: `injectAxe(page)`.
|
|
- `postVisit`: `getStoryContext(page, context)`; skip when
|
|
`parameters.a11y?.disable === true`; else `checkA11y(page, '#storybook-root', …)`,
|
|
honoring `parameters.a11y.config`/`options.runOnly` from `preview.ts` (don't
|
|
duplicate the tag list — read it from the story context).
|
|
4. Scripts:
|
|
- `"test-storybook": "test-storybook"`
|
|
- `"test-storybook:ci": "concurrently -k -s first -n sb,axe \"http-server storybook-static -p 6006 --silent\" \"wait-on tcp:127.0.0.1:6006 && test-storybook --url http://127.0.0.1:6006\""`
|
|
5. CI job `storybook-a11y` in `ci.yml`: checkout → setup-node (same version as the
|
|
`frontend` job) + npm cache → `npm ci` → `npx playwright install --with-deps chromium`
|
|
→ `npm run build-storybook` → `npm run test-storybook:ci`.
|
|
6. Run locally against a fresh `build-storybook`; triage violations: fix trivial ones
|
|
(labels, roles, contrast via `--rhc-*` tokens); anything structural gets the escape
|
|
hatch + comment + WP cross-ref.
|
|
7. Update `docs/backlog/README.md`: GREEN now includes `npm run test-storybook:ci`.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] `npm run test-storybook:ci` passes locally against a fresh `storybook-static/`.
|
|
- [x] CI has a `storybook-a11y` job; an axe violation makes it fail (verified once with a
|
|
deliberately broken story, then reverted).
|
|
- [x] Every `a11y.disable` skip carries a justification comment + WP cross-ref.
|
|
- [x] Backlog README GREEN updated.
|
|
|
|
## Verification
|
|
|
|
GREEN + `npm run test-storybook:ci`.
|
|
|
|
## Out of scope
|
|
|
|
Fixing structural a11y issues in components (WP-16/WP-17); Playwright e2e page sweeps
|
|
(explicitly not chosen).
|
|
|
|
## Risks
|
|
|
|
- test-runner ↔ Storybook 10 peer mismatch → use the documented fallback.
|
|
- Unknown violation count on first run → the escape hatch keeps the WP bounded.
|