You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ai_synth/docs/superpowers/specs/2026-03-22-test-coverage-do...

10 KiB

Design: Test Coverage & Documentation Improvements

Date: 2026-03-22 Source: docs/tech_lead_assessment_Coverage_Documentation.md Scope: 5 improvements — frontend page tests, frontend JSDoc, backend test gaps, E2E tests


Context

The tech lead assessment graded the backend A (332 unit + 145 integration tests, good documentation) and the frontend C (103 utility/API tests only, weak documentation). Every page and component has zero test coverage. This design addresses all 5 recommendations from the assessment.


1. Frontend Component/Page Tests

Goal

Add interaction-level tests for the 5 most critical pages using @solidjs/testing-library + Vitest + MSW.

Test Infrastructure

  • MSW (Mock Service Worker) to intercept fetch calls in tests
  • Shared test-utils.ts with a renderWithProviders() helper that wraps components in AuthContext, I18nProvider, ToastProvider, and Router
  • Mocked Turnstile — stub window.turnstile in test setup
  • Mocked EventSource — stub for SSE tests in GenerateSynthesis

Pages and Tests (~39 tests)

Settings.tsx (~10 tests)

  • Renders form with all fields populated from API response
  • Save button calls PUT /settings with form data
  • Provider dropdown populated from config API
  • Selecting provider updates model dropdown options
  • Dual model dropdowns render (research + writing)
  • Rate limit section renders with null values (empty inputs)
  • Rate limit section shows effective rate when values set
  • Reset link clears rate limit fields to null
  • Export downloads JSON file
  • Import populates form from uploaded JSON

Home.tsx (~7 tests)

  • Renders synthesis list from API response
  • Empty state shows when no syntheses
  • "Nouvelle Synthese" button links to /generate
  • Delete first click shows "Confirmer" state
  • Delete second click removes synthesis from list
  • Delete auto-cancels after 3 seconds
  • In-progress banner shows when a synthesis has status "in_progress"

Sources.tsx (~8 tests)

  • Renders source list from API response
  • Empty state shows when no sources
  • Add form validates empty title/URL
  • Add form submits and new source appears in list
  • Delete with confirmation removes source
  • Bulk import textarea parses and imports
  • CSV export triggers download
  • CSV import triggers file picker

Login.tsx + Register.tsx (~8 tests)

  • Login renders email input and submit button
  • Login submit calls POST /auth/login
  • Login shows "check inbox" message on success
  • Login shows error on API failure
  • Resend button disabled during cooldown
  • Register renders email + display name + submit
  • Register submit calls POST /auth/register
  • Register shows confirmation on success

GenerateSynthesis.tsx (~6 tests)

  • Renders launch button with settings info
  • Launch button calls POST /syntheses/generate
  • Progress bar updates from SSE events
  • Step checklist shows done/in-progress/pending states
  • Completion redirects to synthesis detail
  • Error state shows retry button

Dependencies to Add

  • msw (dev dependency) for API mocking
  • No other new dependencies needed (@solidjs/testing-library already installed)

2. Frontend JSDoc Documentation

Goal

Add English JSDoc comments to all exported components, functions, and complex logic blocks. No code changes.

Scope

API Layer

  • api/client.ts — class purpose, CSRF strategy (X-Requested-With), credential handling (same-origin), 401 redirect behavior
  • api/auth.ts, api/settings.ts, api/sources.ts, api/syntheses.ts, api/admin.ts, api/config.ts, api/apiKeys.ts — brief JSDoc on each exported function

Pages (complex logic)

  • pages/Settings.tsx — export/import logic, provider auto-detection, rate limit null handling, dual model state management
  • pages/GenerateSynthesis.tsx — SSE state machine (idle -> connecting -> progress -> complete/error), step progression, reconnection, completion redirect timer
  • pages/Home.tsx — delete confirmation timer pattern (first click -> confirm state -> 3s auto-cancel)
  • pages/Sources.tsx — bulk import parsing, CSV import/export flow, URL normalization
  • pages/SynthesisDetail.tsx — email send flow, file download mechanism (Blob + anchor)
  • pages/Login.tsx, pages/Register.tsx — Turnstile lifecycle, resend cooldown timer
  • pages/AuthVerify.tsx — token extraction from URL, verification flow

Components

  • components/ApiKeyManager.tsx — key CRUD flow, show/hide toggle, test button
  • components/Turnstile.tsx — widget lifecycle, polling initialization, cleanup
  • components/Navbar.tsx — active route detection, admin link visibility
  • components/MobileMenu.tsx — escape key handler, backdrop click
  • components/Layout.tsx, components/AdminLayout.tsx — layout structure, sidebar nav
  • components/ErrorBoundary.tsx — error catching, retry mechanism
  • components/ui/Button.tsx — props interface, variant behavior (primary/secondary/danger)
  • components/ui/Toast.tsx — toast provider pattern, auto-dismiss timer
  • components/ui/LoadingSpinner.tsx — size/fullPage props

Utilities

  • utils/sse.ts — reconnection backoff logic (exponential, max 3 retries), event type parsing, cleanup
  • utils/dates.ts — date-fns locale configuration
  • utils/providers.ts — provider capability detection

Context

  • contexts/AuthContext.tsx — session check on mount, 401 handling, isAdmin derived signal

Style

  • Brief /** ... */ on exports
  • Inline // comments only for non-obvious logic (state machines, timers, edge cases)
  • No boilerplate comments on trivial code (simple getters, obvious props)

3. Backend Test Gaps

3a. Schema Builder Tests (services/llm/schema.rs) — 6 tests

  • test_schema_single_category — 1 category produces category_0 with correct item schema
  • test_schema_five_categories — 5 categories produce category_0 through category_4
  • test_schema_twenty_categories — max 20 categories all present
  • test_schema_special_characters — category names with accents, quotes, ampersands don't break JSON
  • test_schema_long_category_name — 200-char category name accepted
  • test_schema_item_structure — each category value is array of {title: string, url: string, summary: string}

3b. Auth Middleware Unit Tests (middleware/auth.rs) — 5 tests

  • test_valid_session_cookie_extracted — properly formatted cookie returns token
  • test_malformed_cookie_no_equals — cookie without = returns None
  • test_missing_cookie_header — no Cookie header returns Unauthorized
  • test_multiple_cookies_correct_one_picked — session cookie found among other cookies
  • test_cookie_with_whitespace — leading/trailing whitespace trimmed

3c. Token Utility Tests (util/token.rs) — 4 tests

  • test_generated_token_length — base64url-encoded token has expected length
  • test_tokens_are_unique — two consecutive generated tokens differ
  • test_hash_is_deterministic — same input produces same hash
  • test_hash_differs_from_raw — hash output is not the raw token

Total: 15 new backend unit tests, bringing count from 332 to ~347.


4. E2E Tests with Playwright

Infrastructure

e2e/docker-compose.test.yml:

  • Extends main docker-compose.yml
  • Uses a test-specific Postgres database (fresh per run)
  • App service with TEST_DATABASE_URL and test Turnstile/Resend keys
  • Exposes app on port 8080

e2e/seed.ts:

  • Node.js script connecting directly to test Postgres
  • Creates admin user (email_verified, role=admin) with a known session token
  • Creates regular test user with a known session token
  • Both sessions have 30-day expiry

e2e/helpers/auth.ts:

  • loginAsAdmin() — sets session cookie for admin
  • loginAsUser() — sets session cookie for regular user
  • registerAndVerify(email) — inserts magic link token in DB, navigates to verify URL
  • Direct DB access via pg npm package for token extraction

e2e/playwright.config.ts:

  • Base URL: http://localhost:8080
  • Timeout: 30s per test
  • Retries: 1
  • Screenshots on failure

Test Flows (5 specs)

registration.spec.ts

  • Navigate to /register
  • Fill email, submit (Turnstile bypassed via test key)
  • Extract magic link token from DB
  • Navigate to /auth/verify?token=...
  • Assert: redirected to Home, user email shown in navbar

admin-providers.spec.ts

  • Login as admin (cookie injection)
  • Navigate to /admin/providers
  • Enable Gemini provider, add a model
  • Save
  • Assert: provider appears in GET /config/providers response

settings.spec.ts

  • Login as user
  • Navigate to /settings
  • Change theme, select provider + models, save
  • Reload page
  • Assert: all saved values repopulated

sources.spec.ts

  • Login as user
  • Navigate to /sources
  • Add a source (title + URL)
  • Bulk import 3 sources
  • Assert: 4 sources in list
  • Delete one
  • Assert: 3 sources remain
  • Export CSV
  • Assert: downloaded file contains 3 rows

settings-export.spec.ts

  • Login as user
  • Configure settings (theme, categories, models)
  • Export JSON
  • Change settings to different values, save
  • Import the exported JSON
  • Save
  • Reload
  • Assert: original values restored

File Structure

e2e/
├── playwright.config.ts
├── docker-compose.test.yml
├── package.json              — playwright, pg dependencies
├── seed.ts
├── helpers/
│   └── auth.ts
└── tests/
    ├── registration.spec.ts
    ├── admin-providers.spec.ts
    ├── settings.spec.ts
    ├── sources.spec.ts
    └── settings-export.spec.ts

Summary

Section New Tests New Docs Effort
Frontend page tests ~39 Large
Frontend JSDoc ~30 files Medium
Backend test gaps ~15 Small
E2E tests ~5 flows Large
Total ~59 tests + 5 E2E flows ~30 files documented

Implementation Order

  1. Backend test gaps (small, independent, quick win)
  2. Frontend JSDoc (no code changes, can't break anything)
  3. Frontend page tests (requires MSW setup first, then tests)
  4. E2E tests (requires Docker test infrastructure, depends on everything else working)