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); }); }); });