wip league admin tools
This commit is contained in:
82
core/racing/domain/value-objects/RaceStatus.test.ts
Normal file
82
core/racing/domain/value-objects/RaceStatus.test.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { RaceStatus, type RaceStatusValue } from './RaceStatus';
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
|
||||
describe('RaceStatus', () => {
|
||||
it('creates a status and exposes stable value/toString/props', () => {
|
||||
const status = RaceStatus.create('scheduled');
|
||||
expect(status.value).toBe('scheduled');
|
||||
expect(status.toString()).toBe('scheduled');
|
||||
expect(status.props).toEqual({ value: 'scheduled' });
|
||||
});
|
||||
|
||||
it('rejects missing value', () => {
|
||||
expect(() => RaceStatus.create('' as unknown as RaceStatusValue)).toThrow(
|
||||
RacingDomainValidationError,
|
||||
);
|
||||
expect(() => RaceStatus.create('' as unknown as RaceStatusValue)).toThrow(
|
||||
'Race status is required',
|
||||
);
|
||||
});
|
||||
|
||||
it('supports lifecycle guard helpers', () => {
|
||||
expect(RaceStatus.create('scheduled').canStart()).toBe(true);
|
||||
expect(RaceStatus.create('running').canStart()).toBe(false);
|
||||
|
||||
expect(RaceStatus.create('running').canComplete()).toBe(true);
|
||||
expect(RaceStatus.create('scheduled').canComplete()).toBe(false);
|
||||
|
||||
expect(RaceStatus.create('scheduled').canCancel()).toBe(true);
|
||||
expect(RaceStatus.create('running').canCancel()).toBe(true);
|
||||
expect(RaceStatus.create('completed').canCancel()).toBe(false);
|
||||
|
||||
expect(RaceStatus.create('completed').canReopen()).toBe(true);
|
||||
expect(RaceStatus.create('cancelled').canReopen()).toBe(true);
|
||||
expect(RaceStatus.create('running').canReopen()).toBe(false);
|
||||
|
||||
expect(RaceStatus.create('completed').isTerminal()).toBe(true);
|
||||
expect(RaceStatus.create('cancelled').isTerminal()).toBe(true);
|
||||
expect(RaceStatus.create('running').isTerminal()).toBe(false);
|
||||
|
||||
expect(RaceStatus.create('running').isRunning()).toBe(true);
|
||||
expect(RaceStatus.create('completed').isCompleted()).toBe(true);
|
||||
expect(RaceStatus.create('scheduled').isScheduled()).toBe(true);
|
||||
expect(RaceStatus.create('cancelled').isCancelled()).toBe(true);
|
||||
});
|
||||
|
||||
it('validates allowed transitions', () => {
|
||||
const scheduled = RaceStatus.create('scheduled');
|
||||
const running = RaceStatus.create('running');
|
||||
const completed = RaceStatus.create('completed');
|
||||
const cancelled = RaceStatus.create('cancelled');
|
||||
|
||||
expect(scheduled.canTransitionTo('running')).toEqual({ valid: true });
|
||||
expect(scheduled.canTransitionTo('cancelled')).toEqual({ valid: true });
|
||||
|
||||
expect(running.canTransitionTo('completed')).toEqual({ valid: true });
|
||||
expect(running.canTransitionTo('cancelled')).toEqual({ valid: true });
|
||||
|
||||
expect(completed.canTransitionTo('scheduled')).toEqual({ valid: true });
|
||||
expect(cancelled.canTransitionTo('scheduled')).toEqual({ valid: true });
|
||||
});
|
||||
|
||||
it('rejects disallowed transitions with a helpful error', () => {
|
||||
const scheduled = RaceStatus.create('scheduled');
|
||||
const result = scheduled.canTransitionTo('completed');
|
||||
expect(result.valid).toBe(false);
|
||||
expect(result.error).toBe('Cannot transition from scheduled to completed');
|
||||
});
|
||||
|
||||
it('equals compares by value', () => {
|
||||
const a = RaceStatus.create('scheduled');
|
||||
const b = RaceStatus.create('scheduled');
|
||||
const c = RaceStatus.create('running');
|
||||
expect(a.equals(b)).toBe(true);
|
||||
expect(a.equals(c)).toBe(false);
|
||||
});
|
||||
|
||||
it('only allowed status values compile (type-level)', () => {
|
||||
const allowed: RaceStatusValue[] = ['scheduled', 'running', 'completed', 'cancelled'];
|
||||
expect(allowed).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user