129 lines
3.7 KiB
Markdown
129 lines
3.7 KiB
Markdown
# Testing Improvements Design
|
|
|
|
**Date:** 2026-04-03
|
|
**Scope:** Unit tests for new server code + Playwright E2E test setup with seeded database
|
|
|
|
## Part 1: Unit/Integration Tests (Bun test runner)
|
|
|
|
### tests/lib/params.test.ts
|
|
|
|
Tests for `parseId` helper in `src/server/lib/params.ts`:
|
|
- Valid positive integers (1, 42, 999) return the number
|
|
- Zero returns null
|
|
- Negative numbers (-1, -100) return null
|
|
- Decimals (1.5, 3.14) return null
|
|
- Non-numeric strings ("abc", "", "hello") return null
|
|
- NaN-producing values return null
|
|
|
|
### tests/middleware/rateLimit.test.ts
|
|
|
|
Tests for rate limiter in `src/server/middleware/rateLimit.ts`:
|
|
- First request passes through (200)
|
|
- 5 requests succeed, 6th returns 429
|
|
- 429 response includes `Retry-After` header
|
|
- Different IPs tracked independently
|
|
- After window expires, requests succeed again
|
|
|
|
Since the rate limiter uses a module-level `Map`, tests need to either:
|
|
- Reset the store between tests (export a `resetStore` for testing), OR
|
|
- Use unique paths/IPs per test to avoid interference
|
|
|
|
Recommended: export a `_resetForTesting()` function from rateLimit.ts that clears the store. Only used in tests.
|
|
|
|
### tests/routes/params.test.ts
|
|
|
|
Route-level integration tests verifying 400 responses for invalid IDs:
|
|
- `GET /api/items/abc` → 400
|
|
- `GET /api/items/-1` → 400
|
|
- `GET /api/items/0` → 400
|
|
- `DELETE /api/categories/notanumber` → 400
|
|
- `GET /api/threads/abc` → 400
|
|
- `GET /api/setups/abc` → 400
|
|
|
|
Uses existing test app pattern with in-memory DB.
|
|
|
|
## Part 2: Playwright E2E Setup
|
|
|
|
### Installation
|
|
|
|
- `bun add -d @playwright/test`
|
|
- `bunx playwright install chromium` (only Chromium needed)
|
|
|
|
### Configuration: playwright.config.ts
|
|
|
|
```ts
|
|
export default defineConfig({
|
|
testDir: "./e2e",
|
|
webServer: {
|
|
command: "DATABASE_PATH=./e2e/test.db bun run dev:server",
|
|
port: 3000,
|
|
reuseExistingServer: !process.env.CI,
|
|
},
|
|
use: {
|
|
baseURL: "http://localhost:3000",
|
|
},
|
|
projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
|
|
});
|
|
```
|
|
|
|
### Database Seeding: e2e/seed.ts
|
|
|
|
Script that creates `e2e/test.db` with:
|
|
- Run Drizzle migrations against the file
|
|
- Seed data:
|
|
- 1 user (username: "admin", password: "password123")
|
|
- 3 categories: Shelter, Sleep System, Cook Kit
|
|
- 6 items across categories with realistic weights/prices
|
|
- 1 active thread with 3 candidates (with pros/cons, sort_order)
|
|
- 1 resolved thread
|
|
- 1 setup with 4 items (mixed classifications)
|
|
- Settings: weightUnit=g, currency=USD, onboardingComplete=true
|
|
|
|
Run before E2E tests via `e2e/global-setup.ts` (Playwright globalSetup).
|
|
|
|
### E2E Test Files
|
|
|
|
**e2e/dashboard.spec.ts**
|
|
- Dashboard page loads
|
|
- Summary cards show item count, weight, cost
|
|
- Navigation links to collection work
|
|
|
|
**e2e/collection.spec.ts**
|
|
- Gear tab renders items grouped by category
|
|
- Search input filters items by name
|
|
- Category filter dropdown works
|
|
- Tab switching between gear/planning/setups
|
|
|
|
**e2e/threads.spec.ts**
|
|
- Thread detail page loads with candidates
|
|
- Comparison view toggle works (shows table)
|
|
- Rank badges visible on candidates
|
|
|
|
**e2e/auth.spec.ts**
|
|
- Login page renders
|
|
- Login with valid credentials succeeds
|
|
- Login with wrong password shows error
|
|
- Rate limiting returns error after 5 attempts
|
|
|
|
**e2e/error-boundary.spec.ts**
|
|
- App doesn't white-screen on unknown routes
|
|
- Navigating to a non-existent thread/setup shows appropriate error
|
|
|
|
### Scripts
|
|
|
|
Add to package.json:
|
|
- `"test:e2e": "bunx playwright test"`
|
|
- `"test:e2e:ui": "bunx playwright test --ui"` (for debugging)
|
|
|
|
### Files to .gitignore
|
|
|
|
- `e2e/test.db`
|
|
- `test-results/`
|
|
- `playwright-report/`
|
|
|
|
## Commit Strategy
|
|
|
|
1. Unit tests for parseId, rate limiter, route params
|
|
2. Playwright setup (install, config, seed, global-setup)
|
|
3. Playwright E2E test files
|