320 lines
8.4 KiB
TypeScript
320 lines
8.4 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { ProtestDetailViewDataBuilder } from './ProtestDetailViewDataBuilder';
|
|
|
|
describe('ProtestDetailViewDataBuilder', () => {
|
|
describe('happy paths', () => {
|
|
it('should transform ProtestDetailApiDto to ProtestDetailViewData correctly', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-123',
|
|
leagueId: 'league-456',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: 'Contact at turn 3',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [
|
|
{
|
|
type: 'time_penalty',
|
|
label: 'Time Penalty',
|
|
description: 'Add time to race result',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result).toEqual({
|
|
protestId: 'protest-123',
|
|
leagueId: 'league-456',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: 'Contact at turn 3',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [
|
|
{
|
|
type: 'time_penalty',
|
|
label: 'Time Penalty',
|
|
description: 'Add time to race result',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should handle resolved status', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-456',
|
|
leagueId: 'league-789',
|
|
status: 'resolved',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 10,
|
|
description: 'Contact at turn 5',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-3',
|
|
name: 'Driver 3',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-4',
|
|
name: 'Driver 4',
|
|
},
|
|
race: {
|
|
id: 'race-2',
|
|
name: 'Test Race 2',
|
|
scheduledAt: '2024-01-02T10:00:00Z',
|
|
},
|
|
penaltyTypes: [],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.status).toBe('resolved');
|
|
});
|
|
|
|
it('should handle multiple penalty types', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-789',
|
|
leagueId: 'league-101',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 15,
|
|
description: 'Contact at turn 7',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-5',
|
|
name: 'Driver 5',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-6',
|
|
name: 'Driver 6',
|
|
},
|
|
race: {
|
|
id: 'race-3',
|
|
name: 'Test Race 3',
|
|
scheduledAt: '2024-01-03T10:00:00Z',
|
|
},
|
|
penaltyTypes: [
|
|
{
|
|
type: 'time_penalty',
|
|
label: 'Time Penalty',
|
|
description: 'Add time to race result',
|
|
},
|
|
{
|
|
type: 'grid_penalty',
|
|
label: 'Grid Penalty',
|
|
description: 'Drop grid positions',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.penaltyTypes).toHaveLength(2);
|
|
});
|
|
});
|
|
|
|
describe('data transformation', () => {
|
|
it('should preserve all DTO fields in the output', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-101',
|
|
leagueId: 'league-102',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: 'Contact at turn 3',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [
|
|
{
|
|
type: 'time_penalty',
|
|
label: 'Time Penalty',
|
|
description: 'Add time to race result',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.protestId).toBe(protestDetailApiDto.id);
|
|
expect(result.leagueId).toBe(protestDetailApiDto.leagueId);
|
|
expect(result.status).toBe(protestDetailApiDto.status);
|
|
expect(result.submittedAt).toBe(protestDetailApiDto.submittedAt);
|
|
expect(result.incident).toEqual(protestDetailApiDto.incident);
|
|
expect(result.protestingDriver).toEqual(protestDetailApiDto.protestingDriver);
|
|
expect(result.accusedDriver).toEqual(protestDetailApiDto.accusedDriver);
|
|
expect(result.race).toEqual(protestDetailApiDto.race);
|
|
expect(result.penaltyTypes).toEqual(protestDetailApiDto.penaltyTypes);
|
|
});
|
|
|
|
it('should not modify the input DTO', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-102',
|
|
leagueId: 'league-103',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: 'Contact at turn 3',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [],
|
|
};
|
|
|
|
const originalDto = { ...protestDetailApiDto };
|
|
ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(protestDetailApiDto).toEqual(originalDto);
|
|
});
|
|
});
|
|
|
|
describe('edge cases', () => {
|
|
it('should handle different status values', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-103',
|
|
leagueId: 'league-104',
|
|
status: 'rejected',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: 'Contact at turn 3',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.status).toBe('rejected');
|
|
});
|
|
|
|
it('should handle lap 0', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-104',
|
|
leagueId: 'league-105',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 0,
|
|
description: 'Contact at start',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.incident.lap).toBe(0);
|
|
});
|
|
|
|
it('should handle empty description', () => {
|
|
const protestDetailApiDto = {
|
|
id: 'protest-105',
|
|
leagueId: 'league-106',
|
|
status: 'pending',
|
|
submittedAt: '2024-01-01T10:00:00Z',
|
|
incident: {
|
|
lap: 5,
|
|
description: '',
|
|
},
|
|
protestingDriver: {
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
},
|
|
accusedDriver: {
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
},
|
|
race: {
|
|
id: 'race-1',
|
|
name: 'Test Race',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
},
|
|
penaltyTypes: [],
|
|
};
|
|
|
|
const result = ProtestDetailViewDataBuilder.build(protestDetailApiDto);
|
|
|
|
expect(result.incident.description).toBe('');
|
|
});
|
|
});
|
|
});
|