import { describe, it, expect } from 'vitest'; import { DriverRankingsViewDataBuilder } from './DriverRankingsViewDataBuilder'; import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO'; describe('DriverRankingsViewDataBuilder', () => { describe('happy paths', () => { it('should transform DriverLeaderboardItemDTO array to DriverRankingsViewData correctly', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, avatarUrl: 'https://example.com/avatar1.jpg', }, { id: 'driver-2', name: 'Jane Smith', rating: 1100.0, skillLevel: 'advanced', nationality: 'Canada', racesCompleted: 100, wins: 15, podiums: 40, isActive: true, rank: 2, avatarUrl: 'https://example.com/avatar2.jpg', }, { id: 'driver-3', name: 'Bob Johnson', rating: 950.0, skillLevel: 'intermediate', nationality: 'UK', racesCompleted: 80, wins: 10, podiums: 30, isActive: true, rank: 3, avatarUrl: 'https://example.com/avatar3.jpg', }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); // Verify drivers expect(result.drivers).toHaveLength(3); expect(result.drivers[0].id).toBe('driver-1'); expect(result.drivers[0].name).toBe('John Doe'); expect(result.drivers[0].rating).toBe(1234.56); expect(result.drivers[0].skillLevel).toBe('pro'); expect(result.drivers[0].nationality).toBe('USA'); expect(result.drivers[0].racesCompleted).toBe(150); expect(result.drivers[0].wins).toBe(25); expect(result.drivers[0].podiums).toBe(60); expect(result.drivers[0].rank).toBe(1); expect(result.drivers[0].avatarUrl).toBe('https://example.com/avatar1.jpg'); expect(result.drivers[0].winRate).toBe('16.7'); expect(result.drivers[0].medalBg).toBe('bg-warning-amber'); expect(result.drivers[0].medalColor).toBe('text-warning-amber'); // Verify podium (top 3 with special ordering: 2nd, 1st, 3rd) expect(result.podium).toHaveLength(3); expect(result.podium[0].id).toBe('driver-1'); expect(result.podium[0].name).toBe('John Doe'); expect(result.podium[0].rating).toBe(1234.56); expect(result.podium[0].wins).toBe(25); expect(result.podium[0].podiums).toBe(60); expect(result.podium[0].avatarUrl).toBe('https://example.com/avatar1.jpg'); expect(result.podium[0].position).toBe(2); // 2nd place expect(result.podium[1].id).toBe('driver-2'); expect(result.podium[1].position).toBe(1); // 1st place expect(result.podium[2].id).toBe('driver-3'); expect(result.podium[2].position).toBe(3); // 3rd place // Verify default values expect(result.searchQuery).toBe(''); expect(result.selectedSkill).toBe('all'); expect(result.sortBy).toBe('rank'); expect(result.showFilters).toBe(false); }); it('should handle empty driver array', () => { const driverDTOs: DriverLeaderboardItemDTO[] = []; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers).toEqual([]); expect(result.podium).toEqual([]); expect(result.searchQuery).toBe(''); expect(result.selectedSkill).toBe('all'); expect(result.sortBy).toBe('rank'); expect(result.showFilters).toBe(false); }); it('should handle less than 3 drivers for podium', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, avatarUrl: 'https://example.com/avatar1.jpg', }, { id: 'driver-2', name: 'Jane Smith', rating: 1100.0, skillLevel: 'advanced', nationality: 'Canada', racesCompleted: 100, wins: 15, podiums: 40, isActive: true, rank: 2, avatarUrl: 'https://example.com/avatar2.jpg', }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers).toHaveLength(2); expect(result.podium).toHaveLength(2); expect(result.podium[0].position).toBe(2); // 2nd place expect(result.podium[1].position).toBe(1); // 1st place }); it('should handle missing avatar URLs with empty string fallback', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].avatarUrl).toBe(''); expect(result.podium[0].avatarUrl).toBe(''); }); it('should calculate win rate correctly', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 100, wins: 25, podiums: 60, isActive: true, rank: 1, }, { id: 'driver-2', name: 'Jane Smith', rating: 1100.0, skillLevel: 'advanced', nationality: 'Canada', racesCompleted: 50, wins: 10, podiums: 25, isActive: true, rank: 2, }, { id: 'driver-3', name: 'Bob Johnson', rating: 950.0, skillLevel: 'intermediate', nationality: 'UK', racesCompleted: 0, wins: 0, podiums: 0, isActive: true, rank: 3, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].winRate).toBe('25.0'); expect(result.drivers[1].winRate).toBe('20.0'); expect(result.drivers[2].winRate).toBe('0.0'); }); it('should assign correct medal colors based on position', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, }, { id: 'driver-2', name: 'Jane Smith', rating: 1100.0, skillLevel: 'advanced', nationality: 'Canada', racesCompleted: 100, wins: 15, podiums: 40, isActive: true, rank: 2, }, { id: 'driver-3', name: 'Bob Johnson', rating: 950.0, skillLevel: 'intermediate', nationality: 'UK', racesCompleted: 80, wins: 10, podiums: 30, isActive: true, rank: 3, }, { id: 'driver-4', name: 'Alice Brown', rating: 800.0, skillLevel: 'beginner', nationality: 'Germany', racesCompleted: 60, wins: 5, podiums: 15, isActive: true, rank: 4, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].medalBg).toBe('bg-warning-amber'); expect(result.drivers[0].medalColor).toBe('text-warning-amber'); expect(result.drivers[1].medalBg).toBe('bg-gray-300'); expect(result.drivers[1].medalColor).toBe('text-gray-300'); expect(result.drivers[2].medalBg).toBe('bg-orange-700'); expect(result.drivers[2].medalColor).toBe('text-orange-700'); expect(result.drivers[3].medalBg).toBe('bg-gray-800'); expect(result.drivers[3].medalColor).toBe('text-gray-400'); }); }); describe('data transformation', () => { it('should preserve all DTO fields in the output', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-123', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, avatarUrl: 'https://example.com/avatar.jpg', }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].name).toBe(driverDTOs[0].name); expect(result.drivers[0].nationality).toBe(driverDTOs[0].nationality); expect(result.drivers[0].avatarUrl).toBe(driverDTOs[0].avatarUrl); expect(result.drivers[0].skillLevel).toBe(driverDTOs[0].skillLevel); }); it('should not modify the input DTO', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-123', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, avatarUrl: 'https://example.com/avatar.jpg', }, ]; const originalDTO = JSON.parse(JSON.stringify(driverDTOs)); DriverRankingsViewDataBuilder.build(driverDTOs); expect(driverDTOs).toEqual(originalDTO); }); it('should handle large numbers correctly', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 999999.99, skillLevel: 'pro', nationality: 'USA', racesCompleted: 10000, wins: 2500, podiums: 5000, isActive: true, rank: 1, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].rating).toBe(999999.99); expect(result.drivers[0].wins).toBe(2500); expect(result.drivers[0].podiums).toBe(5000); expect(result.drivers[0].racesCompleted).toBe(10000); expect(result.drivers[0].winRate).toBe('25.0'); }); }); describe('edge cases', () => { it('should handle null/undefined avatar URLs', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, avatarUrl: null as any, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].avatarUrl).toBe(''); expect(result.podium[0].avatarUrl).toBe(''); }); it('should handle null/undefined rating', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: null as any, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 1, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].rating).toBeNull(); expect(result.podium[0].rating).toBeNull(); }); it('should handle zero races completed for win rate calculation', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 0, wins: 0, podiums: 0, isActive: true, rank: 1, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].winRate).toBe('0.0'); }); it('should handle rank 0', () => { const driverDTOs: DriverLeaderboardItemDTO[] = [ { id: 'driver-1', name: 'John Doe', rating: 1234.56, skillLevel: 'pro', nationality: 'USA', racesCompleted: 150, wins: 25, podiums: 60, isActive: true, rank: 0, }, ]; const result = DriverRankingsViewDataBuilder.build(driverDTOs); expect(result.drivers[0].rank).toBe(0); expect(result.drivers[0].medalBg).toBe('bg-gray-800'); expect(result.drivers[0].medalColor).toBe('text-gray-400'); }); }); });