import { describe, it, expect } from 'vitest'; import { LeagueStewardingViewModel, type RaceWithProtests, type Protest, type Penalty } from './LeagueStewardingViewModel'; const createProtest = (id: string, status: string): Protest => ({ id, protestingDriverId: `pd-${id}`, accusedDriverId: `ad-${id}`, incident: { lap: 1, description: 'Test incident' }, filedAt: '2024-01-01T21:00:00Z', status, }); const createPenalty = (id: string): Penalty => ({ id, driverId: `d-${id}`, type: 'time', value: 5, reason: 'Test penalty', }); const createRaceWithProtests = (id: string, pendingCount: number, resolvedCount: number, penaltiesCount: number): RaceWithProtests => ({ race: { id, track: 'Spa-Francorchamps', scheduledAt: new Date('2024-01-01T20:00:00Z'), }, pendingProtests: Array.from({ length: pendingCount }, (_, index) => createProtest(`${id}-pending-${index + 1}`, 'pending')), resolvedProtests: Array.from({ length: resolvedCount }, (_, index) => createProtest(`${id}-resolved-${index + 1}`, 'upheld')), penalties: Array.from({ length: penaltiesCount }, (_, index) => createPenalty(`${id}-pen-${index + 1}`)), }); describe('LeagueStewardingViewModel', () => { it('aggregates totals across all races', () => { const races: RaceWithProtests[] = [ createRaceWithProtests('race-1', 2, 1, 1), createRaceWithProtests('race-2', 1, 3, 2), createRaceWithProtests('race-3', 0, 0, 0), ]; const driverMap = { d1: { id: 'd1', name: 'Driver 1' }, d2: { id: 'd2', name: 'Driver 2' }, }; const viewModel = new LeagueStewardingViewModel(races, driverMap); expect(viewModel.totalPending).toBe(3); expect(viewModel.totalResolved).toBe(4); expect(viewModel.totalPenalties).toBe(3); }); it('filters races into pending and history buckets', () => { const races: RaceWithProtests[] = [ createRaceWithProtests('race-1', 2, 0, 0), // pending only createRaceWithProtests('race-2', 0, 3, 0), // history only (resolved) createRaceWithProtests('race-3', 0, 0, 2), // history only (penalties) createRaceWithProtests('race-4', 0, 0, 0), // no activity ]; const viewModel = new LeagueStewardingViewModel(races, {}); const pendingIds = viewModel.pendingRaces.map(r => r.race.id).sort(); const historyIds = viewModel.historyRaces.map(r => r.race.id).sort(); expect(pendingIds).toEqual(['race-1']); expect(historyIds).toEqual(['race-2', 'race-3']); }); it('exposes all drivers as a flat array', () => { const races: RaceWithProtests[] = [createRaceWithProtests('race-1', 0, 0, 0)]; const driverMap = { d1: { id: 'd1', name: 'Driver 1', avatarUrl: 'avatar-1.png' }, d2: { id: 'd2', name: 'Driver 2', iracingId: 'ir-2' }, }; const viewModel = new LeagueStewardingViewModel(races, driverMap); expect(viewModel.allDrivers).toHaveLength(2); expect(viewModel.allDrivers).toEqual([ driverMap.d1, driverMap.d2, ]); }); it('handles an empty dataset gracefully', () => { const viewModel = new LeagueStewardingViewModel([], {}); expect(viewModel.totalPending).toBe(0); expect(viewModel.totalResolved).toBe(0); expect(viewModel.totalPenalties).toBe(0); expect(viewModel.pendingRaces).toEqual([]); expect(viewModel.historyRaces).toEqual([]); expect(viewModel.allDrivers).toEqual([]); }); });