import { describe, expect, it } from 'vitest'; import { RaceListItemViewModel } from './RaceListItemViewModel'; import { RacesPageViewModel } from './RacesPageViewModel'; describe('RaceListItemViewModel', () => { const baseDto = { id: 'race-123', track: 'Spa-Francorchamps', car: 'GT3', scheduledAt: '2025-01-01T20:00:00Z', status: 'scheduled', leagueId: 'league-1', leagueName: 'Test League', strengthOfField: 2500, isUpcoming: true, isLive: false, isPast: false, }; it('maps DTO fields to properties', () => { const viewModel = new RaceListItemViewModel(baseDto); expect(viewModel.id).toBe('race-123'); expect(viewModel.track).toBe('Spa-Francorchamps'); expect(viewModel.car).toBe('GT3'); expect(viewModel.scheduledAt).toBe('2025-01-01T20:00:00Z'); expect(viewModel.status).toBe('scheduled'); expect(viewModel.leagueId).toBe('league-1'); expect(viewModel.leagueName).toBe('Test League'); expect(viewModel.strengthOfField).toBe(2500); expect(viewModel.isUpcoming).toBe(true); expect(viewModel.isLive).toBe(false); expect(viewModel.isPast).toBe(false); }); it('formats scheduled time as locale string', () => { const viewModel = new RaceListItemViewModel(baseDto); const formatted = viewModel.formattedScheduledTime; expect(formatted).toContain('2025'); }); it('computes status badge variants', () => { const scheduled = new RaceListItemViewModel({ ...baseDto, status: 'scheduled' }); const running = new RaceListItemViewModel({ ...baseDto, status: 'running' }); const completed = new RaceListItemViewModel({ ...baseDto, status: 'completed' }); const cancelled = new RaceListItemViewModel({ ...baseDto, status: 'cancelled' }); const other = new RaceListItemViewModel({ ...baseDto, status: 'unknown' }); expect(scheduled.statusBadgeVariant).toBe('info'); expect(running.statusBadgeVariant).toBe('success'); expect(completed.statusBadgeVariant).toBe('secondary'); expect(cancelled.statusBadgeVariant).toBe('danger'); expect(other.statusBadgeVariant).toBe('default'); }); }); describe('RacesPageViewModel', () => { const createDto = () => ({ races: [ { id: 'race-1', track: 'Spa', car: 'GT3', scheduledAt: '2025-01-01T20:00:00Z', status: 'scheduled', leagueId: 'league-1', leagueName: 'League 1', strengthOfField: 2500, isUpcoming: true, isLive: false, isPast: false, }, { id: 'race-2', track: 'Nürburgring', car: 'GT4', scheduledAt: '2025-01-02T20:00:00Z', status: 'running', leagueId: 'league-2', leagueName: 'League 2', strengthOfField: null, isUpcoming: true, isLive: true, isPast: false, }, { id: 'race-3', track: 'Daytona', car: 'LMP2', scheduledAt: '2024-12-31T20:00:00Z', status: 'completed', leagueId: 'league-3', leagueName: 'League 3', strengthOfField: 2000, isUpcoming: false, isLive: false, isPast: true, }, ], }); it('wraps races DTOs in RaceListItemViewModel instances', () => { const viewModel = new RacesPageViewModel(createDto()); expect(viewModel.races).toHaveLength(3); expect(viewModel.races[0]).toBeInstanceOf(RaceListItemViewModel); }); it('computes total count from races length', () => { const viewModel = new RacesPageViewModel(createDto()); expect(viewModel.totalCount).toBe(3); }); it('filters upcoming, live and past races', () => { const viewModel = new RacesPageViewModel(createDto()); expect(viewModel.upcomingRaces).toHaveLength(2); expect(viewModel.liveRaces).toHaveLength(1); expect(viewModel.pastRaces).toHaveLength(1); }); it('filters scheduled, running and completed races by status', () => { const viewModel = new RacesPageViewModel(createDto()); expect(viewModel.scheduledRaces).toHaveLength(1); expect(viewModel.runningRaces).toHaveLength(1); expect(viewModel.completedRaces).toHaveLength(1); }); });