Files
gridpilot.gg/apps/website/lib/builders/view-data/RaceResultsViewDataBuilder.test.ts
Marc Mintel 108cfbcd65
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m55s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data tests
2026-01-22 18:22:08 +01:00

776 lines
19 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { RaceResultsViewDataBuilder } from './RaceResultsViewDataBuilder';
describe('RaceResultsViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform API DTO to RaceResultsViewData correctly', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [
{
driverId: 'driver-2',
driverName: 'Driver 2',
type: 'time_penalty',
value: 5,
reason: 'Track limits',
notes: 'Warning issued',
},
],
pointsSystem: {
1: 25,
2: 18,
3: 15,
},
fastestLapTime: 120000,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result).toEqual({
raceTrack: 'Test Track',
raceScheduledAt: '2024-01-01T10:00:00Z',
totalDrivers: 20,
leagueName: 'Test League',
raceSOF: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
driverAvatar: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [
{
driverId: 'driver-2',
driverName: 'Driver 2',
type: 'time_penalty',
value: 5,
reason: 'Track limits',
notes: 'Warning issued',
},
],
pointsSystem: {
1: 25,
2: 18,
3: 15,
},
fastestLapTime: 120000,
});
});
it('should handle empty results and penalties', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 0,
},
league: {
name: 'Test League',
},
strengthOfField: null,
results: [],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results).toHaveLength(0);
expect(result.penalties).toHaveLength(0);
expect(result.raceSOF).toBeNull();
});
it('should handle multiple results and penalties', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
{
position: 2,
driverId: 'driver-2',
driverName: 'Driver 2',
avatarUrl: 'avatar-url',
country: 'UK',
car: 'Test Car',
laps: 30,
time: '1:24.000',
fastestLap: '1:21.000',
points: 18,
incidents: 1,
isCurrentUser: true,
},
],
penalties: [
{
driverId: 'driver-3',
driverName: 'Driver 3',
type: 'time_penalty',
value: 5,
reason: 'Track limits',
notes: 'Warning issued',
},
{
driverId: 'driver-4',
driverName: 'Driver 4',
type: 'grid_penalty',
value: 3,
reason: 'Qualifying infringement',
notes: null,
},
],
pointsSystem: {
1: 25,
2: 18,
3: 15,
},
fastestLapTime: 120000,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results).toHaveLength(2);
expect(result.penalties).toHaveLength(2);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {
1: 25,
2: 18,
3: 15,
},
fastestLapTime: 120000,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.raceTrack).toBe(apiDto.race.track);
expect(result.raceScheduledAt).toBe(apiDto.race.scheduledAt);
expect(result.totalDrivers).toBe(apiDto.stats.totalDrivers);
expect(result.leagueName).toBe(apiDto.league.name);
expect(result.raceSOF).toBe(apiDto.strengthOfField);
expect(result.pointsSystem).toEqual(apiDto.pointsSystem);
expect(result.fastestLapTime).toBe(apiDto.fastestLapTime);
});
it('should not modify the input DTO', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const originalDto = { ...apiDto };
RaceResultsViewDataBuilder.build(apiDto);
expect(apiDto).toEqual(originalDto);
});
});
describe('edge cases', () => {
it('should handle null API DTO', () => {
const result = RaceResultsViewDataBuilder.build(null);
expect(result.raceSOF).toBeNull();
expect(result.results).toHaveLength(0);
expect(result.penalties).toHaveLength(0);
expect(result.pointsSystem).toEqual({});
expect(result.fastestLapTime).toBe(0);
});
it('should handle undefined API DTO', () => {
const result = RaceResultsViewDataBuilder.build(undefined);
expect(result.raceSOF).toBeNull();
expect(result.results).toHaveLength(0);
expect(result.penalties).toHaveLength(0);
expect(result.pointsSystem).toEqual({});
expect(result.fastestLapTime).toBe(0);
});
it('should handle results without country', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: null,
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].country).toBe('US');
});
it('should handle results without car', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: null,
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].car).toBe('Unknown');
});
it('should handle results without laps', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: null,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].laps).toBe(0);
});
it('should handle results without time', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: null,
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].time).toBe('0:00.00');
});
it('should handle results without fastest lap', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: null,
points: 25,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].fastestLap).toBe('0.00');
});
it('should handle results without points', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: null,
incidents: 0,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].points).toBe(0);
});
it('should handle results without incidents', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: null,
isCurrentUser: false,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].incidents).toBe(0);
});
it('should handle results without isCurrentUser', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [
{
position: 1,
driverId: 'driver-1',
driverName: 'Driver 1',
avatarUrl: 'avatar-url',
country: 'US',
car: 'Test Car',
laps: 30,
time: '1:23.456',
fastestLap: '1:20.000',
points: 25,
incidents: 0,
isCurrentUser: null,
},
],
penalties: [],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.results[0].isCurrentUser).toBe(false);
});
it('should handle penalties without driver name', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [],
penalties: [
{
driverId: 'driver-1',
driverName: null,
type: 'time_penalty',
value: 5,
reason: 'Track limits',
notes: 'Warning issued',
},
],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.penalties[0].driverName).toBe('Unknown');
});
it('should handle penalties without value', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [],
penalties: [
{
driverId: 'driver-1',
driverName: 'Driver 1',
type: 'time_penalty',
value: null,
reason: 'Track limits',
notes: 'Warning issued',
},
],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.penalties[0].value).toBe(0);
});
it('should handle penalties without reason', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [],
penalties: [
{
driverId: 'driver-1',
driverName: 'Driver 1',
type: 'time_penalty',
value: 5,
reason: null,
notes: 'Warning issued',
},
],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.penalties[0].reason).toBe('Penalty applied');
});
it('should handle different penalty types', () => {
const apiDto = {
race: {
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
},
stats: {
totalDrivers: 20,
},
league: {
name: 'Test League',
},
strengthOfField: 1500,
results: [],
penalties: [
{
driverId: 'driver-1',
driverName: 'Driver 1',
type: 'grid_penalty',
value: 3,
reason: 'Qualifying infringement',
notes: null,
},
{
driverId: 'driver-2',
driverName: 'Driver 2',
type: 'points_deduction',
value: 10,
reason: 'Dangerous driving',
notes: null,
},
{
driverId: 'driver-3',
driverName: 'Driver 3',
type: 'disqualification',
value: 0,
reason: 'Technical infringement',
notes: null,
},
{
driverId: 'driver-4',
driverName: 'Driver 4',
type: 'warning',
value: 0,
reason: 'Minor infraction',
notes: null,
},
{
driverId: 'driver-5',
driverName: 'Driver 5',
type: 'license_points',
value: 2,
reason: 'Multiple incidents',
notes: null,
},
],
pointsSystem: {},
fastestLapTime: 0,
};
const result = RaceResultsViewDataBuilder.build(apiDto);
expect(result.penalties[0].type).toBe('grid_penalty');
expect(result.penalties[1].type).toBe('points_deduction');
expect(result.penalties[2].type).toBe('disqualification');
expect(result.penalties[3].type).toBe('warning');
expect(result.penalties[4].type).toBe('license_points');
});
});
});