docs: Sprint 14 — Vitest for useOnboarding (Q4) across all 6 running docs

Sprint 14 (commit 28f3212) adds Vitest + happy-dom +
@testing-library/react + @testing-library/jest-dom as
devDeps and locks the useOnboarding state-transition
contract with 7 unit tests in 25 ms. Lifts the 'no new
npm deps' rule for testing-only. Runtime bundle unchanged
(503.82 kB). No pre-existing WIP files touched.

Sprint 9's bug 1562929 (onComplete wired to .reset, the
inverse op) shipped a post-deploy fix the same day.
Sprint 14 prevents recurrence at npm test time.

This commit updates the 6 running docs that track sprints:

- .agent/plan.md — header changed to 'Active sprint: Sprint
  14'; Sprint 14 section (S14.1-S14.4 + Done when + Out of
  scope) added after the Sprint 13 section.
- .agent/context.md — Sprint 14 decisions (D1-D7), open Q1,
  and file:line references added.
- Review/sprint14-verification.md — NEW: deploy + 7-case
  test table + verification commands + Case 7 S9-bug-catch
  proof + 5-risk table + open Q1 (component-level tests).
- Review/ui-nielsen-audit.md — Sprint 14 status block
  (T7.1-T7.3) added after the Sprint 13 block.
- fix-ui-audit.md — Sprint 14 section (T7.1-T7.5) added
  after the Sprint 13 section.
- Review/handoff-ui-audit.md — Batch J line in deploy
  list, Sprint 14 section after Sprint 13, TL;DR Sprint
  14 line, Last-updated footer updated. (Did NOT replace
  the Sprint 7/8/TL;DR/environment-quirks/active-risks
  content that was at the bottom of the file — that
  material is preserved unchanged.)
- docs/HANDOFF.md — Sprint 14 section added after Sprint
  13, Last-updated footer updated.

All 6 docs now reflect Sprint 14. §Future backlog
remaining: F9-full (local Ollama model pull on the host).
Q4 (Vitest) is now closed. Sprint 14 is the smallest
sprint in the cycle (devDeps + 1 test file + 2 config
files + 2 scripts) and the first that adds a test
infrastructure layer.
This commit is contained in:
2026-06-05 17:30:00 -07:00
parent 28f321298f
commit af4ec793c7
7 changed files with 287 additions and 6 deletions
+52
View File
@@ -749,3 +749,55 @@ User direction 2026-06-05: "Proceed." F9-lite reuses the pre-existing `OLLAMA_*`
### T7.5 · `Review/sprint13-verification.md` (NEW)
- Deploy + 3-step browser smoke + 4 API curls + a11y check + 6-risk table + future work section. Source of truth for the operator deploy + smoke flow.
---
## Sprint 14 — Vitest for `useOnboarding` (Q4) — 🚧 IN PROGRESS
**Why this sprint:** Sprint 9 (F1 Onboarding Tour) shipped a hand-rolled ~420-line component; the bug `1562929` shipped a post-deploy fix the same day (`onComplete` was wired to `useOnboarding().reset()` — the inverse op, so the X/Skip/Esc dismiss path re-showed the tour). Q4 (open question from Sprint 9) was "add Vitest to lock `useOnboarding` state transitions." Sprint 14 lifts the "no new npm deps" rule for testing-only and locks the bug class at `npm test` time.
### T7.1 · Frontend devDeps (4 new + 1 for tsc)
- **`vitest@^1.6.0`** — the runner. Uses Vite's plugin-react under the hood, so it reuses the existing `vite.config.ts`-style config (no parallel build pipeline).
- **`happy-dom@^14.7.0`** — DOM env. Lighter than jsdom (7x smaller), faster startup. Sufficient for hooks-only tests.
- **`@testing-library/react@^14.2.0`** — `renderHook` + `act` for the `useOnboarding` test.
- **`@testing-library/jest-dom@^6.4.0`** — DOM matchers (loaded via the `/vitest` entry, not the `/jest` entry).
- **`@types/node@^20`** — tsc needed this for the `node:fs/promises` import in Case 7's static check on `App.tsx`.
All five go under `devDependencies`. Runtime bundle size unchanged (503.82 kB before/after).
### T7.2 · Vitest config + setup
- **`frontend/vitest.config.ts` (NEW):** `defineConfig` from `vitest/config` (extends Vite's config). `plugins: [react()]` reuses the existing React plugin. `test.environment: 'happy-dom'`, `test.setupFiles: ['./vitest-setup.ts']`, `test.include: ['src/**/*.test.{ts,tsx}']`, `test.globals: false` (explicit imports preferred over magic globals).
- **`frontend/vitest-setup.ts` (NEW):** a single line: `import '@testing-library/jest-dom/vitest'`. The `/vitest` entry auto-extends `expect` with DOM matchers.
- **`package.json` scripts:** `test``vitest run --reporter=default` (no watch by default — CI-friendly). `test:watch``vitest`.
### T7.3 · `OnboardingTour.test.tsx` — 7 cases
**File:** `frontend/src/components/OnboardingTour.test.tsx` (NEW, ~115 lines).
| # | Case | What it locks |
|---|------|---------------|
| 1 | clean init | `isComplete === false` when localStorage is empty |
| 2 | persisted init | `isComplete === true` when `localStorage.getItem(KEY) === '1'` |
| 3 | `markComplete` | state → true, localStorage **stays** at `'1'` (locks one direction of the S9 bug) |
| 4 | `reset` | localStorage cleared, state → false |
| 5 | `show` | identical to `reset` (intentional mirror) |
| 6 | localStorage throw on read | silently swallowed, `isComplete === false`, no crash |
| 7 | App.tsx wiring | static check on `App.tsx` source: `onComplete` calls `markComplete`, `onReset` calls `reset`; neither inverts (catches the original S9 bug `onComplete → reset` at the call site, which Cases 1-6 cannot catch because the bug was at the wiring, not in the hook) |
**Test runtime:** 7 cases pass in ~25 ms (transform 60 ms, setup 50 ms, collect 230 ms).
**Why Case 7 is the load-bearing test:** Sprint 9's bug `1562929` was at the App.tsx call site (`onComplete={() => onboarding.reset()}`), not inside `useOnboarding`. Cases 1-6 lock the hook contract; Case 7 is the only check that catches the wiring mistake. The integration check uses `node:fs/promises` to read `App.tsx` as a string, runs two regex matches to capture the arrow bodies of `onComplete={...}` and `onReset={...}`, and asserts each body calls the right `onboarding.*` method. Verified: flipping `markComplete``reset` in App.tsx makes Case 7 fail on the `onCompleteBody.toMatch(/markComplete/)` assertion.
### T7.4 · Sprint 14 verification gate
- [x] `npm test` — 7/7 cases pass in ~25 ms.
- [x] `npm run build` — tsc 0 errors, vite built in ~2.6 s, bundle 503.82 kB unchanged.
- [x] Case 7 catches the S9 bug — verified by inverting the wiring in `App.tsx` and watching Case 7 fail.
- [x] Backend untouched (no venv dependency).
- [ ] Commit on host + push.
### T7.5 · `Review/sprint14-verification.md` (NEW)
- Deploy + test commands + 5-risk table + open question for follow-up (Q1: component-level tests for `<OnboardingTour/>` itself, future sprint).