# Testing

Test infrastructure and manual recipes for the Africa Alert PWA. Owned by the `tester` rein.

## Status

- No test framework installed yet — bootstrap is the tester's first sprint.
- Target stack: Vitest (client + server) + Supertest (server) + Playwright (E2E, when needed).

## When you add a new feature

1. Producer writes the feature.
2. Producer hands off to `tester` with a one-line description of the happy path and at least one adversarial path.
3. `tester` writes unit + integration tests, runs them, and reports coverage to the orchestrator.
4. `code-reviewer` audits the tests for circular assertions and demands real-run evidence for the user path.

## Manual recipes (for things that don't auto-test credibly)

### Paynow webhook idempotency

1. Initiate a payment via the UI or `POST /api/payments/initiate` with a small amount.
2. Capture the returned `payment_id`.
3. `curl -X POST http://localhost:3001/api/payments/webhook -d '{ "payment_id": "<id>", "status": "paid" }'` — twice in a row.
4. Verify the database has exactly one row in `payments` for that `student_fee_id` and `student_fees.status = 'paid'`. Two POSTs, one state change.

### Sync engine round-trip

1. Set `SUPABASE_URL` to a local stub (e.g. `http://localhost:4000/rest/v1/`) and `SUPABASE_KEY` to anything truthy.
2. `POST /api/sync/force`.
3. Inspect `sync_logs` — every table should be `success` or `skipped` (offline), no `failed` for a clean round.
4. `GET /api/sync/status` → `lastSync` updated, `totalPending` decreased.

### Offline PWA

1. `npm run dev` in `client/` and `server/`.
2. Open the app, log in, navigate to a couple of pages (warms the service worker cache).
3. DevTools → Application → Service Workers → confirm `sw.js` is `activated`.
4. DevTools → Network → Offline.
5. Reload. The shell should still render; cached pages should still open; the dashboard fetch may fail with a clear offline banner (this is fine — the design point is "no white screen of death").

## CI (planned)

GitHub Actions workflow at `.github/workflows/test.yml` (when the user adds it):
- Matrix: Node 20.x
- Steps: install (client + server), `npm test` in each, build client.

## Test data isolation

- Use `data/school.test.db` for integration tests, never the real `data/school.db`.
- Each test or describe block gets a fresh DB file (or in-memory `:memory:`).
- Don't mock the DB schema — copy the relevant `CREATE TABLE` block from `server/src/database/init.js`.
