175 lines
5.2 KiB
TypeScript
175 lines
5.2 KiB
TypeScript
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';
|
|
|
|
describe('League Schedule - Race Management', () => {
|
|
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 schedule integration tests',
|
|
ownerId: 'driver-123',
|
|
});
|
|
|
|
await context.racingLeagueRepository.create(league);
|
|
return league;
|
|
};
|
|
|
|
const seedSeason = async (params: {
|
|
seasonId: string;
|
|
leagueId: string;
|
|
startDate: Date;
|
|
endDate: Date;
|
|
status?: 'planned' | 'active' | 'completed' | 'archived' | 'cancelled';
|
|
}) => {
|
|
const season = Season.create({
|
|
id: params.seasonId,
|
|
leagueId: params.leagueId,
|
|
gameId: 'iracing',
|
|
name: 'Season 1',
|
|
status: params.status ?? 'active',
|
|
startDate: params.startDate,
|
|
endDate: params.endDate,
|
|
});
|
|
|
|
await context.seasonRepository.add(season);
|
|
return season;
|
|
};
|
|
|
|
it('creates a race in a season schedule', async () => {
|
|
const leagueId = 'league-1';
|
|
await seedRacingLeague({ leagueId });
|
|
|
|
const seasonId = 'season-1';
|
|
await seedSeason({
|
|
seasonId,
|
|
leagueId,
|
|
startDate: new Date('2025-01-01T00:00:00Z'),
|
|
endDate: new Date('2025-01-31T23:59:59Z'),
|
|
});
|
|
|
|
const create = await context.createLeagueSeasonScheduleRaceUseCase.execute({
|
|
leagueId,
|
|
seasonId,
|
|
track: 'Monza',
|
|
car: 'GT3',
|
|
scheduledAt: new Date('2025-01-10T20:00:00Z'),
|
|
});
|
|
|
|
expect(create.isOk()).toBe(true);
|
|
const { raceId } = create.unwrap();
|
|
|
|
const schedule = await context.getLeagueScheduleUseCase.execute({ leagueId, seasonId });
|
|
expect(schedule.isOk()).toBe(true);
|
|
expect(schedule.unwrap().races.map(r => r.race.id)).toEqual([raceId]);
|
|
});
|
|
|
|
it('updates an existing scheduled race (track/car/when)', async () => {
|
|
const leagueId = 'league-1';
|
|
await seedRacingLeague({ leagueId });
|
|
|
|
const seasonId = 'season-1';
|
|
await seedSeason({
|
|
seasonId,
|
|
leagueId,
|
|
startDate: new Date('2025-01-01T00:00:00Z'),
|
|
endDate: new Date('2025-01-31T23:59:59Z'),
|
|
});
|
|
|
|
const create = await context.createLeagueSeasonScheduleRaceUseCase.execute({
|
|
leagueId,
|
|
seasonId,
|
|
track: 'Old Track',
|
|
car: 'Old Car',
|
|
scheduledAt: new Date('2025-01-10T20:00:00Z'),
|
|
});
|
|
expect(create.isOk()).toBe(true);
|
|
const { raceId } = create.unwrap();
|
|
|
|
const update = await context.updateLeagueSeasonScheduleRaceUseCase.execute({
|
|
leagueId,
|
|
seasonId,
|
|
raceId,
|
|
track: 'New Track',
|
|
car: 'New Car',
|
|
scheduledAt: new Date('2025-01-20T20:00:00Z'),
|
|
});
|
|
|
|
expect(update.isOk()).toBe(true);
|
|
|
|
const schedule = await context.getLeagueScheduleUseCase.execute({ leagueId, seasonId });
|
|
expect(schedule.isOk()).toBe(true);
|
|
const race = schedule.unwrap().races[0]?.race;
|
|
expect(race?.id).toBe(raceId);
|
|
expect(race?.track).toBe('New Track');
|
|
expect(race?.car).toBe('New Car');
|
|
expect(race?.scheduledAt.toISOString()).toBe('2025-01-20T20:00:00.000Z');
|
|
});
|
|
|
|
it('deletes a scheduled race from the season', async () => {
|
|
const leagueId = 'league-1';
|
|
await seedRacingLeague({ leagueId });
|
|
|
|
const seasonId = 'season-1';
|
|
await seedSeason({
|
|
seasonId,
|
|
leagueId,
|
|
startDate: new Date('2025-01-01T00:00:00Z'),
|
|
endDate: new Date('2025-01-31T23:59:59Z'),
|
|
});
|
|
|
|
const create = await context.createLeagueSeasonScheduleRaceUseCase.execute({
|
|
leagueId,
|
|
seasonId,
|
|
track: 'Track 1',
|
|
car: 'Car 1',
|
|
scheduledAt: new Date('2025-01-10T20:00:00Z'),
|
|
});
|
|
expect(create.isOk()).toBe(true);
|
|
const { raceId } = create.unwrap();
|
|
|
|
const pre = await context.getLeagueScheduleUseCase.execute({ leagueId, seasonId });
|
|
expect(pre.isOk()).toBe(true);
|
|
expect(pre.unwrap().races.map(r => r.race.id)).toEqual([raceId]);
|
|
|
|
const del = await context.deleteLeagueSeasonScheduleRaceUseCase.execute({ leagueId, seasonId, raceId });
|
|
expect(del.isOk()).toBe(true);
|
|
|
|
const post = await context.getLeagueScheduleUseCase.execute({ leagueId, seasonId });
|
|
expect(post.isOk()).toBe(true);
|
|
expect(post.unwrap().races).toHaveLength(0);
|
|
});
|
|
|
|
it('rejects creating a race outside the season window', async () => {
|
|
const leagueId = 'league-1';
|
|
await seedRacingLeague({ leagueId });
|
|
|
|
const seasonId = 'season-1';
|
|
await seedSeason({
|
|
seasonId,
|
|
leagueId,
|
|
startDate: new Date('2025-01-01T00:00:00Z'),
|
|
endDate: new Date('2025-01-31T23:59:59Z'),
|
|
});
|
|
|
|
const create = await context.createLeagueSeasonScheduleRaceUseCase.execute({
|
|
leagueId,
|
|
seasonId,
|
|
track: 'Track',
|
|
car: 'Car',
|
|
scheduledAt: new Date('2025-02-10T20:00:00Z'),
|
|
});
|
|
|
|
expect(create.isErr()).toBe(true);
|
|
expect(create.unwrapErr().code).toBe('RACE_OUTSIDE_SEASON_WINDOW');
|
|
});
|
|
});
|