homelabby/.planning/phases/05-cable-test-integration/05-03-SUMMARY.md

4.5 KiB


phase: 05-cable-test-integration plan: "03" subsystem: frontend tags: [cable-test, ui, react, sse, vitest] dependency_graph: requires: [05-02] provides: [cable-test-ui, /test-route, test-api-helpers] affects: [web/src/router.tsx, web/src/components/layout/TopBar.tsx] tech_stack: added: [vitest, @testing-library/react, jsdom] patterns: [tanstack-query-mutation, sse-use-effect, three-panel-layout] key_files: created: - web/src/api/test.ts - web/src/pages/CableTestPage.tsx - web/src/pages/CableTestPage.test.tsx - web/vitest.config.ts - web/src/test/setup.ts modified: - web/src/router.tsx - web/src/components/layout/TopBar.tsx - web/package.json decisions:

  • Mock AppShell in tests to isolate from TanStack Router context dependency
  • streamTestEvents returns EventSource instance for caller-controlled teardown
  • Cable type selector as button group (not dropdown) for bench usability metrics: duration: "~10 minutes" completed: "2026-04-10T07:21:10Z" tasks_completed: 2 files_created: 5 files_modified: 3

Phase 05 Plan 03: Cable Test Station UI Summary

Three-panel Cable Test Station page at /test with SSE live readout, TanStack Query recent-tests list, Print & Next mutation workflow, and full Vitest unit test coverage.

Tasks Completed

# Name Commit Files
1 API helpers + Cable Test Station page 499dbb9 web/src/api/test.ts, CableTestPage.tsx, router.tsx, TopBar.tsx
2 Unit tests for CableTestPage 4e5a354 CableTestPage.test.tsx, vitest.config.ts, src/test/setup.ts, package.json

What Was Built

web/src/api/test.ts exports three typed helpers:

  • submitCableTest(result) — POST /api/test/cable, returns SubmitResponse
  • getRecentTests() — GET /api/test/recent, returns TestResult[]
  • streamTestEvents(onReading, onError?) — opens EventSource at /api/test/events, returns instance for caller-controlled close

web/src/pages/CableTestPage.tsx — three-column layout (single col on mobile via grid-cols-1 lg:grid-cols-3):

  • Left: ReadoutPanel — displays live voltage/current/power/protocol from SSE state, or "No tester connected"
  • Center: LabelPanel — controlled form for all TestResult fields, cable type toggle (USB/DP/HDMI), Print & Next button (bg-[#faff69]) that calls useMutation → submitCableTest, resets form on success
  • Right: RecentTestsPanel — useQuery with 5s refetchInterval, renders up to 20 rows with cable type icon, HW ID, continuity chip, speed

SSE lifecycle: useEffect opens EventSource on mount via streamTestEvents, cleanup calls es.close() on unmount (mitigates T-05-08).

All values rendered via React JSX (no dangerouslySetInnerHTML) — mitigates T-05-07.

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Installed missing Vitest test framework

  • Found during: Task 2
  • Issue: Plan stated "Vitest + RTL already in the project from Phase 3" but package.json had no test framework
  • Fix: Installed vitest, @testing-library/react, @testing-library/user-event, @testing-library/jest-dom, jsdom; created vitest.config.ts and src/test/setup.ts
  • Files modified: web/package.json, web/package-lock.json (new: vitest.config.ts, src/test/setup.ts)
  • Commit: 4e5a354

2. [Rule 1 - Bug] Mocked AppShell in tests to prevent TanStack Router crash

  • Found during: Task 2 (first test run)
  • Issue: AppShell renders TopBar which uses TanStack Router Link — requires router context that throws in test environment
  • Fix: Added vi.mock('@/components/layout/AppShell') rendering children-only div; added window.matchMedia stub for react-hot-toast Toaster
  • Files modified: CableTestPage.test.tsx, src/test/setup.ts
  • Commit: 4e5a354

Verification

npm run build   # exits 0 — CableTestPage-283Afuy4.js 13.20 kB
npm test -- --run CableTestPage   # 4/4 tests passed

Known Stubs

  • Live readout pre-population: SSE readings update the readout panel display only. Form fields (speed_gbps, max_watts etc.) are NOT auto-populated from live readings — real driver parsing is not yet implemented (per plan: "the test fields remain manual until real driver parsing is implemented"). The form starts blank and requires manual entry.

Self-Check: PASSED

Item Status
web/src/api/test.ts FOUND
web/src/pages/CableTestPage.tsx FOUND
web/src/pages/CableTestPage.test.tsx FOUND
commit 499dbb9 FOUND
commit 4e5a354 FOUND