import { describe, expect, it } from 'vitest'; import type { RaceDetailLeagueDTO } from '@/lib/types/generated/RaceDetailLeagueDTO'; import type { RaceDetailRaceDTO } from '@/lib/types/generated/RaceDetailRaceDTO'; import type { RaceDetailRegistrationDTO } from '@/lib/types/generated/RaceDetailRegistrationDTO'; import type { RaceDetailUserResultDTO } from '@/lib/types/generated/RaceDetailUserResultDTO'; import type { RaceDetailEntryDTO } from '@/lib/types/RaceDetailEntryDTO'; import { RaceDetailViewModel } from './RaceDetailViewModel'; describe('RaceDetailViewModel', () => { const createMockRace = (overrides?: Partial): RaceDetailRaceDTO => ({ id: 'race-123', title: 'Test Race', scheduledAt: '2023-12-31T20:00:00Z', status: 'upcoming', ...overrides, }); const createMockLeague = (): RaceDetailLeagueDTO => ({ id: 'league-123', name: 'Test League', }); const createMockRegistration = ( overrides?: Partial ): RaceDetailRegistrationDTO => ({ isRegistered: false, canRegister: true, ...overrides, }); it('should create instance with all properties', () => { const race = createMockRace(); const league = createMockLeague(); const entries: RaceDetailEntryDTO[] = []; const registration = createMockRegistration(); const userResult: RaceDetailUserResultDTO | null = null; const viewModel = new RaceDetailViewModel({ race, league, entryList: entries, registration, userResult, }, 'current-driver'); expect(viewModel.race).toBe(race); expect(viewModel.league).toBe(league); expect(viewModel.entryList).toHaveLength(0); expect(viewModel.registration).toBe(registration); expect(viewModel.userResult).toBe(userResult); }); it('should handle null race and league', () => { const viewModel = new RaceDetailViewModel({ race: null, league: null, entryList: [], registration: createMockRegistration(), userResult: null, }); expect(viewModel.race).toBeNull(); expect(viewModel.league).toBeNull(); }); it('should return correct isRegistered value', () => { const registeredVm = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ isRegistered: true }), userResult: null, }); const notRegisteredVm = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ isRegistered: false }), userResult: null, }); expect(registeredVm.isRegistered).toBe(true); expect(notRegisteredVm.isRegistered).toBe(false); }); it('should return correct canRegister value', () => { const canRegisterVm = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ canRegister: true }), userResult: null, }); const cannotRegisterVm = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ canRegister: false }), userResult: null, }); expect(canRegisterVm.canRegister).toBe(true); expect(cannotRegisterVm.canRegister).toBe(false); }); it('should format race status correctly', () => { const upcomingVm = new RaceDetailViewModel({ race: createMockRace({ status: 'upcoming' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); const liveVm = new RaceDetailViewModel({ race: createMockRace({ status: 'live' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); const finishedVm = new RaceDetailViewModel({ race: createMockRace({ status: 'finished' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(upcomingVm.raceStatusDisplay).toBe('Upcoming'); expect(liveVm.raceStatusDisplay).toBe('Live'); expect(finishedVm.raceStatusDisplay).toBe('Finished'); }); it('should return Unknown for status when race is null', () => { const viewModel = new RaceDetailViewModel({ race: null, league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(viewModel.raceStatusDisplay).toBe('Unknown'); }); it('should format scheduled time correctly', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace({ scheduledAt: '2023-12-31T20:00:00Z' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); const formatted = viewModel.formattedScheduledTime; expect(formatted).toContain('2023'); expect(formatted).toContain('12/31'); }); it('should return empty string for formatted time when race is null', () => { const viewModel = new RaceDetailViewModel({ race: null, league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(viewModel.formattedScheduledTime).toBe(''); }); it('should return correct entry count', () => { const entries: RaceDetailEntryDTO[] = [ { driverId: 'driver-1', carId: 'car-1' }, { driverId: 'driver-2', carId: 'car-2' }, { driverId: 'driver-3', carId: 'car-3' }, ] as RaceDetailEntryDTO[]; const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: entries, registration: createMockRegistration(), userResult: null, }); expect(viewModel.entryCount).toBe(3); }); it('should return true for hasResults when userResult exists', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: { position: 1, lapTime: 90.5 } as RaceDetailUserResultDTO, }); expect(viewModel.hasResults).toBe(true); }); it('should return false for hasResults when userResult is null', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(viewModel.hasResults).toBe(false); }); it('should return correct registration status message when registered', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ isRegistered: true }), userResult: null, }); expect(viewModel.registrationStatusMessage).toBe('You are registered for this race'); }); it('should return correct registration status message when can register', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ isRegistered: false, canRegister: true }), userResult: null, }); expect(viewModel.registrationStatusMessage).toBe('You can register for this race'); }); it('should return correct registration status message when cannot register', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration({ isRegistered: false, canRegister: false }), userResult: null, }); expect(viewModel.registrationStatusMessage).toBe('Registration not available'); }); it('should expose canReopenRace for completed and cancelled statuses', () => { const completedVm = new RaceDetailViewModel({ race: createMockRace({ status: 'completed' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); const cancelledVm = new RaceDetailViewModel({ race: createMockRace({ status: 'cancelled' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); const upcomingVm = new RaceDetailViewModel({ race: createMockRace({ status: 'upcoming' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(completedVm.canReopenRace).toBe(true); expect(cancelledVm.canReopenRace).toBe(true); expect(upcomingVm.canReopenRace).toBe(false); }); it('should handle error property', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace(), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, error: 'Failed to load race details', }); expect(viewModel.error).toBe('Failed to load race details'); }); it('should handle custom race status', () => { const viewModel = new RaceDetailViewModel({ race: createMockRace({ status: 'cancelled' }), league: createMockLeague(), entryList: [], registration: createMockRegistration(), userResult: null, }); expect(viewModel.raceStatusDisplay).toBe('cancelled'); }); });