mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
docs(testing): describe the browser project and its helper
Say which claims belong in *.browser.test.tsx, how to run the project alone, and what tests/browser/ provides. The browser install guard now names the browser project beside the hero-geometry check, since both launch the headless shell the CI slices install.
This commit is contained in:
1 parent
392b2c47a9
commit
232c3db6ef
2 files changed
+48
-3
No files matched your search
@@ -11,6 +11,7 @@ is about choosing and writing tests.
|
||||
| Pure logic: statistics, time zones, cadence, parsers, unit conversion, formatting | `src/**/__tests__/*.test.ts` (unit) | `pnpm test` |
|
||||
| Laws of that logic over random inputs | `*.property.test.ts` next to the unit tests | `pnpm test` |
|
||||
| What a component renders for a given state | `src/**/__tests__/*.test.tsx` (unit) | `pnpm test` |
|
||||
| How a component behaves when someone types, clicks or presses keys, and what it sends | `src/**/__tests__/*.browser.test.tsx` | `pnpm test` |
|
||||
| A structural rule about the tree (a guard) | `src/__tests__/` with a stated floor | `pnpm test` |
|
||||
| A route: auth, scope, validation, what it stores and what it answers | `tests/integration/routes/` with the kit | `pnpm test:integration` |
|
||||
| Anything whose truth lives in Postgres: constraints, `where` semantics, transactions, locks, cascades, time zones in SQL, backups, jobs | `tests/integration/` | `pnpm test:integration` |
|
||||
@@ -114,6 +115,43 @@ into a fresh account and reads it back there. A new setting column without a
|
||||
table entry fails the file. A column with no write route says why in its
|
||||
entry.
|
||||
|
||||
## Browser tests
|
||||
|
||||
Interaction belongs in the `browser` project: `*.browser.test.tsx` files run
|
||||
in headless Chromium through Vitest's Playwright provider, as part of
|
||||
`pnpm test`. Run them alone with `pnpm test --project browser`, or one file
|
||||
with `pnpm exec vitest run --project browser <path>`. The Node projects never
|
||||
collect these files and this project collects nothing else. CI installs the
|
||||
browser it needs (`playwright install --only-shell chromium`); locally, run
|
||||
that once.
|
||||
|
||||
Reach for it when the claim is about behaviour a markup test cannot see:
|
||||
focus, keys, an open menu, a pending state, the body a form posts, the URL a
|
||||
filter writes. A `renderToStaticMarkup` grep stays the tool for what a given
|
||||
state renders, and bottom-sheet gestures stay in `e2e/`.
|
||||
|
||||
The helper is `tests/browser/`:
|
||||
|
||||
- `renderWithApp(ui, { locale, user })` mounts the app's own providers: a real
|
||||
TanStack `QueryClient` (no retries) and `I18nProvider` with the real
|
||||
catalog. The signed-in account is seeded where `useAuth` reads it, with
|
||||
`authUser()` defaults under `user`. The app stylesheet and the default
|
||||
theme class are loaded, so layout, visibility and colour tokens resolve.
|
||||
- `stubFetch()` replaces `fetch` and nothing above it. Answer a route with
|
||||
`.on(method, path, { status, data, error, meta })`, hold one with
|
||||
`.deferred(...)` to assert a pending state, and read the parsed bodies from
|
||||
`.calls(method, path)`. An unmatched request gets a 404 envelope and is
|
||||
recorded. Do not mock `@tanstack/react-query` or `@/lib/api/api-fetch`.
|
||||
- `next/navigation` is aliased to a shim over the page's real `location` and
|
||||
`history`; `url.ts` sets the starting query, records pushes and replaces,
|
||||
and simulates Back or an edited address.
|
||||
- `pinDate(iso)` fakes `Date` only, so timers and animation frames still run.
|
||||
|
||||
Every test gets the real `fetch`, clock, address and an empty `localStorage`
|
||||
back afterwards. Locate by role and accessible name, the way a person finds a
|
||||
control; a `Label` adds a colon to its name, so match a labelled combobox with
|
||||
`/^Type/` rather than `"Type"`.
|
||||
|
||||
## The integration database
|
||||
|
||||
Global setup boots one Postgres container and migrates one template database.
|
||||
@@ -152,7 +190,8 @@ node scripts/test-durations.mjs unit unit.json
|
||||
The nightly workflow (`.github/workflows/test-nightly.yml`) uploads a file
|
||||
regenerated from CI timings, which is the better source.
|
||||
|
||||
The unit suite is three projects, decided per file from its source
|
||||
The unit suite is three Node projects and the `browser` project above. The
|
||||
Node ones are decided per file from its source
|
||||
(`tests/unit-projects.ts`): `guards` and `unit` share a module graph within a
|
||||
worker, `isolated` gives each file a fresh one. A file lands in `isolated` when
|
||||
it mocks, spies, stubs env or globals, fakes timers or resets modules. If a
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
* same suite: every dependency bump failed on a launch error that said nothing
|
||||
* about the bump. One workflow was fixed, one class was not.
|
||||
*
|
||||
* Since v1.46 the suite also carries the `browser` project
|
||||
* (`*.browser.test.tsx`, see `tests/browser/`), which launches the same
|
||||
* headless shell through Vitest's Playwright provider for every interaction
|
||||
* test. A slice without the browser now fails on many files rather than one;
|
||||
* the install it needs is the same, so this guard covers both.
|
||||
*
|
||||
* The sweep is textual and file-scoped, which is its limit: a workflow with two
|
||||
* jobs, only one of which installs the browser, satisfies it. It catches the
|
||||
* thing that actually went wrong — a whole workflow running the suite with no
|
||||
@@ -58,8 +64,8 @@ describe("the browser the unit suite measures with", () => {
|
||||
expect(
|
||||
missing,
|
||||
"a workflow runs the unit suite without installing the headless " +
|
||||
"Chromium the hero-geometry check measures with — that check refuses " +
|
||||
"to skip under CI, so the job fails on a launch error instead",
|
||||
"Chromium the hero-geometry check and the browser project launch — " +
|
||||
"neither skips under CI, so the job fails on a launch error instead",
|
||||
).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user