feat: add testing infrastructure — Vitest, Playwright, CI, git hooks
Add comprehensive testing covering 420 unit/handler tests across 24 Vitest files, 9 Playwright E2E specs, accessibility scans, and visual regression. Includes GitHub Actions CI, Husky pre-push hook, and TESTING.md docs.
This commit is contained in:
parent
036af95e00
commit
1e30ba23cd
35 changed files with 3637 additions and 5 deletions
90
TESTING.md
Normal file
90
TESTING.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# Testing
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
npm test # Vitest watch mode
|
||||
npm run test:run # Vitest single run (used by pre-push hook)
|
||||
npm run test:e2e # Playwright E2E tests
|
||||
npm run test:e2e:ui # Playwright with interactive UI
|
||||
npm run test:a11y # Accessibility scans (axe-core)
|
||||
npm run test:visual # Visual regression screenshots
|
||||
npm run test:all # Vitest + Playwright together
|
||||
```
|
||||
|
||||
## Vitest (Unit / Handler Tests)
|
||||
|
||||
Tests live in `tests/` mirroring the source structure. Two vitest projects:
|
||||
|
||||
- **server** (`tests/server/`) — Node environment, `setup.js` stubs Nitro auto-imports
|
||||
- **client** (`tests/client/`) — jsdom environment for composables
|
||||
|
||||
### Test patterns
|
||||
|
||||
**Behavioral tests** mock models/services with `vi.mock()`, import the handler, and call it with `createMockEvent()`:
|
||||
|
||||
```js
|
||||
vi.mock('../../../server/models/member.js', () => ({ default: { findOne: vi.fn() } }))
|
||||
import handler from '../../../server/api/some/route.js'
|
||||
import { createMockEvent } from '../helpers/createMockEvent.js'
|
||||
```
|
||||
|
||||
**Source inspection tests** use `readFileSync` to verify structural properties (auth guards, import order) without executing handlers.
|
||||
|
||||
### Nitro auto-imports in tests
|
||||
|
||||
Handlers use Nitro auto-imports for `requireAuth`, `requireAdmin`, `validateBody`, and schemas. These are stubbed as globals in `tests/server/setup.js`. Individual tests can configure their behavior with `.mockResolvedValue()` etc.
|
||||
|
||||
## Playwright (E2E Tests)
|
||||
|
||||
Tests live in `e2e/`. Requires a running dev server and MongoDB.
|
||||
|
||||
### Auth helpers
|
||||
|
||||
`e2e/helpers/auth.js` provides `loginAsAdmin(page)` and `loginAsMember(page, email)` using the dev login endpoints. These set real JWT cookies.
|
||||
|
||||
`e2e/helpers/fixtures.js` extends Playwright's `test` with `adminPage` and `memberPage` fixtures.
|
||||
|
||||
### Running locally
|
||||
|
||||
```bash
|
||||
# Start dev server (Playwright config does this automatically)
|
||||
npm run dev
|
||||
|
||||
# Run tests
|
||||
npm run test:e2e
|
||||
|
||||
# Interactive mode
|
||||
npm run test:e2e:ui
|
||||
```
|
||||
|
||||
### Visual regression
|
||||
|
||||
Baselines stored in `e2e/__screenshots__/`. Generate or update:
|
||||
|
||||
```bash
|
||||
npm run test:visual:update
|
||||
```
|
||||
|
||||
Note: Linux CI and macOS local produce different renders. Generate baselines in CI with `--update-snapshots`, then commit.
|
||||
|
||||
## Pre-Push Hook
|
||||
|
||||
Husky runs `npm run test:run` (Vitest only) before `git push`. All mocked, runs in ~1s. Playwright is not included — too slow and requires MongoDB.
|
||||
|
||||
## CI (GitHub Actions)
|
||||
|
||||
`.github/workflows/test.yml` defines three jobs:
|
||||
|
||||
1. **vitest** — runs on every push/PR to main
|
||||
2. **playwright** — runs after vitest passes, uses MongoDB service container
|
||||
3. **visual** — runs after vitest, `continue-on-error: true` during stabilization
|
||||
|
||||
CI uses dummy secrets (`JWT_SECRET: ci-test-jwt-secret`). No real Helcim/Resend/Slack tokens — those paths are mocked at Vitest level, and E2E skips the Helcim iframe.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- **Helcim iframe** — cannot be tested in E2E (cross-origin). Payment flows are tested at the Vitest handler level. E2E tests stop before the iframe opens.
|
||||
- **Email delivery** — mocked at Vitest level. E2E verifies form submission, not actual email.
|
||||
- **Slack invitations** — mocked at Vitest level.
|
||||
- **Visual baseline OS drift** — generate baselines in CI, not locally.
|
||||
Loading…
Add table
Add a link
Reference in a new issue