5.3.8 Story tests — Vitest matrix (types × validation × permissions × lifecycle) + Playwright E2E (define → set → history → delete) + a11y sweep
Estimate: 30m · Depends on: 5.3.6, 5.3.7
The story-closing verification (Principle #18; the 5.1.7/5.2.8 split — epic-wide journeys stay Story 5.6).
Vitest (integration, real Postgres): the full matrix — five types × (valid set / invalid set / clear / re-set) with the per-type edge cases (decimal scale, UTC date boundary, archived-option new-write rejection, non-viewable user, text cap); definition lifecycle (create → rename → reorder → delete-with-values, cascades verified); option lifecycle (archive keeps values renderable; delete blocked in-use at BOTH service and DB layers; delete-when-unused); the 50/55 caps; the permission matrix (project admin / member / viewer / cross-workspace) over definitions AND values; revision diffs (customFields.<key>) written per change.
Playwright E2E (tests/e2e/custom-fields.spec.ts): as the PM — create the five fields (Severity select w/ options, Customer text, Effort number, Go-live date, Stakeholder user) in settings; open an issue → set each type inline (date via the DatePicker grid, select via Combobox, user via the member picker keyboard path); reload → values persist; the History/revision data shows the changes; "Show more fields" discloses the still-empty ones; archive an option → gone from the picker, still rendered on the holding issue; delete Severity → the confirm names the count, the rail card disappears. Role pass: non-admin member gets read-only settings; viewer gets read-only rail. Run against the standing dev-server harness.
Strict a11y sweep: the Fields settings page + the detail rail with editors open pass the strict axe config (extends the settings + 2.4.6 sweeps).
Acceptance criteria
- The Vitest matrix covers every cell above;
pnpm test:coveragekeeps all 5.3 files ≥90% branch/fn/line. custom-fields.spec.tspasses the define → set-each-type → persist → archive/delete journey + both role passes, green in CI's Playwright lane (selector gotchas: Combobox option names include secondary text — match substrings).- The strict axe sweep over both surfaces reports zero violations.
- The Story 5.3 verification recipe runs clean top to bottom; shared-DB flake isolation respected.
Context refs
tests/integration/+tests/e2e/conventions; the E2E selector-gotcha + harness memories (standing dev server; Combobox names)- The 5.1.7/5.2.8 story-test shape (the split vs Story 5.6)
- The Story 5.3 verification recipe — the checklist this automates
- The strict-a11y sweep configs (settings + detail routes)