Files
gridpilot.gg/tests/integration/leagues/schedule/GetLeagueSchedule.test.ts
2026-01-23 14:51:33 +01:00

240 lines
7.3 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';
import { Race } from '../../../../core/racing/domain/entities/Race';
describe('League Schedule - GetLeagueScheduleUseCase', () => {
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';
schedulePublished?: boolean;
}) => {
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,
...(params.schedulePublished !== undefined ? { schedulePublished: params.schedulePublished } : {}),
});
await context.seasonRepository.add(season);
return season;
};
it('returns schedule for active season and races within season window', async () => {
const leagueId = 'league-1';
await seedRacingLeague({ leagueId });
const seasonId = 'season-jan';
await seedSeason({
seasonId,
leagueId,
startDate: new Date('2025-01-01T00:00:00Z'),
endDate: new Date('2025-01-31T23:59:59Z'),
status: 'active',
});
const createRace1 = await context.createLeagueSeasonScheduleRaceUseCase.execute({
leagueId,
seasonId,
track: 'Track A',
car: 'Car A',
scheduledAt: new Date('2025-01-10T20:00:00Z'),
});
expect(createRace1.isOk()).toBe(true);
const createRace2 = await context.createLeagueSeasonScheduleRaceUseCase.execute({
leagueId,
seasonId,
track: 'Track B',
car: 'Car B',
scheduledAt: new Date('2025-01-20T20:00:00Z'),
});
expect(createRace2.isOk()).toBe(true);
const result = await context.getLeagueScheduleUseCase.execute({ leagueId });
expect(result.isOk()).toBe(true);
const value = result.unwrap();
expect(value.league.id.toString()).toBe(leagueId);
expect(value.seasonId).toBe(seasonId);
expect(value.published).toBe(false);
expect(value.races.map(r => r.race.track)).toEqual(['Track A', 'Track B']);
});
it('scopes schedule by seasonId (no season date bleed)', async () => {
const leagueId = 'league-1';
await seedRacingLeague({ leagueId });
const janSeasonId = 'season-jan';
const febSeasonId = 'season-feb';
await seedSeason({
seasonId: janSeasonId,
leagueId,
startDate: new Date('2025-01-01T00:00:00Z'),
endDate: new Date('2025-01-31T23:59:59Z'),
status: 'active',
});
await seedSeason({
seasonId: febSeasonId,
leagueId,
startDate: new Date('2025-02-01T00:00:00Z'),
endDate: new Date('2025-02-28T23:59:59Z'),
status: 'planned',
});
const janRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({
leagueId,
seasonId: janSeasonId,
track: 'Track Jan',
car: 'Car Jan',
scheduledAt: new Date('2025-01-10T20:00:00Z'),
});
expect(janRace.isOk()).toBe(true);
const febRace = await context.createLeagueSeasonScheduleRaceUseCase.execute({
leagueId,
seasonId: febSeasonId,
track: 'Track Feb',
car: 'Car Feb',
scheduledAt: new Date('2025-02-10T20:00:00Z'),
});
expect(febRace.isOk()).toBe(true);
const janResult = await context.getLeagueScheduleUseCase.execute({
leagueId,
seasonId: janSeasonId,
});
expect(janResult.isOk()).toBe(true);
const janValue = janResult.unwrap();
expect(janValue.seasonId).toBe(janSeasonId);
expect(janValue.races.map(r => r.race.track)).toEqual(['Track Jan']);
const febResult = await context.getLeagueScheduleUseCase.execute({
leagueId,
seasonId: febSeasonId,
});
expect(febResult.isOk()).toBe(true);
const febValue = febResult.unwrap();
expect(febValue.seasonId).toBe(febSeasonId);
expect(febValue.races.map(r => r.race.track)).toEqual(['Track Feb']);
});
it('returns all races when no seasons exist for league', async () => {
const leagueId = 'league-1';
await seedRacingLeague({ leagueId });
await context.raceRepository.create(
Race.create({
id: 'race-1',
leagueId,
scheduledAt: new Date('2025-01-10T20:00:00Z'),
track: 'Track 1',
car: 'Car 1',
}),
);
await context.raceRepository.create(
Race.create({
id: 'race-2',
leagueId,
scheduledAt: new Date('2025-01-15T20:00:00Z'),
track: 'Track 2',
car: 'Car 2',
}),
);
const result = await context.getLeagueScheduleUseCase.execute({ leagueId });
expect(result.isOk()).toBe(true);
const value = result.unwrap();
expect(value.seasonId).toBe('no-season');
expect(value.published).toBe(false);
expect(value.races.map(r => r.race.track)).toEqual(['Track 1', 'Track 2']);
});
it('reflects schedule published state from the selected 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'),
status: 'active',
schedulePublished: false,
});
const pre = await context.getLeagueScheduleUseCase.execute({ leagueId });
expect(pre.isOk()).toBe(true);
expect(pre.unwrap().published).toBe(false);
const publish = await context.publishLeagueSeasonScheduleUseCase.execute({ leagueId, seasonId });
expect(publish.isOk()).toBe(true);
const post = await context.getLeagueScheduleUseCase.execute({ leagueId });
expect(post.isOk()).toBe(true);
expect(post.unwrap().published).toBe(true);
});
it('returns LEAGUE_NOT_FOUND when league does not exist', async () => {
const result = await context.getLeagueScheduleUseCase.execute({ leagueId: 'missing-league' });
expect(result.isErr()).toBe(true);
expect(result.unwrapErr().code).toBe('LEAGUE_NOT_FOUND');
});
it('returns SEASON_NOT_FOUND when requested season does not belong to the league', async () => {
const leagueId = 'league-1';
await seedRacingLeague({ leagueId });
await seedSeason({
seasonId: 'season-other',
leagueId: 'league-other',
startDate: new Date('2025-01-01T00:00:00Z'),
endDate: new Date('2025-01-31T23:59:59Z'),
status: 'active',
});
const result = await context.getLeagueScheduleUseCase.execute({
leagueId,
seasonId: 'season-other',
});
expect(result.isErr()).toBe(true);
expect(result.unwrapErr().code).toBe('SEASON_NOT_FOUND');
});
});