docs: ADR-0006 test-data builders, close out WP-70
Writes up the principle behind WP-70's three tracks ("build test data
through the same door production code uses") as ADR-0006, with a decision
table for which fixture idiom fits which test type. Updates the
test-strategy skill (adds the Fixtures rule, fixes its stale pre-monorepo
src/app/... worked-example paths) and the shared Storybook testing.mdx page
to match. Closes WP-70 with the signatures/counts as actually shipped.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,9 +63,38 @@ expect(parseBrpAddress(null).ok).toBe(false);
|
||||
expect(parseBrpAddress({}).ok).toBe(false); // missing required field
|
||||
```
|
||||
|
||||
Elm-style machines test the pure `reduce` with inline state fixtures — no Angular
|
||||
Elm-style machines test the pure `reduce` — no Angular
|
||||
(`registratie/domain/registratie-wizard.machine.spec.ts`).
|
||||
|
||||
## Fixtures: build test data through the production door
|
||||
|
||||
A fixture is not a shortcut around the domain — it's the domain's own construction path, run
|
||||
once for the test. [ADR-0006](../../../docs/reference/architecture/0006-test-data-builders.md)
|
||||
covers this in full (with a backend example too); the frontend idiom is one combinator,
|
||||
`given` (`libs/shared/src/testing/machine.ts`):
|
||||
|
||||
```ts
|
||||
export const given =
|
||||
<S, M>(reduce: (s: S, m: M) => S, initial: S) =>
|
||||
(...msgs: M[]): S =>
|
||||
msgs.reduce(reduce, initial);
|
||||
|
||||
export const givenIntake = given(reduce, initial); // per-context wrapper, pure TS
|
||||
```
|
||||
|
||||
A machine spec replays real `Msg`s instead of hand-writing a `State` literal — so a fixture
|
||||
can only ever be a state the real reducer actually produces:
|
||||
|
||||
```ts
|
||||
const atStep3 = givenIntake(Start(), SetUren('1200'), Next(), SetDiplomaHerkomst('NL'), Next());
|
||||
```
|
||||
|
||||
The same rule extends to value objects (`unwrapOk(parseX(raw))` instead of a cast) and to
|
||||
`RemoteData` (`loading()` / `success(v)` / `failure(e)` in
|
||||
`libs/shared/src/testing/{value-object,remote-data}.ts` instead of a redefined-per-file
|
||||
literal). **Never** a `.withX().withY()` builder over an open constructor — that just
|
||||
re-opens whatever illegal state the domain closed.
|
||||
|
||||
## UI = Storybook, not heavy component tests
|
||||
|
||||
`@storybook/addon-a11y` runs the `wcag2a/2aa/21a/21aa` rule sets on **every** story;
|
||||
|
||||
Reference in New Issue
Block a user