view models
This commit is contained in:
140
apps/website/lib/view-models/RaceStewardingViewModel.test.ts
Normal file
140
apps/website/lib/view-models/RaceStewardingViewModel.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { RaceStewardingViewModel } from './RaceStewardingViewModel';
|
||||
|
||||
const createRaceStewardingDto = () => ({
|
||||
raceDetail: {
|
||||
race: {
|
||||
id: 'race-1',
|
||||
track: 'Spa-Francorchamps',
|
||||
scheduledAt: '2024-01-01T20:00:00Z',
|
||||
status: 'completed',
|
||||
},
|
||||
league: {
|
||||
id: 'league-1',
|
||||
name: 'Test League',
|
||||
},
|
||||
},
|
||||
protests: {
|
||||
protests: [
|
||||
{
|
||||
id: 'p1',
|
||||
protestingDriverId: 'd1',
|
||||
accusedDriverId: 'd2',
|
||||
incident: { lap: 1, description: 'Turn 1 divebomb' },
|
||||
filedAt: '2024-01-01T21:00:00Z',
|
||||
status: 'pending',
|
||||
},
|
||||
{
|
||||
id: 'p2',
|
||||
protestingDriverId: 'd3',
|
||||
accusedDriverId: 'd4',
|
||||
incident: { lap: 5, description: 'Blocking' },
|
||||
filedAt: '2024-01-01T21:05:00Z',
|
||||
status: 'under_review',
|
||||
},
|
||||
{
|
||||
id: 'p3',
|
||||
protestingDriverId: 'd5',
|
||||
accusedDriverId: 'd6',
|
||||
incident: { lap: 10, description: 'Contact' },
|
||||
filedAt: '2024-01-01T21:10:00Z',
|
||||
status: 'upheld',
|
||||
},
|
||||
{
|
||||
id: 'p4',
|
||||
protestingDriverId: 'd7',
|
||||
accusedDriverId: 'd8',
|
||||
incident: { lap: 12, description: 'Off-track overtake' },
|
||||
filedAt: '2024-01-01T21:15:00Z',
|
||||
status: 'dismissed',
|
||||
},
|
||||
{
|
||||
id: 'p5',
|
||||
protestingDriverId: 'd9',
|
||||
accusedDriverId: 'd10',
|
||||
incident: { lap: 15, description: 'Withdrawn protest' },
|
||||
filedAt: '2024-01-01T21:20:00Z',
|
||||
status: 'withdrawn',
|
||||
},
|
||||
],
|
||||
driverMap: {
|
||||
d1: { id: 'd1', name: 'Driver 1' },
|
||||
d2: { id: 'd2', name: 'Driver 2' },
|
||||
},
|
||||
},
|
||||
penalties: {
|
||||
penalties: [
|
||||
{
|
||||
id: 'pen1',
|
||||
driverId: 'd2',
|
||||
type: 'time',
|
||||
value: 5,
|
||||
reason: 'Avoidable contact',
|
||||
},
|
||||
{
|
||||
id: 'pen2',
|
||||
driverId: 'd3',
|
||||
type: 'points',
|
||||
value: 2,
|
||||
reason: 'Reckless driving',
|
||||
},
|
||||
],
|
||||
driverMap: {
|
||||
d3: { id: 'd3', name: 'Driver 3' },
|
||||
d4: { id: 'd4', name: 'Driver 4' },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('RaceStewardingViewModel', () => {
|
||||
it('maps core race, league, protests, penalties and driver map', () => {
|
||||
const dto = createRaceStewardingDto();
|
||||
|
||||
const viewModel = new RaceStewardingViewModel(dto as any);
|
||||
|
||||
expect(viewModel.race).toEqual(dto.raceDetail.race);
|
||||
expect(viewModel.league).toEqual(dto.raceDetail.league);
|
||||
expect(viewModel.protests).toEqual(dto.protests.protests);
|
||||
expect(viewModel.penalties).toEqual(dto.penalties.penalties);
|
||||
expect(viewModel.driverMap).toEqual({
|
||||
...dto.protests.driverMap,
|
||||
...dto.penalties.driverMap,
|
||||
});
|
||||
});
|
||||
|
||||
it('derives pending and resolved protest buckets and counts', () => {
|
||||
const dto = createRaceStewardingDto();
|
||||
|
||||
const viewModel = new RaceStewardingViewModel(dto as any);
|
||||
|
||||
const pendingIds = viewModel.pendingProtests.map(p => p.id);
|
||||
const resolvedIds = viewModel.resolvedProtests.map(p => p.id);
|
||||
|
||||
expect(pendingIds.sort()).toEqual(['p1', 'p2']);
|
||||
expect(resolvedIds.sort()).toEqual(['p3', 'p4', 'p5']);
|
||||
expect(viewModel.pendingCount).toBe(2);
|
||||
expect(viewModel.resolvedCount).toBe(3);
|
||||
});
|
||||
|
||||
it('derives penalties count from penalties list', () => {
|
||||
const dto = createRaceStewardingDto();
|
||||
|
||||
const viewModel = new RaceStewardingViewModel(dto as any);
|
||||
|
||||
expect(viewModel.penaltiesCount).toBe(2);
|
||||
});
|
||||
|
||||
it('handles empty protests and penalties gracefully', () => {
|
||||
const dto = createRaceStewardingDto();
|
||||
dto.protests.protests = [];
|
||||
dto.penalties.penalties = [];
|
||||
|
||||
const viewModel = new RaceStewardingViewModel(dto as any);
|
||||
|
||||
expect(viewModel.pendingProtests).toEqual([]);
|
||||
expect(viewModel.resolvedProtests).toEqual([]);
|
||||
expect(viewModel.pendingCount).toBe(0);
|
||||
expect(viewModel.resolvedCount).toBe(0);
|
||||
expect(viewModel.penaltiesCount).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user