212 lines
6.8 KiB
TypeScript
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');
|
|
});
|
|
});
|
|
});
|