Pure Transition Testing
Problem
You want to test transition selection and context updates without effects, timers, or subscriptions.
Solution
Call machine.transition() with a snapshot and assert its returned result.
ts
import { expect, test } from 'vitest';
import { defineMachine } from '@vielzeug/clockwork';
type Event = { type: 'LOGIN' };
const auth = defineMachine<{ attempts: number }, Event>()({
context: { attempts: 0 },
initial: 'signedOut',
states: {
signedOut: {
on: {
LOGIN: {
guard: ({ context }) => context.attempts < 3,
reduce: ({ context }) => ({ attempts: context.attempts + 1 }),
target: 'loading',
},
},
},
loading: {},
},
});
test('allows login below the limit', () => {
const result = auth.transition({ context: { attempts: 2 }, state: 'signedOut' }, { type: 'LOGIN' });
expect(result).toMatchObject({
snapshot: { context: { attempts: 3 }, state: 'loading' },
type: 'transition',
});
});Pitfalls
- Pure transitions return only a snapshot and result type; they never execute runtime work.
- Test timers, invokes, subscriptions, and disposal through an actor.