Files
gridpilot.gg/tests/unit/website/LeagueScheduleViewDataBuilder.test.ts
2026-01-21 22:36:01 +01:00

387 lines
11 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { LeagueScheduleViewDataBuilder } from '../../../apps/website/lib/builders/view-data/LeagueScheduleViewDataBuilder';
import type { LeagueScheduleApiDto } from '../../../apps/website/lib/types/tbd/LeagueScheduleApiDto';
describe('LeagueScheduleViewDataBuilder', () => {
const mockApiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-1',
name: 'Race 1',
date: '2024-02-01T18:00:00Z',
track: 'Track A',
car: 'Car A',
sessionType: 'Qualifying',
},
{
id: 'race-2',
name: 'Race 2',
date: '2024-02-08T18:00:00Z',
track: 'Track B',
car: 'Car B',
sessionType: 'Race',
},
{
id: 'race-3',
name: 'Race 3',
date: '2024-02-15T18:00:00Z',
track: 'Track C',
car: 'Car C',
sessionType: 'Race',
},
],
};
describe('build()', () => {
it('should transform all races correctly', () => {
const result = LeagueScheduleViewDataBuilder.build(mockApiDto);
expect(result.leagueId).toBe('league-123');
expect(result.races).toHaveLength(3);
// Check first race
expect(result.races[0].id).toBe('race-1');
expect(result.races[0].name).toBe('Race 1');
expect(result.races[0].scheduledAt).toBe('2024-02-01T18:00:00Z');
expect(result.races[0].track).toBe('Track A');
expect(result.races[0].car).toBe('Car A');
expect(result.races[0].sessionType).toBe('Qualifying');
});
it('should mark past races correctly', () => {
const now = new Date();
const pastDate = new Date(now.getTime() - 86400000).toISOString(); // 1 day ago
const futureDate = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-past',
name: 'Past Race',
date: pastDate,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
{
id: 'race-future',
name: 'Future Race',
date: futureDate,
track: 'Track B',
car: 'Car B',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].isPast).toBe(true);
expect(result.races[0].isUpcoming).toBe(false);
expect(result.races[0].status).toBe('completed');
expect(result.races[1].isPast).toBe(false);
expect(result.races[1].isUpcoming).toBe(true);
expect(result.races[1].status).toBe('scheduled');
});
it('should mark upcoming races correctly', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-future',
name: 'Future Race',
date: futureDate,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].isPast).toBe(false);
expect(result.races[0].isUpcoming).toBe(true);
expect(result.races[0].status).toBe('scheduled');
});
it('should handle empty schedule', () => {
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.leagueId).toBe('league-123');
expect(result.races).toHaveLength(0);
});
it('should handle races with missing optional fields', () => {
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-1',
name: 'Race 1',
date: '2024-02-01T18:00:00Z',
track: undefined,
car: undefined,
sessionType: undefined,
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].track).toBeUndefined();
expect(result.races[0].car).toBeUndefined();
expect(result.races[0].sessionType).toBeUndefined();
});
it('should handle current driver ID parameter', () => {
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456');
expect(result.currentDriverId).toBe('driver-456');
});
it('should handle admin permission parameter', () => {
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456', true);
expect(result.isAdmin).toBe(true);
expect(result.races[0].canEdit).toBe(true);
expect(result.races[0].canReschedule).toBe(true);
});
it('should handle non-admin permission parameter', () => {
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456', false);
expect(result.isAdmin).toBe(false);
expect(result.races[0].canEdit).toBe(false);
expect(result.races[0].canReschedule).toBe(false);
});
it('should handle default admin parameter as false', () => {
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456');
expect(result.isAdmin).toBe(false);
expect(result.races[0].canEdit).toBe(false);
expect(result.races[0].canReschedule).toBe(false);
});
it('should handle registration status for upcoming races', () => {
const now = new Date();
const futureDate = new Date(now.getTime() + 86400000).toISOString();
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-future',
name: 'Future Race',
date: futureDate,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].isUserRegistered).toBe(false);
expect(result.races[0].canRegister).toBe(true);
});
it('should handle registration status for past races', () => {
const now = new Date();
const pastDate = new Date(now.getTime() - 86400000).toISOString();
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-past',
name: 'Past Race',
date: pastDate,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].isUserRegistered).toBe(false);
expect(result.races[0].canRegister).toBe(false);
});
it('should handle races exactly at current time', () => {
const now = new Date();
const exactDate = now.toISOString();
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-exact',
name: 'Exact Race',
date: exactDate,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
// Race at exact current time is considered upcoming (not past)
// because the comparison uses < (strictly less than)
expect(result.races[0].isPast).toBe(false);
expect(result.races[0].isUpcoming).toBe(true);
expect(result.races[0].status).toBe('scheduled');
});
it('should handle races with different session types', () => {
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-qualifying',
name: 'Qualifying',
date: '2024-02-01T18:00:00Z',
track: 'Track A',
car: 'Car A',
sessionType: 'Qualifying',
},
{
id: 'race-practice',
name: 'Practice',
date: '2024-02-02T18:00:00Z',
track: 'Track B',
car: 'Car B',
sessionType: 'Practice',
},
{
id: 'race-race',
name: 'Race',
date: '2024-02-03T18:00:00Z',
track: 'Track C',
car: 'Car C',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].sessionType).toBe('Qualifying');
expect(result.races[1].sessionType).toBe('Practice');
expect(result.races[2].sessionType).toBe('Race');
});
it('should handle races without session type', () => {
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-1',
name: 'Race 1',
date: '2024-02-01T18:00:00Z',
track: 'Track A',
car: 'Car A',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].sessionType).toBeUndefined();
});
it('should handle races with empty track and car', () => {
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-1',
name: 'Race 1',
date: '2024-02-01T18:00:00Z',
track: '',
car: '',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races[0].track).toBe('');
expect(result.races[0].car).toBe('');
});
it('should handle multiple races with mixed dates', () => {
const now = new Date();
const pastDate1 = new Date(now.getTime() - 172800000).toISOString(); // 2 days ago
const pastDate2 = new Date(now.getTime() - 86400000).toISOString(); // 1 day ago
const futureDate1 = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
const futureDate2 = new Date(now.getTime() + 172800000).toISOString(); // 2 days from now
const apiDto: LeagueScheduleApiDto = {
leagueId: 'league-123',
races: [
{
id: 'race-past-2',
name: 'Past Race 2',
date: pastDate1,
track: 'Track A',
car: 'Car A',
sessionType: 'Race',
},
{
id: 'race-past-1',
name: 'Past Race 1',
date: pastDate2,
track: 'Track B',
car: 'Car B',
sessionType: 'Race',
},
{
id: 'race-future-1',
name: 'Future Race 1',
date: futureDate1,
track: 'Track C',
car: 'Car C',
sessionType: 'Race',
},
{
id: 'race-future-2',
name: 'Future Race 2',
date: futureDate2,
track: 'Track D',
car: 'Car D',
sessionType: 'Race',
},
],
};
const result = LeagueScheduleViewDataBuilder.build(apiDto);
expect(result.races).toHaveLength(4);
expect(result.races[0].isPast).toBe(true);
expect(result.races[1].isPast).toBe(true);
expect(result.races[2].isPast).toBe(false);
expect(result.races[3].isPast).toBe(false);
});
});
});