import { beforeEach, describe, expect, it } from 'vitest'; import { LeaguesTestContext } from '../LeaguesTestContext'; import { League as RacingLeague } from '../../../../core/racing/domain/entities/League'; import { Season } from '../../../../core/racing/domain/entities/season/Season'; import { LeagueMembership } from '../../../../core/racing/domain/entities/LeagueMembership'; // Note: the current racing module does not expose explicit "open/close registration" use-cases. // Registration is modeled via membership + registrations repository interactions. describe('League Schedule - Race Registration', () => { let context: LeaguesTestContext; beforeEach(() => { context = new LeaguesTestContext(); context.clear(); }); const seedRacingLeague = async (params: { leagueId: string }) => { const league = RacingLeague.create({ id: params.leagueId, name: 'Racing League', description: 'League used for registration integration tests', ownerId: 'driver-123', }); await context.racingLeagueRepository.create(league); return league; }; const seedSeason = async (params: { seasonId: string; leagueId: string; startDate?: Date; endDate?: Date; }) => { const season = Season.create({ id: params.seasonId, leagueId: params.leagueId, gameId: 'iracing', name: 'Season 1', status: 'active', startDate: params.startDate ?? new Date('2025-01-01T00:00:00Z'), endDate: params.endDate ?? new Date('2025-01-31T23:59:59Z'), }); await context.seasonRepository.add(season); return season; }; const seedActiveMembership = async (params: { leagueId: string; driverId: string }) => { const membership = LeagueMembership.create({ leagueId: params.leagueId, driverId: params.driverId, role: 'member', status: 'active', }); await context.leagueMembershipRepository.saveMembership(membership); return membership; }; it('registers an active league member for a race', async () => { const leagueId = 'league-1'; const seasonId = 'season-1'; const driverId = 'driver-1'; await seedRacingLeague({ leagueId }); await seedSeason({ leagueId, seasonId }); await seedActiveMembership({ leagueId, driverId }); const createRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({ leagueId, seasonId, track: 'Monza', car: 'GT3', scheduledAt: new Date('2025-01-10T20:00:00Z'), }); expect(createRace.isOk()).toBe(true); const { raceId } = createRace.unwrap(); const register = await context.registerForRaceUseCase.execute({ leagueId, raceId, driverId, }); expect(register.isOk()).toBe(true); expect(register.unwrap()).toEqual({ raceId, driverId, status: 'registered' }); const isRegistered = await context.raceRegistrationRepository.isRegistered(raceId, driverId); expect(isRegistered).toBe(true); }); it('rejects registration when driver is not an active member', async () => { const leagueId = 'league-1'; const seasonId = 'season-1'; await seedRacingLeague({ leagueId }); await seedSeason({ leagueId, seasonId }); const createRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({ leagueId, seasonId, track: 'Monza', car: 'GT3', scheduledAt: new Date('2025-01-10T20:00:00Z'), }); expect(createRace.isOk()).toBe(true); const { raceId } = createRace.unwrap(); const result = await context.registerForRaceUseCase.execute({ leagueId, raceId, driverId: 'driver-missing' }); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('NOT_ACTIVE_MEMBER'); }); it('rejects duplicate registration', async () => { const leagueId = 'league-1'; const seasonId = 'season-1'; const driverId = 'driver-1'; await seedRacingLeague({ leagueId }); await seedSeason({ leagueId, seasonId }); await seedActiveMembership({ leagueId, driverId }); const createRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({ leagueId, seasonId, track: 'Monza', car: 'GT3', scheduledAt: new Date('2025-01-10T20:00:00Z'), }); expect(createRace.isOk()).toBe(true); const { raceId } = createRace.unwrap(); const first = await context.registerForRaceUseCase.execute({ leagueId, raceId, driverId }); expect(first.isOk()).toBe(true); const second = await context.registerForRaceUseCase.execute({ leagueId, raceId, driverId }); expect(second.isErr()).toBe(true); expect(second.unwrapErr().code).toBe('ALREADY_REGISTERED'); }); it('withdraws an existing registration for an upcoming race', async () => { const leagueId = 'league-1'; const seasonId = 'season-1'; const driverId = 'driver-1'; await seedRacingLeague({ leagueId }); await seedSeason({ leagueId, seasonId, startDate: new Date('2000-01-01T00:00:00Z'), endDate: new Date('2100-12-31T23:59:59Z'), }); await seedActiveMembership({ leagueId, driverId }); const createRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({ leagueId, seasonId, track: 'Monza', car: 'GT3', scheduledAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), }); expect(createRace.isOk()).toBe(true); const { raceId } = createRace.unwrap(); const register = await context.registerForRaceUseCase.execute({ leagueId, raceId, driverId }); expect(register.isOk()).toBe(true); const withdraw = await context.withdrawFromRaceUseCase.execute({ raceId, driverId }); expect(withdraw.isOk()).toBe(true); expect(withdraw.unwrap()).toEqual({ raceId, driverId, status: 'withdrawn' }); const isRegistered = await context.raceRegistrationRepository.isRegistered(raceId, driverId); expect(isRegistered).toBe(false); }); });