docs(test): make Given/When/Then the default BDD structure (WP-71)
bdd.mdx previously banned "Given/When/Then ceremony" outright, which
directly contradicted WP-70's own acceptance tests (Acceptance/
BesluitLifecycleTests.cs already used // Given/When/Then comments) and
the backend's organically-evolved PascalCase_snake_sentence convention,
which the doc gave zero guidance for. Reverses that rule: every test is
now structured Given -> When -> Then, with a genuinely empty phase
omitted rather than faked; present-tense declarative naming and the
one-behaviour-per-test rule are unchanged. ADR-0006 gets a cross-reference
so both documents agree everywhere, not just in acceptance tests.
Also closes out the doc's other named-but-unenforced rules found by the
audit: fixes the 5 files asserting rendered $localize copy instead of
the underlying tag/message-id (the compliant pattern already existed in
werkvoorraad-item-view.spec.ts), splits the multi-behaviour titles the
doc itself calls a smell (";", "and", "/"), and fixes bdd.mdx's own false
citation of registratie-wizard.machine.spec.ts as "one transition per
test" by actually splitting that test into one-transition-per-test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,32 +27,49 @@ describe('statusLabel', () => {
|
||||
|
||||
describe('detailRows', () => {
|
||||
it('lists soort/status/referentie/eigenaar/ingediend', () => {
|
||||
// Given a case InBehandeling.
|
||||
// When its detail rows are derived...
|
||||
const rows = detailRows({
|
||||
...base,
|
||||
status: { tag: 'InBehandeling', referentie: 'R1', manual: false },
|
||||
});
|
||||
const values = rows.map((r) => r.value);
|
||||
|
||||
// Then the type label (via TYPE_LABELS, not a literal), the reference, and the
|
||||
// owner all appear as rows.
|
||||
expect(values).toContain(TYPE_LABELS.herregistratie);
|
||||
expect(values).toContain('R1');
|
||||
expect(values).toContain(base.owner);
|
||||
expect(rows.length).toBe(5);
|
||||
});
|
||||
|
||||
it('adds a reden row for Afgewezen and MeerInfoGevraagd only', () => {
|
||||
// One behaviour ("a reden row is added exactly for the two statuses that carry a
|
||||
// reden") checked as a truth table over three statuses — kept together per
|
||||
// bdd.mdx's "truth-table of one rule" exception, rather than split apart.
|
||||
//
|
||||
// `reden` itself is raw domain data (a free-text field on the status union, not an
|
||||
// enum), passed through `detailRows` unchanged and never wrapped by `$localize` —
|
||||
// there is no reason-code/tag to assert on instead; the value under test IS the
|
||||
// string the Given supplied, so checking it reappears in the Then is a
|
||||
// pass-through check, not a translated-copy assertion.
|
||||
it('a reden row is present only for Afgewezen and MeerInfoGevraagd', () => {
|
||||
// Given three cases: rejected, more-info-requested, and approved.
|
||||
// When their detail rows are derived...
|
||||
const afgewezen = detailRows({
|
||||
...base,
|
||||
status: { tag: 'Afgewezen', referentie: 'R1', reden: 'Onvoldoende uren' },
|
||||
});
|
||||
expect(afgewezen.length).toBe(6);
|
||||
expect(afgewezen.map((r) => r.value)).toContain('Onvoldoende uren');
|
||||
|
||||
const meerInfo = detailRows({
|
||||
...base,
|
||||
status: { tag: 'MeerInfoGevraagd', referentie: 'R1', reden: 'Diploma ontbreekt' },
|
||||
});
|
||||
expect(meerInfo.length).toBe(6);
|
||||
|
||||
const goedgekeurd = detailRows({ ...base, status: { tag: 'Goedgekeurd', referentie: 'R1' } });
|
||||
|
||||
// Then only the rejected and more-info-requested cases gain a reden row (carrying
|
||||
// the reason through unchanged); the approved case does not.
|
||||
expect(afgewezen.length).toBe(6);
|
||||
expect(afgewezen.map((r) => r.value)).toContain('Onvoldoende uren');
|
||||
expect(meerInfo.length).toBe(6);
|
||||
expect(goedgekeurd.length).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,7 +31,13 @@ describe('parseBeoordelingStatus', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a missing status, unknown tag, and wrong-typed fields', () => {
|
||||
// One behaviour ("rejects a malformed status") checked over several malformed
|
||||
// shapes — a loop asserting one rule over many inputs, kept together per bdd.mdx.
|
||||
it('rejects a malformed status', () => {
|
||||
// Given a status that is missing entirely, has an unknown tag, or is missing a
|
||||
// required field for its tag.
|
||||
// When each is parsed...
|
||||
// Then all are rejected.
|
||||
expect(parseBeoordelingStatus(undefined).ok).toBe(false);
|
||||
expect(parseBeoordelingStatus({ tag: 'Concept' } as never).ok).toBe(false);
|
||||
expect(parseBeoordelingStatus({ tag: 'InBehandeling', referentie: 'BIG-1' }).ok).toBe(false);
|
||||
@@ -50,7 +56,13 @@ describe('parseBeoordelingView', () => {
|
||||
expect(r.value.canBesluiten).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects a missing owner, bad type, missing decisions, and non-objects', () => {
|
||||
// One behaviour ("rejects a malformed view") checked over several malformed
|
||||
// shapes — a loop asserting one rule over many inputs, kept together per bdd.mdx.
|
||||
it('rejects a malformed view', () => {
|
||||
// Given a view that is a non-object, missing the owner, has an unknown aanvraag
|
||||
// type, or is missing decisions.
|
||||
// When each is parsed...
|
||||
// Then all are rejected.
|
||||
expect(parseBeoordelingView(null).ok).toBe(false);
|
||||
expect(
|
||||
parseBeoordelingView({ ...view, aanvraag: { ...view.aanvraag, owner: undefined } }).ok,
|
||||
|
||||
Reference in New Issue
Block a user