350 lines
9.9 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|