# E2E harness (Playwright)

The automated regression net for the QA plan — real clicks in a real browser,
plus visual-regression and axe-a11y that re-run every cycle. See
[`docs/QA_PLAN.md` §4.4](../docs/QA_PLAN.md) and the **B-UI / B14 / B15** batches.

## Setup (one-time)

```bash
npm install
npx playwright install chromium   # add: firefox webkit  for cross-browser
```

## Run

```bash
npm run test:e2e          # seed scratch DB, then run headless
npm run test:e2e:ui       # seed scratch DB, then Playwright UI mode (watch/debug)
npm run test:e2e:update   # re-baseline visual-regression screenshots
```

## Safe by construction

Each command runs `e2e/setup/prepare-db.js` first, which builds a **fresh scratch
DB** (`db/e2e.db`, git-ignored) with a seeded regular user — it **refuses to touch
`db/bills.db`**. [`playwright.config.js`](../playwright.config.js) then boots the
app against that scratch DB on **dedicated ports** (UI `5199`, API `3099`) with
`reuseExistingServer: false`, so E2E never collides with or reuses your normal
dev server on `5173/3000`. You can keep `npm run dev` running while E2E runs.

Override defaults via env: `E2E_DB_PATH`, `E2E_USER`, `E2E_PASS`, `E2E_UI_PORT`,
`E2E_API_PORT` (see `e2e/constants.js`).

## What's here

| File | Covers |
|------|--------|
| `setup/prepare-db.js` | fresh scratch DB + seeded regular user (run automatically) |
| `auth.setup.js` | logs in via the UI once, saves `.auth/user.json` for reuse |
| `smoke.spec.js` | (logged-out) login renders, empty-submit doesn't crash, routing, login visual baseline |
| `a11y.spec.js` | axe-core scan of public pages — fails on critical/serious WCAG violations |
| `critical-path.spec.js` | (logged-in) tracker renders seeded data, quick-pay + undo, all authed pages render error-free, sidebar nav |

## Growing it (next steps)

1. **Numeric reconciliation** — assert Summary's paid/unpaid/remaining totals
   match the Tracker for the same month (QA_PLAN B5); see the TODO in
   `critical-path.spec.js`.
2. **Create-bill flow** — drive BillModal (create → appears on Tracker → delete).
3. **Primitive state matrix** — one spec per `client/components/ui/*` (B-UI).
4. **Fault injection** — `page.route()` to force 401/429/500/timeout per page and
   assert a recoverable error, never a white screen (B14).
5. **Visual coverage** — a `toHaveScreenshot` per page × {desktop,mobile}.
6. **Cross-browser** — enable the firefox/webkit projects in the config.

Screenshot baselines live in `e2e/**/*-snapshots/` and **are committed** (that's
the point of visual regression). `test-results/`, `playwright-report/`, and
`e2e/.auth/` are not.
