website service tests
This commit is contained in:
140
apps/website/lib/services/races/RaceStewardingService.test.ts
Normal file
140
apps/website/lib/services/races/RaceStewardingService.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { describe, it, expect, vi, Mocked } from 'vitest';
|
||||
import { RaceStewardingService } from './RaceStewardingService';
|
||||
import { RacesApiClient } from '../../api/races/RacesApiClient';
|
||||
import { ProtestsApiClient } from '../../api/protests/ProtestsApiClient';
|
||||
import { PenaltiesApiClient } from '../../api/penalties/PenaltiesApiClient';
|
||||
import { RaceStewardingViewModel } from '../../view-models/RaceStewardingViewModel';
|
||||
|
||||
describe('RaceStewardingService', () => {
|
||||
let mockRacesApiClient: Mocked<RacesApiClient>;
|
||||
let mockProtestsApiClient: Mocked<ProtestsApiClient>;
|
||||
let mockPenaltiesApiClient: Mocked<PenaltiesApiClient>;
|
||||
let service: RaceStewardingService;
|
||||
|
||||
beforeEach(() => {
|
||||
mockRacesApiClient = {
|
||||
getDetail: vi.fn(),
|
||||
} as Mocked<RacesApiClient>;
|
||||
|
||||
mockProtestsApiClient = {
|
||||
getRaceProtests: vi.fn(),
|
||||
} as Mocked<ProtestsApiClient>;
|
||||
|
||||
mockPenaltiesApiClient = {
|
||||
getRacePenalties: vi.fn(),
|
||||
} as Mocked<PenaltiesApiClient>;
|
||||
|
||||
service = new RaceStewardingService(mockRacesApiClient, mockProtestsApiClient, mockPenaltiesApiClient);
|
||||
});
|
||||
|
||||
describe('getRaceStewardingData', () => {
|
||||
it('should return race stewarding data with all protests and penalties', async () => {
|
||||
const raceId = 'race-123';
|
||||
const driverId = 'driver-456';
|
||||
|
||||
const raceDetailDto = {
|
||||
race: {
|
||||
id: raceId,
|
||||
track: 'Monza',
|
||||
scheduledAt: '2023-10-01T10:00:00Z',
|
||||
status: 'completed',
|
||||
},
|
||||
league: {
|
||||
id: 'league-1',
|
||||
name: 'Test League',
|
||||
},
|
||||
};
|
||||
|
||||
const protestsDto = {
|
||||
protests: [
|
||||
{
|
||||
id: 'protest-1',
|
||||
protestingDriverId: 'driver-1',
|
||||
accusedDriverId: 'driver-2',
|
||||
incident: { lap: 5, description: 'Contact at turn 1' },
|
||||
filedAt: '2023-10-01T10:00:00Z',
|
||||
status: 'pending',
|
||||
},
|
||||
{
|
||||
id: 'protest-2',
|
||||
protestingDriverId: 'driver-3',
|
||||
accusedDriverId: 'driver-4',
|
||||
incident: { lap: 10, description: 'Off-track' },
|
||||
filedAt: '2023-10-01T10:05:00Z',
|
||||
status: 'upheld',
|
||||
},
|
||||
],
|
||||
driverMap: {
|
||||
'driver-1': { id: 'driver-1', name: 'Driver 1' },
|
||||
'driver-2': { id: 'driver-2', name: 'Driver 2' },
|
||||
'driver-3': { id: 'driver-3', name: 'Driver 3' },
|
||||
'driver-4': { id: 'driver-4', name: 'Driver 4' },
|
||||
},
|
||||
};
|
||||
|
||||
const penaltiesDto = {
|
||||
penalties: [
|
||||
{ id: 'penalty-1', driverId: 'driver-2', type: 'time', value: 5, reason: 'Incident' },
|
||||
{ id: 'penalty-2', driverId: 'driver-4', type: 'grid', value: 3, reason: 'Qualifying incident' },
|
||||
],
|
||||
driverMap: {
|
||||
'driver-2': { id: 'driver-2', name: 'Driver 2' },
|
||||
'driver-4': { id: 'driver-4', name: 'Driver 4' },
|
||||
},
|
||||
};
|
||||
|
||||
mockRacesApiClient.getDetail.mockResolvedValue(raceDetailDto as any);
|
||||
mockProtestsApiClient.getRaceProtests.mockResolvedValue(protestsDto as any);
|
||||
mockPenaltiesApiClient.getRacePenalties.mockResolvedValue(penaltiesDto as any);
|
||||
|
||||
const result = await service.getRaceStewardingData(raceId, driverId);
|
||||
|
||||
expect(mockRacesApiClient.getDetail).toHaveBeenCalledWith(raceId, driverId);
|
||||
expect(mockProtestsApiClient.getRaceProtests).toHaveBeenCalledWith(raceId);
|
||||
expect(mockPenaltiesApiClient.getRacePenalties).toHaveBeenCalledWith(raceId);
|
||||
|
||||
expect(result).toBeInstanceOf(RaceStewardingViewModel);
|
||||
expect(result.race).toEqual(raceDetailDto.race);
|
||||
expect(result.league).toEqual(raceDetailDto.league);
|
||||
expect(result.protests).toHaveLength(2);
|
||||
expect(result.penalties).toHaveLength(2);
|
||||
expect(result.pendingProtests).toHaveLength(1);
|
||||
expect(result.resolvedProtests).toHaveLength(1);
|
||||
expect(result.pendingCount).toBe(1);
|
||||
expect(result.resolvedCount).toBe(1);
|
||||
expect(result.penaltiesCount).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle empty protests and penalties', async () => {
|
||||
const raceId = 'race-123';
|
||||
const driverId = 'driver-456';
|
||||
|
||||
const raceDetailDto = {
|
||||
race: { id: raceId, track: 'Monza', scheduledAt: '2023-10-01T10:00:00Z', status: 'completed' },
|
||||
league: { id: 'league-1', name: 'Test League' },
|
||||
};
|
||||
|
||||
mockRacesApiClient.getDetail.mockResolvedValue(raceDetailDto as any);
|
||||
mockProtestsApiClient.getRaceProtests.mockResolvedValue({ protests: [], driverMap: {} } as any);
|
||||
mockPenaltiesApiClient.getRacePenalties.mockResolvedValue({ penalties: [], driverMap: {} } as any);
|
||||
|
||||
const result = await service.getRaceStewardingData(raceId, driverId);
|
||||
|
||||
expect(result.protests).toHaveLength(0);
|
||||
expect(result.penalties).toHaveLength(0);
|
||||
expect(result.pendingCount).toBe(0);
|
||||
expect(result.resolvedCount).toBe(0);
|
||||
expect(result.penaltiesCount).toBe(0);
|
||||
});
|
||||
|
||||
it('should throw error when any API call fails', async () => {
|
||||
const raceId = 'race-123';
|
||||
const driverId = 'driver-456';
|
||||
|
||||
const error = new Error('API call failed');
|
||||
mockRacesApiClient.getDetail.mockRejectedValue(error);
|
||||
|
||||
await expect(service.getRaceStewardingData(raceId, driverId)).rejects.toThrow('API call failed');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user