# 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)