Files
gridpilot.gg/apps/website/lib/builders/view-data/LeagueScheduleViewDataBuilder.test.ts
Marc Mintel 1f4f837282
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m58s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data tests
2026-01-22 18:06:46 +01:00

212 lines
6.8 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { LeagueScheduleViewDataBuilder } from './LeagueScheduleViewDataBuilder';
describe('LeagueScheduleViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform schedule DTO to LeagueScheduleViewData correctly', () => {
const now = new Date();
const pastDate = new Date(now.getTime() - 24 * 60 * 60 * 1000); // 1 day ago
const futureDate = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 1 day from now
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Past Race',
date: pastDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
{
id: 'race-2',
name: 'Future Race',
date: futureDate.toISOString(),
track: 'Monza',
car: 'Ferrari 488 GT3',
sessionType: 'race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto, 'driver-1', true);
expect(result.leagueId).toBe('league-1');
expect(result.races).toHaveLength(2);
expect(result.races[0].id).toBe('race-1');
expect(result.races[0].name).toBe('Past Race');
expect(result.races[0].scheduledAt).toBe(pastDate.toISOString());
expect(result.races[0].track).toBe('Spa');
expect(result.races[0].car).toBe('Porsche 911 GT3');
expect(result.races[0].sessionType).toBe('race');
expect(result.races[0].isPast).toBe(true);
expect(result.races[0].isUpcoming).toBe(false);
expect(result.races[0].status).toBe('completed');
expect(result.races[0].isUserRegistered).toBe(false);
expect(result.races[0].canRegister).toBe(false);
expect(result.races[0].canEdit).toBe(true);
expect(result.races[0].canReschedule).toBe(true);
expect(result.races[1].id).toBe('race-2');
expect(result.races[1].name).toBe('Future Race');
expect(result.races[1].scheduledAt).toBe(futureDate.toISOString());
expect(result.races[1].track).toBe('Monza');
expect(result.races[1].car).toBe('Ferrari 488 GT3');
expect(result.races[1].sessionType).toBe('race');
expect(result.races[1].isPast).toBe(false);
expect(result.races[1].isUpcoming).toBe(true);
expect(result.races[1].status).toBe('scheduled');
expect(result.races[1].isUserRegistered).toBe(false);
expect(result.races[1].canRegister).toBe(true);
expect(result.races[1].canEdit).toBe(true);
expect(result.races[1].canReschedule).toBe(true);
expect(result.currentDriverId).toBe('driver-1');
expect(result.isAdmin).toBe(true);
});
it('should handle empty races list', () => {
const apiDto = {
leagueId: 'league-1',
races: [],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.leagueId).toBe('league-1');
expect(result.races).toHaveLength(0);
});
it('should handle non-admin user', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Future Race',
date: futureDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto, 'driver-1', false);
expect(result.races[0].canEdit).toBe(false);
expect(result.races[0].canReschedule).toBe(false);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Test Race',
date: futureDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.leagueId).toBe(apiDto.leagueId);
expect(result.races[0].id).toBe(apiDto.races[0].id);
expect(result.races[0].name).toBe(apiDto.races[0].name);
expect(result.races[0].scheduledAt).toBe(apiDto.races[0].date);
expect(result.races[0].track).toBe(apiDto.races[0].track);
expect(result.races[0].car).toBe(apiDto.races[0].car);
expect(result.races[0].sessionType).toBe(apiDto.races[0].sessionType);
});
it('should not modify the input DTO', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Test Race',
date: futureDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
],
};
const originalDto = JSON.parse(JSON.stringify(apiDto));
LeagueScheduleViewDataBuilder.build(apiDto);
expect(apiDto).toEqual(originalDto);
});
});
describe('edge cases', () => {
it('should handle races with missing optional fields', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Test Race',
date: futureDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].track).toBe('Spa');
expect(result.races[0].car).toBe('Porsche 911 GT3');
expect(result.races[0].sessionType).toBe('race');
});
it('should handle races at exactly the current time', () => {
const now = new Date();
const currentRaceDate = new Date(now.getTime());
const apiDto = {
leagueId: 'league-1',
races: [
{
id: 'race-1',
name: 'Current Race',
date: currentRaceDate.toISOString(),
track: 'Spa',
car: 'Porsche 911 GT3',
sessionType: 'race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
// Race at current time should be considered past
expect(result.races[0].isPast).toBe(true);
expect(result.races[0].isUpcoming).toBe(false);
expect(result.races[0].status).toBe('completed');
});
});
});