import { describe, it, expect } from 'vitest'; import { LeagueStandingsViewDataBuilder } from '../../../apps/website/lib/builders/view-data/LeagueStandingsViewDataBuilder'; import type { LeagueStandingDTO } from '../../../apps/website/lib/types/generated/LeagueStandingDTO'; import type { LeagueMemberDTO } from '../../../apps/website/lib/types/generated/LeagueMemberDTO'; describe('LeagueStandingsViewDataBuilder', () => { const mockStandings: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: 0, lastRacePoints: 25, droppedRaceIds: ['race-1', 'race-2'], }, { driverId: 'driver-2', driver: { id: 'driver-2', name: 'Jane Smith', iracingId: '67890', country: 'UK', joinedAt: '2024-01-02T00:00:00Z', }, points: 120, position: 2, wins: 2, podiums: 4, races: 10, positionChange: 1, lastRacePoints: 18, droppedRaceIds: ['race-3'], }, { driverId: 'driver-3', driver: { id: 'driver-3', name: 'Bob Wilson', iracingId: '11111', country: 'CA', joinedAt: '2024-01-03T00:00:00Z', }, points: 90, position: 3, wins: 1, podiums: 3, races: 10, positionChange: -1, lastRacePoints: 12, droppedRaceIds: [], }, ]; const mockMemberships: LeagueMemberDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, role: 'member', joinedAt: '2024-01-01T00:00:00Z', }, { driverId: 'driver-2', driver: { id: 'driver-2', name: 'Jane Smith', iracingId: '67890', country: 'UK', joinedAt: '2024-01-02T00:00:00Z', }, role: 'member', joinedAt: '2024-01-02T00:00:00Z', }, ]; describe('build()', () => { it('should transform standings correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.leagueId).toBe('league-123'); expect(result.standings).toHaveLength(3); // Check first standing expect(result.standings[0].driverId).toBe('driver-1'); expect(result.standings[0].position).toBe(1); expect(result.standings[0].totalPoints).toBe(150); expect(result.standings[0].racesFinished).toBe(10); expect(result.standings[0].racesStarted).toBe(10); expect(result.standings[0].positionChange).toBe(0); expect(result.standings[0].lastRacePoints).toBe(25); expect(result.standings[0].droppedRaceIds).toEqual(['race-1', 'race-2']); expect(result.standings[0].wins).toBe(3); expect(result.standings[0].podiums).toBe(5); }); it('should calculate position change correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].positionChange).toBe(0); // No change expect(result.standings[1].positionChange).toBe(1); // Moved up expect(result.standings[2].positionChange).toBe(-1); // Moved down }); it('should map last race points correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].lastRacePoints).toBe(25); expect(result.standings[1].lastRacePoints).toBe(18); expect(result.standings[2].lastRacePoints).toBe(12); }); it('should handle dropped race IDs correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].droppedRaceIds).toEqual(['race-1', 'race-2']); expect(result.standings[1].droppedRaceIds).toEqual(['race-3']); expect(result.standings[2].droppedRaceIds).toEqual([]); }); it('should calculate championship stats (wins, podiums)', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].wins).toBe(3); expect(result.standings[0].podiums).toBe(5); expect(result.standings[1].wins).toBe(2); expect(result.standings[1].podiums).toBe(4); expect(result.standings[2].wins).toBe(1); expect(result.standings[2].podiums).toBe(3); }); it('should extract driver metadata correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.drivers).toHaveLength(3); // Check first driver expect(result.drivers[0].id).toBe('driver-1'); expect(result.drivers[0].name).toBe('John Doe'); expect(result.drivers[0].iracingId).toBe('12345'); expect(result.drivers[0].country).toBe('US'); }); it('should convert memberships correctly', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.memberships).toHaveLength(2); // Check first membership expect(result.memberships[0].driverId).toBe('driver-1'); expect(result.memberships[0].leagueId).toBe('league-123'); expect(result.memberships[0].role).toBe('member'); expect(result.memberships[0].status).toBe('active'); }); it('should handle empty standings', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: [] }, { members: mockMemberships }, 'league-123' ); expect(result.standings).toHaveLength(0); expect(result.drivers).toHaveLength(0); }); it('should handle empty memberships', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: [] }, 'league-123' ); expect(result.memberships).toHaveLength(0); }); it('should handle missing driver objects in standings', () => { const standingsWithMissingDriver: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: 0, lastRacePoints: 25, droppedRaceIds: [], }, { driverId: 'driver-2', driver: { id: 'driver-2', name: 'Jane Smith', iracingId: '67890', country: 'UK', joinedAt: '2024-01-02T00:00:00Z', }, points: 120, position: 2, wins: 2, podiums: 4, races: 10, positionChange: 1, lastRacePoints: 18, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithMissingDriver }, { members: mockMemberships }, 'league-123' ); expect(result.drivers).toHaveLength(2); expect(result.drivers[0].id).toBe('driver-1'); expect(result.drivers[1].id).toBe('driver-2'); }); it('should handle standings with missing positionChange', () => { const standingsWithoutPositionChange: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: undefined as any, lastRacePoints: 25, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithoutPositionChange }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].positionChange).toBe(0); }); it('should handle standings with missing lastRacePoints', () => { const standingsWithoutLastRacePoints: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: 0, lastRacePoints: undefined as any, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithoutLastRacePoints }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].lastRacePoints).toBe(0); }); it('should handle standings with missing droppedRaceIds', () => { const standingsWithoutDroppedRaceIds: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: 0, lastRacePoints: 25, droppedRaceIds: undefined as any, }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithoutDroppedRaceIds }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].droppedRaceIds).toEqual([]); }); it('should handle standings with missing wins', () => { const standingsWithoutWins: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: undefined as any, podiums: 5, races: 10, positionChange: 0, lastRacePoints: 25, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithoutWins }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].wins).toBe(0); }); it('should handle standings with missing podiums', () => { const standingsWithoutPodiums: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: undefined as any, races: 10, positionChange: 0, lastRacePoints: 25, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithoutPodiums }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].podiums).toBe(0); }); it('should handle team championship mode', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123', true ); expect(result.isTeamChampionship).toBe(true); }); it('should handle non-team championship mode by default', () => { const result = LeagueStandingsViewDataBuilder.build( { standings: mockStandings }, { members: mockMemberships }, 'league-123' ); expect(result.isTeamChampionship).toBe(false); }); it('should handle standings with zero points', () => { const standingsWithZeroPoints: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 0, position: 1, wins: 0, podiums: 0, races: 10, positionChange: 0, lastRacePoints: 0, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithZeroPoints }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].totalPoints).toBe(0); expect(result.standings[0].wins).toBe(0); expect(result.standings[0].podiums).toBe(0); }); it('should handle standings with negative position change', () => { const standingsWithNegativeChange: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: -2, lastRacePoints: 25, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithNegativeChange }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].positionChange).toBe(-2); }); it('should handle standings with positive position change', () => { const standingsWithPositiveChange: LeagueStandingDTO[] = [ { driverId: 'driver-1', driver: { id: 'driver-1', name: 'John Doe', iracingId: '12345', country: 'US', joinedAt: '2024-01-01T00:00:00Z', }, points: 150, position: 1, wins: 3, podiums: 5, races: 10, positionChange: 3, lastRacePoints: 25, droppedRaceIds: [], }, ]; const result = LeagueStandingsViewDataBuilder.build( { standings: standingsWithPositiveChange }, { members: mockMemberships }, 'league-123' ); expect(result.standings[0].positionChange).toBe(3); }); }); });