# Integration Test Patterns

Story tests live in `backend/src/tests/story/<flow>/<actor>--<action>.test.ts`.
Each runs against a live workspace over a few GraphQL calls, so the suite is
network-bound. Keep it fast with the patterns below.

## Parallelism

`vitest.config.ts` sets `maxWorkers: 16` — run many files at once (above the CPU
count) to hide network latency.

## Test data

- Seed holds **master and login data only**.
- Never depend on seeded **mutable** rows — parallel tests change them.
- Create mutable data **in the test**, with a distinctive suffix
  (`` `PROD-${Date.now()}` ``).

> A timestamp suffix can collide across files in the same millisecond — rare,
> and accepted.

## Fewer round-trips

| Pattern | Use it to |
| --- | --- |
| `beforeAll` | Run a shared **read-only** lookup once, not per case. |
| `Promise.all` | Create **independent** preconditions together. |

Keep dependent steps sequential. `beforeAll` runs once **per worker** — fine for
a read, not for shared mutable state.

```ts
let uomId: string;
beforeAll(async () => {
  const res = await gql.query(listUnits, {}).toPromise();
  uomId = res.data!.units.edges[0].node.id;
});
```

Keep every `describe` / `it` title matching the story doc's `## Test Cases` —
`erp-kit app sync-check` compares them.

If the implementation cannot satisfy a documented Test Case as written (a status
that does not exist, a rule nothing enforces), **raise the discrepancy** — fix the
doc or the implementation. Never hedge the title or the assertion ("shows A or B")
to make the test pass.
