Files
atomic-design-poc/src/app/organisms/herregistratie-wizard/wizard.machine.spec.ts
Edwin van den Houdt 80c1b627d0 Drive herregistratie as a state-machine wizard
Model the multi-step form as one tagged union: step/errors exist only while
Editing, and Submitting/Submitted/Failed carry a parsed Valid payload. So
"submitting while a field is invalid" and "success screen with errors set"
are unrepresentable by construction.

Pure transitions (next/back/submit/resolve) with a spec covering the key
invariants; illegal events are no-ops. The page becomes pure composition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:56:04 +02:00

33 lines
1.5 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { ok, err } from '../../core/fp';
import { initial, next, back, submit, resolve, WizardState } from './wizard.machine';
const editing1 = (uren: string, punten = ''): WizardState => ({ tag: 'Editing', step: 1, draft: { uren, punten }, errors: {} });
const editing2 = (uren: string, punten: string): WizardState => ({ tag: 'Editing', step: 2, draft: { uren, punten }, errors: {} });
describe('wizard.machine', () => {
it('next advances only when step 1 parses', () => {
expect(next(initial).tag).toBe('Editing'); // empty uren -> stays, with error
expect((next(initial) as any).errors.uren).toBeTruthy();
expect((next(editing1('4160')) as any).step).toBe(2);
});
it('submit reaches Submitting ONLY with fully valid data', () => {
expect(submit(editing2('4160', 'x')).tag).toBe('Editing'); // invalid punten -> no Submitting
const good = submit(editing2('4160', '200'));
expect(good.tag).toBe('Submitting');
expect((good as any).data).toEqual({ uren: 4160, punten: 200 });
});
it('back / resolve are no-ops from illegal states', () => {
expect(back(initial)).toBe(initial); // step 1, nothing to go back to
expect(resolve(initial, ok(undefined))).toBe(initial); // not Submitting
});
it('resolve maps Submitting to Submitted / Failed', () => {
const submitting = submit(editing2('4160', '200'));
expect(resolve(submitting, ok(undefined)).tag).toBe('Submitted');
expect(resolve(submitting, err('boom')).tag).toBe('Failed');
});
});