Files
gridpilot.gg/apps/website/lib/builders/view-data/StewardingViewDataBuilder.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

350 lines
9.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { StewardingViewDataBuilder } from './StewardingViewDataBuilder';
import type { StewardingApiDto } from '@/lib/types/tbd/StewardingApiDto';
describe('StewardingViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform StewardingApiDto to StewardingViewData correctly', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-123',
totalPending: 5,
totalResolved: 10,
totalPenalties: 3,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1', 'protest-2'],
resolvedProtests: ['protest-3'],
penalties: ['penalty-1'],
},
],
drivers: [
{
id: 'driver-1',
name: 'Driver 1',
},
],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result).toEqual({
leagueId: 'league-123',
totalPending: 5,
totalResolved: 10,
totalPenalties: 3,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1', 'protest-2'],
resolvedProtests: ['protest-3'],
penalties: ['penalty-1'],
},
],
drivers: [
{
id: 'driver-1',
name: 'Driver 1',
},
],
});
});
it('should handle empty races and drivers', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-456',
totalPending: 0,
totalResolved: 0,
totalPenalties: 0,
races: [],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races).toHaveLength(0);
expect(result.drivers).toHaveLength(0);
});
it('should handle multiple races and drivers', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-789',
totalPending: 10,
totalResolved: 20,
totalPenalties: 5,
races: [
{
id: 'race-1',
track: 'Test Track 1',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1'],
resolvedProtests: ['protest-2'],
penalties: ['penalty-1'],
},
{
id: 'race-2',
track: 'Test Track 2',
scheduledAt: '2024-01-02T10:00:00Z',
pendingProtests: ['protest-3'],
resolvedProtests: ['protest-4'],
penalties: ['penalty-2'],
},
],
drivers: [
{
id: 'driver-1',
name: 'Driver 1',
},
{
id: 'driver-2',
name: 'Driver 2',
},
],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races).toHaveLength(2);
expect(result.drivers).toHaveLength(2);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-101',
totalPending: 5,
totalResolved: 10,
totalPenalties: 3,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1'],
resolvedProtests: ['protest-2'],
penalties: ['penalty-1'],
},
],
drivers: [
{
id: 'driver-1',
name: 'Driver 1',
},
],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.leagueId).toBe(stewardingApiDto.leagueId);
expect(result.totalPending).toBe(stewardingApiDto.totalPending);
expect(result.totalResolved).toBe(stewardingApiDto.totalResolved);
expect(result.totalPenalties).toBe(stewardingApiDto.totalPenalties);
expect(result.races).toEqual(stewardingApiDto.races);
expect(result.drivers).toEqual(stewardingApiDto.drivers);
});
it('should not modify the input DTO', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-102',
totalPending: 0,
totalResolved: 0,
totalPenalties: 0,
races: [],
drivers: [],
};
const originalDto = { ...stewardingApiDto };
StewardingViewDataBuilder.build(stewardingApiDto);
expect(stewardingApiDto).toEqual(originalDto);
});
});
describe('edge cases', () => {
it('should handle null API DTO', () => {
const result = StewardingViewDataBuilder.build(null);
expect(result.leagueId).toBeUndefined();
expect(result.totalPending).toBe(0);
expect(result.totalResolved).toBe(0);
expect(result.totalPenalties).toBe(0);
expect(result.races).toHaveLength(0);
expect(result.drivers).toHaveLength(0);
});
it('should handle undefined API DTO', () => {
const result = StewardingViewDataBuilder.build(undefined);
expect(result.leagueId).toBeUndefined();
expect(result.totalPending).toBe(0);
expect(result.totalResolved).toBe(0);
expect(result.totalPenalties).toBe(0);
expect(result.races).toHaveLength(0);
expect(result.drivers).toHaveLength(0);
});
it('should handle races without pending protests', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-103',
totalPending: 0,
totalResolved: 5,
totalPenalties: 2,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: [],
resolvedProtests: ['protest-1'],
penalties: ['penalty-1'],
},
],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races[0].pendingProtests).toHaveLength(0);
});
it('should handle races without resolved protests', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-104',
totalPending: 5,
totalResolved: 0,
totalPenalties: 2,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1'],
resolvedProtests: [],
penalties: ['penalty-1'],
},
],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races[0].resolvedProtests).toHaveLength(0);
});
it('should handle races without penalties', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-105',
totalPending: 5,
totalResolved: 10,
totalPenalties: 0,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1'],
resolvedProtests: ['protest-2'],
penalties: [],
},
],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races[0].penalties).toHaveLength(0);
});
it('should handle races with empty arrays', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-106',
totalPending: 0,
totalResolved: 0,
totalPenalties: 0,
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: [],
resolvedProtests: [],
penalties: [],
},
],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.races[0].pendingProtests).toHaveLength(0);
expect(result.races[0].resolvedProtests).toHaveLength(0);
expect(result.races[0].penalties).toHaveLength(0);
});
it('should handle drivers without name', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-107',
totalPending: 0,
totalResolved: 0,
totalPenalties: 0,
races: [],
drivers: [
{
id: 'driver-1',
name: null,
},
],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.drivers[0].name).toBeNull();
});
it('should handle count values from DTO', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-108',
totalPending: 15,
totalResolved: 25,
totalPenalties: 8,
races: [],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.totalPending).toBe(15);
expect(result.totalResolved).toBe(25);
expect(result.totalPenalties).toBe(8);
});
it('should calculate counts from arrays when not provided', () => {
const stewardingApiDto: StewardingApiDto = {
leagueId: 'league-109',
races: [
{
id: 'race-1',
track: 'Test Track',
scheduledAt: '2024-01-01T10:00:00Z',
pendingProtests: ['protest-1', 'protest-2'],
resolvedProtests: ['protest-3', 'protest-4', 'protest-5'],
penalties: ['penalty-1', 'penalty-2'],
},
],
drivers: [],
};
const result = StewardingViewDataBuilder.build(stewardingApiDto);
expect(result.totalPending).toBe(2);
expect(result.totalResolved).toBe(3);
expect(result.totalPenalties).toBe(2);
});
});
});