import { Session } from './Session'; import { SessionType } from '../value-objects/SessionType'; import { RacingDomainValidationError, RacingDomainInvariantError } from '../errors/RacingDomainError'; describe('Session', () => { describe('create', () => { it('should create a session with required fields', () => { const scheduledAt = new Date('2023-01-01T10:00:00Z'); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), }); expect(session.id).toBe('session-1'); expect(session.raceEventId).toBe('race-event-1'); expect(session.scheduledAt).toEqual(scheduledAt); expect(session.track).toBe('Monza'); expect(session.car).toBe('Ferrari SF21'); expect(session.sessionType).toEqual(SessionType.main()); expect(session.status).toBe('scheduled'); expect(session.trackId).toBeUndefined(); expect(session.carId).toBeUndefined(); expect(session.strengthOfField).toBeUndefined(); expect(session.registeredCount).toBeUndefined(); expect(session.maxParticipants).toBeUndefined(); }); it('should create a session with all fields', () => { const scheduledAt = new Date('2023-01-01T10:00:00Z'); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', trackId: 'track-1', car: 'Ferrari SF21', carId: 'car-1', sessionType: SessionType.qualifying(), status: 'running', strengthOfField: 1500, registeredCount: 20, maxParticipants: 24, }); expect(session.id).toBe('session-1'); expect(session.raceEventId).toBe('race-event-1'); expect(session.scheduledAt).toEqual(scheduledAt); expect(session.track).toBe('Monza'); expect(session.trackId).toBe('track-1'); expect(session.car).toBe('Ferrari SF21'); expect(session.carId).toBe('car-1'); expect(session.sessionType).toEqual(SessionType.qualifying()); expect(session.status).toBe('running'); expect(session.strengthOfField).toBe(1500); expect(session.registeredCount).toBe(20); expect(session.maxParticipants).toBe(24); }); it('should throw error for invalid id', () => { const scheduledAt = new Date(); expect(() => Session.create({ id: '', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid raceEventId', () => { const scheduledAt = new Date(); expect(() => Session.create({ id: 'session-1', raceEventId: '', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid scheduledAt', () => { expect(() => Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt: 'invalid' as unknown as Date, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid track', () => { const scheduledAt = new Date(); expect(() => Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: '', car: 'Ferrari SF21', sessionType: SessionType.main(), })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid car', () => { const scheduledAt = new Date(); expect(() => Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: '', sessionType: SessionType.main(), })).toThrow(RacingDomainValidationError); }); it('should throw error for invalid sessionType', () => { const scheduledAt = new Date(); expect(() => Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: undefined as unknown as SessionType, })).toThrow(RacingDomainValidationError); }); }); describe('start', () => { it('should start a scheduled session', () => { const scheduledAt = new Date(Date.now() + 3600000); // future const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'scheduled', }); const started = session.start(); expect(started.status).toBe('running'); }); it('should throw error if not scheduled', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'running', }); expect(() => session.start()).toThrow(RacingDomainInvariantError); }); }); describe('complete', () => { it('should complete a running session', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'running', }); const completed = session.complete(); expect(completed.status).toBe('completed'); }); it('should throw error if already completed', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'completed', }); expect(() => session.complete()).toThrow(RacingDomainInvariantError); }); it('should throw error if cancelled', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'cancelled', }); expect(() => session.complete()).toThrow(RacingDomainInvariantError); }); }); describe('cancel', () => { it('should cancel a scheduled session', () => { const scheduledAt = new Date(Date.now() + 3600000); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'scheduled', }); const cancelled = session.cancel(); expect(cancelled.status).toBe('cancelled'); }); it('should throw error if completed', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'completed', }); expect(() => session.cancel()).toThrow(RacingDomainInvariantError); }); it('should throw error if already cancelled', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'cancelled', }); expect(() => session.cancel()).toThrow(RacingDomainInvariantError); }); }); describe('updateField', () => { it('should update strengthOfField and registeredCount', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), }); const updated = session.updateField(1600, 22); expect(updated.strengthOfField).toBe(1600); expect(updated.registeredCount).toBe(22); }); }); describe('isPast', () => { it('should return true for past session', () => { const scheduledAt = new Date(Date.now() - 3600000); // past const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), }); expect(session.isPast()).toBe(true); }); it('should return false for future session', () => { const scheduledAt = new Date(Date.now() + 3600000); // future const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), }); expect(session.isPast()).toBe(false); }); }); describe('isUpcoming', () => { it('should return true for scheduled future session', () => { const scheduledAt = new Date(Date.now() + 3600000); // future const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'scheduled', }); expect(session.isUpcoming()).toBe(true); }); it('should return false for past scheduled session', () => { const scheduledAt = new Date(Date.now() - 3600000); // past const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'scheduled', }); expect(session.isUpcoming()).toBe(false); }); it('should return false for running session', () => { const scheduledAt = new Date(Date.now() + 3600000); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'running', }); expect(session.isUpcoming()).toBe(false); }); }); describe('isLive', () => { it('should return true for running session', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'running', }); expect(session.isLive()).toBe(true); }); it('should return false for scheduled session', () => { const scheduledAt = new Date(); const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt, track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), status: 'scheduled', }); expect(session.isLive()).toBe(false); }); }); describe('countsForPoints', () => { it('should return true for main session', () => { const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt: new Date(), track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.main(), }); expect(session.countsForPoints()).toBe(true); }); it('should return false for practice session', () => { const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt: new Date(), track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.practice(), }); expect(session.countsForPoints()).toBe(false); }); }); describe('determinesGrid', () => { it('should return true for qualifying session', () => { const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt: new Date(), track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.qualifying(), }); expect(session.determinesGrid()).toBe(true); }); it('should return false for practice session', () => { const session = Session.create({ id: 'session-1', raceEventId: 'race-event-1', scheduledAt: new Date(), track: 'Monza', car: 'Ferrari SF21', sessionType: SessionType.practice(), }); expect(session.determinesGrid()).toBe(false); }); }); });