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); }); }); });