Add test coverage and documentation implementation plan
12 tasks: backend auth middleware tests, frontend test utilities, 5 page test suites (Home, Settings, Sources, Login/Register, Generate), JSDoc for API layer + pages/components, E2E infrastructure + 5 Playwright flows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>master
parent
449edfcf59
commit
7b3fc717eb
@ -0,0 +1,553 @@
|
||||
# Test Coverage & Documentation Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Close the quality gaps identified in the tech lead assessment: add frontend page tests, JSDoc documentation, backend auth middleware tests, and E2E tests.
|
||||
|
||||
**Architecture:** Frontend tests use the existing Vitest + @solidjs/testing-library + manual fetch mocking pattern (no MSW — the existing `vi.fn()` pattern works well). Backend tests use inline `#[cfg(test)]` modules. E2E tests use Playwright against a Docker stack.
|
||||
|
||||
**Tech Stack:** Vitest, @solidjs/testing-library, Playwright, Rust #[cfg(test)], Docker
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-03-22-test-coverage-documentation-design.md`
|
||||
|
||||
**Note:** The spec called for schema.rs (6 tests) and token.rs (4 tests), but exploration revealed these already have 7 and 8 tests respectively. Only `middleware/auth.rs` (0 tests) remains as a backend gap.
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
### New Files
|
||||
- `frontend/src/__tests__/test-utils.tsx` — shared `renderWithProviders()` helper
|
||||
- `frontend/src/__tests__/pages/settings.test.tsx` — Settings page tests
|
||||
- `frontend/src/__tests__/pages/home.test.tsx` — Home page tests
|
||||
- `frontend/src/__tests__/pages/sources.test.tsx` — Sources page tests
|
||||
- `frontend/src/__tests__/pages/login.test.tsx` — Login page tests
|
||||
- `frontend/src/__tests__/pages/register.test.tsx` — Register page tests
|
||||
- `frontend/src/__tests__/pages/generate.test.tsx` — GenerateSynthesis page tests
|
||||
- `e2e/playwright.config.ts` — Playwright config
|
||||
- `e2e/package.json` — E2E dependencies
|
||||
- `e2e/docker-compose.test.yml` — test Docker stack
|
||||
- `e2e/seed.ts` — DB seed script
|
||||
- `e2e/helpers/auth.ts` — auth helpers
|
||||
- `e2e/tests/*.spec.ts` — 5 E2E test files
|
||||
|
||||
### Modified Files (documentation only — no logic changes)
|
||||
- `frontend/src/api/client.ts` — JSDoc
|
||||
- `frontend/src/api/auth.ts` — JSDoc
|
||||
- `frontend/src/api/settings.ts` — JSDoc
|
||||
- `frontend/src/api/sources.ts` — JSDoc
|
||||
- `frontend/src/api/syntheses.ts` — JSDoc
|
||||
- `frontend/src/api/admin.ts` — JSDoc
|
||||
- `frontend/src/api/config.ts` — JSDoc
|
||||
- `frontend/src/api/apiKeys.ts` — JSDoc
|
||||
- `frontend/src/pages/*.tsx` (all 11 pages) — JSDoc
|
||||
- `frontend/src/components/*.tsx` (all 10 components) — JSDoc
|
||||
- `frontend/src/utils/*.ts` (all 3 utils) — JSDoc
|
||||
- `frontend/src/contexts/AuthContext.tsx` — JSDoc
|
||||
- `backend/src/middleware/auth.rs` — unit tests added
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Backend Auth Middleware Unit Tests
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/src/middleware/auth.rs`
|
||||
|
||||
- [ ] **Step 1: Read the current cookie extraction logic**
|
||||
|
||||
Read `/Users/oabrivard/Projects/rust/ai_synth/backend/src/middleware/auth.rs` lines 34-81 to understand the `AuthUser::from_request_parts()` implementation. The cookie extraction is at lines 41-51.
|
||||
|
||||
- [ ] **Step 2: Write unit tests**
|
||||
|
||||
Add a `#[cfg(test)] mod tests` block at the bottom of `auth.rs`. Since the full `from_request_parts` requires a DB connection, test the cookie extraction logic as a standalone helper function. Extract the cookie parsing into a testable function if it isn't already:
|
||||
|
||||
```rust
|
||||
/// Extract session token from Cookie header value.
|
||||
/// Returns None if the session cookie is not found.
|
||||
fn extract_session_token(cookie_header: &str, cookie_name: &str) -> Option<String> {
|
||||
cookie_header
|
||||
.split(';')
|
||||
.map(|s| s.trim())
|
||||
.find(|s| s.starts_with(&format!("{}=", cookie_name)))
|
||||
.and_then(|s| s.strip_prefix(&format!("{}=", cookie_name)))
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const COOKIE_NAME: &str = "session";
|
||||
|
||||
#[test]
|
||||
fn test_valid_session_cookie_extracted() {
|
||||
let header = "session=abc123def";
|
||||
let result = extract_session_token(header, COOKIE_NAME);
|
||||
assert_eq!(result, Some("abc123def".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_session_cookie_returns_none() {
|
||||
let header = "other=value; another=thing";
|
||||
let result = extract_session_token(header, COOKIE_NAME);
|
||||
assert_eq!(result, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_cookies_correct_one_picked() {
|
||||
let header = "theme=dark; session=mytoken123; lang=fr";
|
||||
let result = extract_session_token(header, COOKIE_NAME);
|
||||
assert_eq!(result, Some("mytoken123".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cookie_with_whitespace_trimmed() {
|
||||
let header = " session=abc123 ; other=val ";
|
||||
let result = extract_session_token(header, COOKIE_NAME);
|
||||
assert_eq!(result, Some("abc123".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_cookie_header_returns_none() {
|
||||
let header = "";
|
||||
let result = extract_session_token(header, COOKIE_NAME);
|
||||
assert_eq!(result, None);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the current code already has a separate extraction function, add the tests to it. If the extraction is inline in `from_request_parts`, extract it first as shown above, then use it in `from_request_parts`.
|
||||
|
||||
- [ ] **Step 3: Run tests**
|
||||
|
||||
Run: `cd backend && cargo test --lib middleware`
|
||||
Expected: 5 new tests PASS
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
cd /Users/oabrivard/Projects/rust/ai_synth
|
||||
git add backend/src/middleware/auth.rs
|
||||
git commit -m "test: add unit tests for auth middleware cookie extraction"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Frontend Test Utilities
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/test-utils.tsx`
|
||||
|
||||
- [ ] **Step 1: Create shared test utilities**
|
||||
|
||||
```tsx
|
||||
import { render } from '@solidjs/testing-library';
|
||||
import { Router } from '@solidjs/router';
|
||||
import type { ParentComponent } from 'solid-js';
|
||||
import { I18nProvider } from '~/i18n';
|
||||
import { ToastProvider } from '~/components/ui/Toast';
|
||||
|
||||
/**
|
||||
* Wraps a component in all required providers for testing.
|
||||
* Includes: Router, I18nProvider, ToastProvider.
|
||||
* AuthContext is NOT included — mock it per-test as needed.
|
||||
*/
|
||||
export function renderWithProviders(ui: () => any) {
|
||||
return render(() => (
|
||||
<Router>
|
||||
<I18nProvider locale="fr">
|
||||
<ToastProvider>
|
||||
{ui()}
|
||||
</ToastProvider>
|
||||
</I18nProvider>
|
||||
</Router>
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock fetch that returns the given response for any call.
|
||||
* Resets between tests via afterEach.
|
||||
*/
|
||||
export function mockFetch(response: any, status = 200) {
|
||||
const fn = vi.fn().mockResolvedValue({
|
||||
ok: status >= 200 && status < 300,
|
||||
status,
|
||||
json: () => Promise.resolve(response),
|
||||
text: () => Promise.resolve(JSON.stringify(response)),
|
||||
headers: new Headers({ 'content-type': 'application/json' }),
|
||||
});
|
||||
globalThis.fetch = fn;
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock fetch that returns different responses per URL pattern.
|
||||
*/
|
||||
export function mockFetchRoutes(routes: Record<string, { body: any; status?: number }>) {
|
||||
const fn = vi.fn().mockImplementation((url: string) => {
|
||||
const match = Object.entries(routes).find(([pattern]) => url.includes(pattern));
|
||||
const { body, status } = match?.[1] ?? { body: {}, status: 404 };
|
||||
return Promise.resolve({
|
||||
ok: (status ?? 200) >= 200 && (status ?? 200) < 300,
|
||||
status: status ?? 200,
|
||||
json: () => Promise.resolve(body),
|
||||
text: () => Promise.resolve(JSON.stringify(body)),
|
||||
headers: new Headers({ 'content-type': 'application/json' }),
|
||||
});
|
||||
});
|
||||
globalThis.fetch = fn;
|
||||
return fn;
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify it compiles**
|
||||
|
||||
Run: `cd frontend && npx tsc --noEmit`
|
||||
Expected: no errors
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/test-utils.tsx
|
||||
git commit -m "test: add shared test utilities (renderWithProviders, mockFetch)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Frontend Page Tests — Home
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/pages/home.test.tsx`
|
||||
|
||||
- [ ] **Step 1: Read Home.tsx**
|
||||
|
||||
Read `/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/Home.tsx` to understand the component structure, signals, and API calls.
|
||||
|
||||
- [ ] **Step 2: Write tests**
|
||||
|
||||
Write ~7 tests covering: list rendering, empty state, new synthesis link, delete double-click flow, auto-cancel, in-progress banner. Mock `~/api/syntheses` module. Use `renderWithProviders` from test-utils. Use `vi.mock()` for the API module and `waitFor` for async assertions.
|
||||
|
||||
- [ ] **Step 3: Run tests**
|
||||
|
||||
Run: `cd frontend && npx vitest run src/__tests__/pages/home.test.tsx`
|
||||
Expected: all PASS
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/pages/home.test.tsx
|
||||
git commit -m "test: add Home page interaction tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Frontend Page Tests — Settings
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/pages/settings.test.tsx`
|
||||
|
||||
- [ ] **Step 1: Read Settings.tsx**
|
||||
|
||||
Read `/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/Settings.tsx` — understand provider/model selection, rate limits, export/import, save flow.
|
||||
|
||||
- [ ] **Step 2: Write tests**
|
||||
|
||||
Write ~10 tests covering: form rendering with API data, save calls PUT, provider dropdown, dual model dropdowns, rate limit inputs, rate limit reset, export triggers download, import populates form. Mock `~/api/settings`, `~/api/config`, `~/api/apiKeys`.
|
||||
|
||||
- [ ] **Step 3: Run tests**
|
||||
|
||||
Run: `cd frontend && npx vitest run src/__tests__/pages/settings.test.tsx`
|
||||
Expected: all PASS
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/pages/settings.test.tsx
|
||||
git commit -m "test: add Settings page interaction tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Frontend Page Tests — Sources
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/pages/sources.test.tsx`
|
||||
|
||||
- [ ] **Step 1: Read Sources.tsx**
|
||||
|
||||
Read `/Users/oabrivard/Projects/rust/ai_synth/frontend/src/pages/Sources.tsx`.
|
||||
|
||||
- [ ] **Step 2: Write tests**
|
||||
|
||||
Write ~8 tests covering: list rendering, empty state, add form validation, add form submit, delete confirmation, bulk import, CSV export trigger, CSV import trigger. Mock `~/api/sources`.
|
||||
|
||||
- [ ] **Step 3: Run and commit**
|
||||
|
||||
Run: `cd frontend && npx vitest run src/__tests__/pages/sources.test.tsx`
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/pages/sources.test.tsx
|
||||
git commit -m "test: add Sources page interaction tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Frontend Page Tests — Login + Register
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/pages/login.test.tsx`
|
||||
- Create: `frontend/src/__tests__/pages/register.test.tsx`
|
||||
|
||||
- [ ] **Step 1: Read Login.tsx and Register.tsx**
|
||||
|
||||
Read both files to understand Turnstile integration, form submission, success/error states, resend cooldown.
|
||||
|
||||
- [ ] **Step 2: Write Login tests (~4 tests)**
|
||||
|
||||
Renders email input + submit, submit calls API, success shows "check inbox", error shows message. Mock `~/api/auth`. Stub `window.turnstile` in setup.
|
||||
|
||||
- [ ] **Step 3: Write Register tests (~4 tests)**
|
||||
|
||||
Renders email + display name + submit, submit calls API, success shows confirmation, error shows message.
|
||||
|
||||
- [ ] **Step 4: Run and commit**
|
||||
|
||||
Run: `cd frontend && npx vitest run src/__tests__/pages/login.test.tsx src/__tests__/pages/register.test.tsx`
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/pages/login.test.tsx frontend/src/__tests__/pages/register.test.tsx
|
||||
git commit -m "test: add Login and Register page interaction tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Frontend Page Tests — GenerateSynthesis
|
||||
|
||||
**Files:**
|
||||
- Create: `frontend/src/__tests__/pages/generate.test.tsx`
|
||||
|
||||
- [ ] **Step 1: Read GenerateSynthesis.tsx**
|
||||
|
||||
Read to understand SSE state machine, step progression, provider display, completion redirect.
|
||||
|
||||
- [ ] **Step 2: Write tests (~6 tests)**
|
||||
|
||||
Renders launch button with settings info, launch calls POST, progress bar updates from mocked SSE events, step checklist shows states, completion triggers redirect, error shows retry. Mock `~/api/syntheses`, `~/api/settings`, `~/api/config`. Stub `EventSource` globally.
|
||||
|
||||
- [ ] **Step 3: Run and commit**
|
||||
|
||||
Run: `cd frontend && npx vitest run src/__tests__/pages/generate.test.tsx`
|
||||
|
||||
```bash
|
||||
git add frontend/src/__tests__/pages/generate.test.tsx
|
||||
git commit -m "test: add GenerateSynthesis page interaction tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 8: Frontend JSDoc Documentation — API Layer
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/src/api/client.ts`
|
||||
- Modify: `frontend/src/api/auth.ts`
|
||||
- Modify: `frontend/src/api/settings.ts`
|
||||
- Modify: `frontend/src/api/sources.ts`
|
||||
- Modify: `frontend/src/api/syntheses.ts`
|
||||
- Modify: `frontend/src/api/admin.ts`
|
||||
- Modify: `frontend/src/api/config.ts`
|
||||
- Modify: `frontend/src/api/apiKeys.ts`
|
||||
|
||||
- [ ] **Step 1: Add JSDoc to api/client.ts**
|
||||
|
||||
Document: class purpose ("Fetch wrapper for authenticated API calls"), CSRF strategy ("Adds X-Requested-With header to all requests"), credential handling ("Uses same-origin credentials for session cookies"), 401 redirect ("Redirects to /login on 401 Unauthorized"), each public method.
|
||||
|
||||
- [ ] **Step 2: Add JSDoc to all other API modules**
|
||||
|
||||
Brief `/** ... */` on each exported function describing what endpoint it calls and what it returns. Example:
|
||||
```typescript
|
||||
/** POST /auth/register — Create account with email + Turnstile token. */
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Verify no code changes**
|
||||
|
||||
Run: `cd frontend && npx tsc --noEmit && npx vitest run`
|
||||
Expected: no errors, all tests pass (docs only)
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/src/api/
|
||||
git commit -m "docs: add JSDoc to all frontend API modules"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 9: Frontend JSDoc Documentation — Pages + Components
|
||||
|
||||
**Files:**
|
||||
- Modify: all files in `frontend/src/pages/`, `frontend/src/components/`, `frontend/src/utils/`, `frontend/src/contexts/`
|
||||
|
||||
- [ ] **Step 1: Document pages**
|
||||
|
||||
Add JSDoc to each page component. Focus on:
|
||||
- `Settings.tsx` — export/import logic, provider auto-detection, rate limit null handling, dual model state
|
||||
- `GenerateSynthesis.tsx` — SSE state machine, step progression, reconnection
|
||||
- `Home.tsx` — delete confirmation timer pattern
|
||||
- `Sources.tsx` — bulk import parsing, CSV flow
|
||||
- Brief JSDoc on all other pages
|
||||
|
||||
- [ ] **Step 2: Document components**
|
||||
|
||||
Add JSDoc to each component. Focus on:
|
||||
- `ApiKeyManager.tsx` — key CRUD flow, show/hide toggle, test button
|
||||
- `Turnstile.tsx` — widget lifecycle, polling initialization, cleanup
|
||||
- Brief JSDoc on all other components including ui/
|
||||
|
||||
- [ ] **Step 3: Document utilities and context**
|
||||
|
||||
- `utils/sse.ts` — reconnection backoff logic, event parsing, cleanup
|
||||
- `utils/dates.ts` — locale configuration
|
||||
- `utils/providers.ts` — capability detection
|
||||
- `contexts/AuthContext.tsx` — session check on mount, isAdmin derived signal
|
||||
|
||||
- [ ] **Step 4: Verify and commit**
|
||||
|
||||
Run: `cd frontend && npx tsc --noEmit && npx vitest run`
|
||||
|
||||
```bash
|
||||
git add frontend/src/pages/ frontend/src/components/ frontend/src/utils/ frontend/src/contexts/
|
||||
git commit -m "docs: add JSDoc to all frontend pages, components, utilities"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 10: E2E Infrastructure
|
||||
|
||||
**Files:**
|
||||
- Create: `e2e/package.json`
|
||||
- Create: `e2e/playwright.config.ts`
|
||||
- Create: `e2e/docker-compose.test.yml`
|
||||
- Create: `e2e/seed.ts`
|
||||
- Create: `e2e/helpers/auth.ts`
|
||||
|
||||
- [ ] **Step 1: Create e2e/package.json**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "ai-synth-e2e",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "playwright test",
|
||||
"test:ui": "playwright test --ui",
|
||||
"seed": "npx tsx seed.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.50.0",
|
||||
"pg": "^8.13.0",
|
||||
"tsx": "^4.21.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Create playwright.config.ts**
|
||||
|
||||
Base URL `http://localhost:8080`, 30s timeout, 1 retry, screenshots on failure, single worker (sequential for DB state).
|
||||
|
||||
- [ ] **Step 3: Create docker-compose.test.yml**
|
||||
|
||||
Extends main `docker-compose.yml`. Uses test Postgres with fresh DB. Sets test environment variables (TEST turnstile/resend keys). Exposes on port 8080.
|
||||
|
||||
- [ ] **Step 4: Create seed.ts**
|
||||
|
||||
Connects to Postgres. Creates admin user (email_verified=true, role=admin) with a known session token. Creates regular user with known session token. Both tokens stored in known-hashes table for cookie injection.
|
||||
|
||||
- [ ] **Step 5: Create helpers/auth.ts**
|
||||
|
||||
`loginAsAdmin(page)` — sets session cookie. `loginAsUser(page)` — sets session cookie. `registerAndVerify(page, email)` — inserts magic link token in DB, navigates to verify URL.
|
||||
|
||||
- [ ] **Step 6: Install and verify**
|
||||
|
||||
```bash
|
||||
cd e2e && npm install && npx playwright install chromium
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add e2e/
|
||||
git commit -m "test: add E2E infrastructure (Playwright + Docker + seed)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 11: E2E Tests — 5 Flows
|
||||
|
||||
**Files:**
|
||||
- Create: `e2e/tests/registration.spec.ts`
|
||||
- Create: `e2e/tests/admin-providers.spec.ts`
|
||||
- Create: `e2e/tests/settings.spec.ts`
|
||||
- Create: `e2e/tests/sources.spec.ts`
|
||||
- Create: `e2e/tests/settings-export.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Write registration flow**
|
||||
|
||||
Navigate to /register, fill email, submit, extract token from DB, visit verify URL, assert redirected to Home with user email in navbar.
|
||||
|
||||
- [ ] **Step 2: Write admin provider config flow**
|
||||
|
||||
Login as admin, navigate to /admin/providers, enable provider, add model, save, verify API returns updated config.
|
||||
|
||||
- [ ] **Step 3: Write settings config flow**
|
||||
|
||||
Login as user, go to /settings, change theme + select provider/models, save, reload, assert values persisted.
|
||||
|
||||
- [ ] **Step 4: Write sources CRUD flow**
|
||||
|
||||
Login, add source, verify in list, bulk import 3, verify count = 4, delete one, verify count = 3, export CSV.
|
||||
|
||||
- [ ] **Step 5: Write settings export/import flow**
|
||||
|
||||
Login, configure settings, export JSON, change settings to different values, save, import exported JSON, save, reload, assert original values restored.
|
||||
|
||||
- [ ] **Step 6: Run E2E (manual — requires Docker)**
|
||||
|
||||
```bash
|
||||
cd e2e
|
||||
docker compose -f docker-compose.test.yml up -d --wait
|
||||
npm run seed
|
||||
npm test
|
||||
docker compose -f docker-compose.test.yml down -v
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add e2e/tests/
|
||||
git commit -m "test: add 5 E2E test flows (registration, admin, settings, sources, export)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 12: Final Verification
|
||||
|
||||
- [ ] **Step 1: Full backend check**
|
||||
|
||||
Run: `cd backend && cargo check && cargo test --lib`
|
||||
Expected: compiles, all tests pass
|
||||
|
||||
- [ ] **Step 2: Full frontend check**
|
||||
|
||||
Run: `cd frontend && npx tsc --noEmit && npx vitest run`
|
||||
Expected: type-checks, all tests pass (original 103 + ~39 new page tests)
|
||||
|
||||
- [ ] **Step 3: Verify frontend build**
|
||||
|
||||
Run: `cd frontend && npx vite build`
|
||||
Expected: production build succeeds
|
||||
|
||||
- [ ] **Step 4: Final commit**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "test: complete test coverage and documentation improvements"
|
||||
```
|
||||
Loading…
Reference in New Issue