16 KiB
Phase 2 Frontend Tests Design Specification
Date: 2026-04-18
Status: APPROVED
Target: 80%+ coverage for frontend components, hooks, utilities
Branch: refactor/ai-friendly
Reference: Phase 1 Backend Tests (TDD pattern, subagent-driven execution)
1. Overview
Phase 2 creates a comprehensive Vitest test suite for the aInventory frontend, mirroring the TDD approach and execution patterns from Phase 1 (backend tests). The goal is to establish 80%+ coverage across 9 test files: 4 component suites, 3 utility/hook suites, and 2 integration workflows.
Key Alignment with Phase 1:
- Test infrastructure first (setup.ts ≈ conftest.py)
- Balanced unit + integration testing
- Shared fixtures to avoid duplication
- Subagent-driven execution (batches of 2-3 files)
- Git tags for phase completion & rollback
2. Test Architecture & Setup
2.1 File Structure
frontend/tests/
├── setup.ts # Vitest config, shared mocks, fixtures
├── components/
│ ├── Scanner.test.tsx # QR scan + OCR matching
│ ├── AIOnboarding.test.tsx # AI extraction wizard
│ ├── AdminOverlay.test.tsx # Admin config UI
│ └── IdentityCheckOverlay.test.tsx # Login form
├── hooks/
│ └── useAdmin.test.ts # Admin state hook
├── lib/
│ ├── api.test.ts # Axios + retry logic
│ └── labels.test.ts # SVG/QR generation
└── integration/
├── scanner-workflow.test.tsx # Scan → match → adjust
└── inventory-workflow.test.tsx # View → filter → create → sync
2.2 Setup.ts (Shared Fixtures & Mocks)
Purpose: Centralized Vitest configuration and reusable mock fixtures (analogous to Phase 1's conftest.py)
Contents:
- Vitest globals — enable
describe,it,expectwithout imports - vi.mock() calls for:
axios— stub GET/POST/PUT with fixed responsesdexie— in-memory IndexedDB replacementhtml5-qrcode— stub camera access (requestPermission, scan)next/router— stub Next.js routing
- Shared fixtures:
- Mock user token (valid + invalid variants)
- Mock item list response (5 items with various states)
- Mock AI extraction response (Gemini + Claude formats)
- Mock offline sync queue
- Cleanup: Reset mocks before each test
Philosophy:
- Same fixtures reused across all 9 test files
- Test-specific overrides allowed (e.g.,
vi.spyOn(axios, 'post').mockReturnValue(...)) - Reduces boilerplate, ensures consistency
2.3 Vitest Configuration (vitest.config.ts)
Setup:
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./tests/setup.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
all: true,
lines: 80,
functions: 80,
branches: 80,
statements: 80,
},
},
})
Key Settings:
environment: 'jsdom'— simulate browser for React componentssetupFiles— load shared mocks before tests- Coverage thresholds: 80%+ across all metrics (lines, functions, branches, statements)
2.4 Package.json Updates
Add dependencies:
{
"devDependencies": {
"vitest": "^1.0.0",
"@vitest/ui": "^1.0.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.0.0",
"@testing-library/jest-dom": "^6.0.0",
"@vitejs/plugin-react": "^4.0.0",
"jsdom": "^23.0.0"
}
}
Test scripts:
{
"scripts": {
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage"
}
}
3. Component Tests (4 Files)
3.1 Scanner.test.tsx
What it tests:
- Viewport rendering (video element, canvas overlay)
- Zoom controls (1x → 2x → max cycle)
- OCR matching engine (scoring, threshold logic)
- Camera permission flows
- State updates on scan result
Test Types:
- Unit: Zoom logic, matching score calculation, error handling
- Integration: Real component tree, mocked camera, verify state callbacks
Coverage Targets:
- Render paths: initial + error states
- Zoom cycle: all 4 states (1x, 2x, max/2, max)
- Matching: exact match (500pts), partial (200pts), token (50pts), category (20pts), threshold (40pts)
- Callbacks: onScanResult, onError
Key Mocks:
html5-qrcode— stub camera access, return fixed QR/barcode string- Component props — onScanResult callback verification
3.2 AIOnboarding.test.tsx
What it tests:
- Step progression (image capture → extraction → confirmation)
- Image preprocessing (validation, resize, crop, filter)
- AI response formatting (Gemini vs Claude)
- User validation of extracted data
- Form submission
Test Types:
- Unit: Step validation, data transformation, error messages
- Integration: Full wizard flow, mocked AI response, verify final submit
Coverage Targets:
- Step transitions: capture → extraction → confirm → done
- Image validation: size, format, EXIF handling
- AI response parsing: field mapping, confidence scores
- User override: edited fields on confirmation step
- Submit: API call with validated data
Key Mocks:
axios.post('/ai/extract')— return mock Gemini/Claude response- Canvas API — image preprocessing simulation
3.3 AdminOverlay.test.tsx
What it tests:
- Tab rendering (Identity, Database, LDAP, AI, Categories)
- Form field validation (required, format, length)
- Form submission with mocked API
- Error message display
- Loading states
Test Types:
- Unit: Field validation, error rendering, tab switching
- Integration: Full form submission, mock API response, state update
Coverage Targets:
- Tab rendering: all 5 tabs present and switchable
- Form validation: required fields, format validation, error messages
- Submission: API call with payload, success/error handling
- Loading state: button disabled, spinner visible during submission
Key Mocks:
axios.put('/admin/config')— mock successful + error responses- Form fields — controlled component rendering
3.4 IdentityCheckOverlay.test.tsx
What it tests:
- Login form rendering (username, password, login button)
- Form validation (required fields)
- LDAP authentication flow
- Local password authentication fallback
- Token storage and success callback
Test Types:
- Unit: Form validation, error handling
- Integration: Login flow, mocked auth endpoint, token storage
Coverage Targets:
- Form fields: username + password required
- Validation: empty field errors
- LDAP login: POST to
/auth/loginwith credentials - Success: token stored, onLoginSuccess callback fired
- Error: error message displayed, form remains editable
Key Mocks:
axios.post('/auth/login')— mock LDAP response with JWT token- localStorage — in-memory token storage
4. Hook & Utility Tests (3 Files)
4.1 useAdmin.test.ts
What it tests:
- Hook initialization (load config from API)
- State updates (identity, DB, LDAP, AI, categories)
- Validation before submission
- Error handling and retry logic
Test Types:
- Unit: State mutations, validation logic
- Integration: API calls (mocked), state persistence
Coverage Targets:
- Initialization: load admin config on mount
- State updates: each config section (identity, LDAP, AI, etc.)
- Validation: required fields, format checks
- Submission: API call with validated payload
- Error states: network failure, validation error, server error
Key Mocks:
axios.get('/admin/config')— return mock config objectaxios.put('/admin/config')— mock success + error responses
4.2 api.test.ts
What it tests:
- Axios instance configuration (base URL, headers, auth)
- Request construction (query params, body, headers)
- Retry logic for network failures
- Response parsing and error mapping
- Token refresh on 401
Test Types:
- Unit: Request building, error mapping, retry logic
- Integration: Mocked axios, verify request/response flow
Coverage Targets:
- Auth headers: JWT token in Authorization header
- Request types: GET, POST, PUT, DELETE
- Query params: proper URL encoding
- Retry: exponential backoff on network error
- Error mapping: HTTP status → human-readable error message
- Token refresh: 401 triggers new login flow
Key Mocks:
axios— intercept requests, mock responses
4.3 labels.test.ts
What it tests:
- SVG Code 128 barcode generation
- SVG QR code generation (no external library)
- Canvas-to-PNG rasterization (browser export)
- Label dimension validation (62mm x 29mm)
Test Types:
- Unit: SVG encoding, QR structure validation
- Integration: Canvas API, image export
Coverage Targets:
- Code 128 encoding: valid barcode structure
- QR generation: valid QR format
- SVG output: valid XML structure, correct dimensions
- Canvas export: PNG blob generation
- Error handling: invalid input, encoding errors
Key Mocks:
- Canvas API — stub createImageData, getContext
5. Integration Tests (2 Files)
5.1 scanner-workflow.test.tsx
What it tests:
- End-to-end: Scan QR/barcode → OCR match → select item → stock adjustment
- Real component tree: Scanner + ItemList + StockAdjustmentForm
- Mocked: html5-qrcode, axios (item API, stock update API)
User Journey:
- Scanner displays, user clicks "Scan"
- html5-qrcode stub returns barcode string
- Matching engine finds item (exact or partial match)
- Item details displayed in form
- User adjusts quantity, clicks "Check In"
- API updates stock, success message shown
Coverage Targets:
- Scan trigger → match → form population
- User interaction: quantity adjustment, submission
- API integration: stock update call
- Error handling: no match found, network error
Key Mocks:
html5-qrcode— return fixed barcode on scanaxios.get('/items')— return mock item listaxios.post('/operations/checkin')— mock success response
5.2 inventory-workflow.test.tsx
What it tests:
- End-to-end: View inventory → filter/sort → create new item → offline sync
- Real component tree: Dashboard + ItemTable + CreateItemModal + SyncStatus
- Mocked: axios (all API calls), Dexie (IndexedDB for offline queue)
User Journey:
- Dashboard loads, displays item list from API
- User filters by category, sorts by quantity
- User clicks "Create Item", fills form, submits
- Network goes offline (axios fails)
- Item queued in IndexedDB (offline sync)
- Network comes back online
- Sync button triggers, offline items sent to backend
- Item list updates
Coverage Targets:
- Data loading: initial list from API
- Filter/sort: UI updates, no API call
- Create item: form submission, success message
- Offline queue: Dexie stores pending items
- Sync: batch API call for offline items, success/error handling
Key Mocks:
axios.get('/items')— return mock inventoryaxios.post('/items')— handle create + batch syncDexie.table('pending_operations')— in-memory queue
6. Execution Plan (Subagent-Driven)
6.1 Batch 1: Scanner Foundation (Tests 1-2)
Files: setup.ts, Scanner.test.tsx
Tasks:
- Create
frontend/tests/setup.tswith Vitest config, shared mocks (axios, html5-qrcode, Dexie, next/router) - Create
frontend/tests/components/Scanner.test.tsxwith unit + integration tests - Run
npm test -- --coverageand verify 80%+ on Scanner module
Roles:
- Implementer: Write setup + Scanner tests
- Reviewer 1: Validate mock fixtures align with Phase 1 patterns
- Reviewer 2: Verify test coverage (render, zoom, matching, callbacks)
Success Criteria:
- setup.ts exports fixtures and vi.mock() setup
- Scanner tests cover all paths (unit + integration)
npm test -- --coverageshows 80%+ on Scanner module- All tests passing, no console errors
Commit: test: setup vitest and create Scanner test suite
6.2 Batch 2: AIOnboarding & Hooks (Tests 3-5)
Files: AIOnboarding.test.tsx, useAdmin.test.ts, api.test.ts
Tasks:
- Create
frontend/tests/components/AIOnboarding.test.tsx— step progression, AI response parsing - Create
frontend/tests/hooks/useAdmin.test.ts— state management, form submission - Create
frontend/tests/lib/api.test.ts— request building, retry logic, error mapping
Roles:
- Implementer: Reuse Batch 1 fixtures, write 3 test files
- Reviewer 1: Ensure consistent mock usage across files
- Reviewer 2: Verify 80%+ coverage on all 3 modules
Success Criteria:
- All 3 test files created
- Reuse setup.ts fixtures (no duplication)
npm test -- --coverageshows 80%+ on AIOnboarding, useAdmin, api- All tests passing
Commit: test: add AIOnboarding, useAdmin, api test suites
6.3 Batch 3: Admin & Utilities (Tests 6-7)
Files: AdminOverlay.test.tsx, labels.test.ts
Tasks:
- Create
frontend/tests/components/AdminOverlay.test.tsx— tab rendering, form validation, submission - Create
frontend/tests/lib/labels.test.ts— barcode/QR generation, canvas export
Roles:
- Implementer: Write 2 test files
- Reviewer 1: Validate form field coverage (5 tabs, validation logic)
- Reviewer 2: Verify SVG/canvas test patterns
Success Criteria:
- Both test files created
- AdminOverlay covers all 5 tabs + form submission
- labels.ts covers Code 128, QR, canvas export
npm test -- --coverageshows 80%+ on both modules
Commit: test: add AdminOverlay and labels test suites
6.4 Batch 4: Identity & Integration (Tests 8-9)
Files: IdentityCheckOverlay.test.tsx, scanner-workflow.test.tsx, inventory-workflow.test.tsx
Tasks:
- Create
frontend/tests/components/IdentityCheckOverlay.test.tsx— login form, LDAP flow, token storage - Create
frontend/tests/integration/scanner-workflow.test.tsx— scan → match → adjust - Create
frontend/tests/integration/inventory-workflow.test.tsx— view → filter → create → sync
Roles:
- Implementer: Write 3 test files
- Reviewer 1: Validate login flow coverage (LDAP, error states)
- Reviewer 2: Verify integration test patterns (real component tree, mocked API)
Success Criteria:
- All 3 test files created
- IdentityCheckOverlay covers login + error states
- scanner-workflow covers end-to-end scan flow
- inventory-workflow covers CRUD + offline sync
npm test -- --coverageshows 80%+ on all modules
Commit: test: add IdentityCheckOverlay and integration test suites
6.5 Phase Completion
Tasks:
- Run full test suite:
npm test -- --coverage - Verify 80%+ coverage across all files
- Create git tag:
phase-2-complete - Update
SESSION_STATE.mdwith Phase 2 status - Update
REFACTORING_PROGRESS.md(mark Phase 2 ✅)
Success Criteria:
- All 9 test files created and passing
- Coverage report: 80%+ on all metrics (lines, functions, branches, statements)
- No console errors or warnings
- Git tag
phase-2-completecreated
Commit: docs: mark phase 2 complete - frontend test suite at 80%+ coverage
7. Success Metrics
| Metric | Target | Status |
|---|---|---|
| Test files created | 9 | ⏳ |
| Total test cases | 100+ | ⏳ |
| Coverage (lines) | 80%+ | ⏳ |
| Coverage (functions) | 80%+ | ⏳ |
| Coverage (branches) | 80%+ | ⏳ |
| All tests passing | Yes | ⏳ |
| No console errors | Yes | ⏳ |
Git tag phase-2-complete |
Yes | ⏳ |
8. Dependencies & Pre-requisites
- Phase 1 (Backend Tests) ✅ COMPLETE
- Vitest installed (v1.0.0+)
- @testing-library/react installed
- jsdom (React component testing environment)
- Git tag
phase-1-completeavailable for rollback
9. Rollback Plan
If Phase 2 encounters critical issues:
# Rollback to Phase 1 completion
git reset --hard phase-1-complete
# Delete Phase 2 tags
git tag -d phase-2-complete
# Resume when ready
git checkout refactor/ai-friendly
10. Next Phase (Phase 3)
After Phase 2 completion:
- Create
docs/superpowers/plans/2026-04-18-phase-3-e2e-tests.md - Add Playwright E2E tests for critical workflows (login, scan, create item, offline sync, admin settings)
- Target: 5+ workflows automated, <30 min runtime