131 lines
4.0 KiB
TypeScript
131 lines
4.0 KiB
TypeScript
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> = {}): 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[] }> = {}): 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);
|
|
});
|
|
});
|