import { describe, expect, it } from 'vitest'; import type { RaceResultDTO } from '../types/generated/RaceResultDTO'; import type { RaceResultsDetailDTO } from '../types/generated/RaceResultsDetailDTO'; import { RaceResultsDetailViewModel } from './RaceResultsDetailViewModel'; import { RaceResultViewModel } from './RaceResultViewModel'; const createResult = (overrides: Partial = {}): RaceResultDTO => ({ driverId: 'driver-1', driverName: 'Driver One', avatarUrl: 'https://example.com/avatar.jpg', position: 2, startPosition: 3, incidents: 1, fastestLap: 90.5, positionChange: 1, isPodium: true, isClean: true, ...overrides, }); const createDto = (overrides: Partial = {}): RaceResultsDetailDTO & { results?: RaceResultDTO[] } => ({ raceId: 'race-1', track: 'Spa', ...overrides, }); describe('RaceResultsDetailViewModel', () => { it('maps basic fields and wraps results into view models', () => { const dto = createDto({ results: [createResult({ driverId: 'driver-1' }), createResult({ driverId: 'driver-2' })], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); expect(viewModel.raceId).toBe('race-1'); expect(viewModel.track).toBe('Spa'); expect(viewModel.results).toHaveLength(2); expect(viewModel.results[0]).toBeInstanceOf(RaceResultViewModel); }); it('sorts results by position', () => { const dto = createDto({ results: [ createResult({ driverId: 'driver-1', position: 3 }), createResult({ driverId: 'driver-2', position: 1 }), createResult({ driverId: 'driver-3', position: 2 }), ], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); const byPosition = viewModel.resultsByPosition; expect(byPosition.map(r => r.position)).toEqual([1, 2, 3]); }); it('sorts results by fastest lap', () => { const dto = createDto({ results: [ createResult({ driverId: 'driver-1', fastestLap: 95 }), createResult({ driverId: 'driver-2', fastestLap: 90 }), createResult({ driverId: 'driver-3', fastestLap: 100 }), ], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); const byLap = viewModel.resultsByFastestLap; expect(byLap.map(r => r.fastestLap)).toEqual([90, 95, 100]); }); it('filters clean drivers', () => { const dto = createDto({ results: [ createResult({ driverId: 'driver-1', isClean: true }), createResult({ driverId: 'driver-2', isClean: false }), ], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); const clean = viewModel.cleanDrivers; expect(clean).toHaveLength(1); expect(clean[0].driverId).toBe('driver-1'); }); it('finds current user result by driver id', () => { const dto = createDto({ results: [ createResult({ driverId: 'driver-1' }), createResult({ driverId: 'driver-2' }), ], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-2'); expect(viewModel.currentUserResult?.driverId).toBe('driver-2'); }); it('computes stats for total drivers, clean rate and average incidents', () => { const dto = createDto({ results: [ createResult({ driverId: 'driver-1', isClean: true, incidents: 0 }), createResult({ driverId: 'driver-2', isClean: false, incidents: 4 }), ], }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); const stats = viewModel.stats; expect(stats.totalDrivers).toBe(2); expect(stats.cleanRate).toBeCloseTo(50); expect(stats.averageIncidents).toBeCloseTo(2); }); it('returns zeroed stats when there are no results', () => { const dto = createDto({ results: [] }); const viewModel = new RaceResultsDetailViewModel(dto, 'driver-1'); const stats = viewModel.stats; expect(stats.totalDrivers).toBe(0); expect(stats.cleanRate).toBe(0); expect(stats.averageIncidents).toBe(0); }); });