import { describe, it, expect } from 'vitest'; import { TeamRankingsViewDataBuilder } from './TeamRankingsViewDataBuilder'; import type { GetTeamsLeaderboardOutputDTO } from '@/lib/types/generated/GetTeamsLeaderboardOutputDTO'; describe('TeamRankingsViewDataBuilder', () => { describe('happy paths', () => { it('should transform GetTeamsLeaderboardOutputDTO to TeamRankingsViewData correctly', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo1.jpg', memberCount: 15, rating: 1500, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, { id: 'team-2', name: 'Speed Demons', tag: 'SD', logoUrl: 'https://example.com/logo2.jpg', memberCount: 8, rating: 1200, totalWins: 20, totalRaces: 150, performanceLevel: 'advanced', isRecruiting: true, createdAt: '2023-06-01', }, { id: 'team-3', name: 'Rookie Racers', tag: 'RR', logoUrl: 'https://example.com/logo3.jpg', memberCount: 5, rating: 800, totalWins: 5, totalRaces: 50, performanceLevel: 'intermediate', isRecruiting: false, createdAt: '2023-09-01', }, ], recruitingCount: 5, groupsBySkillLevel: 'elite,advanced,intermediate', topTeams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo1.jpg', memberCount: 15, rating: 1500, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, { id: 'team-2', name: 'Speed Demons', tag: 'SD', logoUrl: 'https://example.com/logo2.jpg', memberCount: 8, rating: 1200, totalWins: 20, totalRaces: 150, performanceLevel: 'advanced', isRecruiting: true, createdAt: '2023-06-01', }, ], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); // Verify teams expect(result.teams).toHaveLength(3); expect(result.teams[0].id).toBe('team-1'); expect(result.teams[0].name).toBe('Racing Team Alpha'); expect(result.teams[0].tag).toBe('RTA'); expect(result.teams[0].memberCount).toBe(15); expect(result.teams[0].totalWins).toBe(50); expect(result.teams[0].totalRaces).toBe(200); expect(result.teams[0].logoUrl).toBe('https://example.com/logo1.jpg'); expect(result.teams[0].position).toBe(1); expect(result.teams[0].isRecruiting).toBe(false); expect(result.teams[0].performanceLevel).toBe('elite'); expect(result.teams[0].rating).toBe(1500); expect(result.teams[0].category).toBeUndefined(); // Verify podium (top 3) expect(result.podium).toHaveLength(3); expect(result.podium[0].id).toBe('team-1'); expect(result.podium[0].position).toBe(1); expect(result.podium[1].id).toBe('team-2'); expect(result.podium[1].position).toBe(2); expect(result.podium[2].id).toBe('team-3'); expect(result.podium[2].position).toBe(3); // Verify recruiting count expect(result.recruitingCount).toBe(5); }); it('should handle empty team array', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams).toEqual([]); expect(result.podium).toEqual([]); expect(result.recruitingCount).toBe(0); }); it('should handle less than 3 teams for podium', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo1.jpg', memberCount: 15, rating: 1500, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, { id: 'team-2', name: 'Speed Demons', tag: 'SD', logoUrl: 'https://example.com/logo2.jpg', memberCount: 8, rating: 1200, totalWins: 20, totalRaces: 150, performanceLevel: 'advanced', isRecruiting: true, createdAt: '2023-06-01', }, ], recruitingCount: 2, groupsBySkillLevel: 'elite,advanced', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams).toHaveLength(2); expect(result.podium).toHaveLength(2); expect(result.podium[0].position).toBe(1); expect(result.podium[1].position).toBe(2); }); it('should handle missing avatar URLs with empty string fallback', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', memberCount: 15, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].logoUrl).toBe(''); }); it('should calculate position based on index', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Team 1', tag: 'T1', memberCount: 10, totalWins: 30, totalRaces: 150, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01' }, { id: 'team-2', name: 'Team 2', tag: 'T2', memberCount: 8, totalWins: 20, totalRaces: 120, performanceLevel: 'advanced', isRecruiting: true, createdAt: '2023-02-01' }, { id: 'team-3', name: 'Team 3', tag: 'T3', memberCount: 6, totalWins: 10, totalRaces: 80, performanceLevel: 'intermediate', isRecruiting: false, createdAt: '2023-03-01' }, { id: 'team-4', name: 'Team 4', tag: 'T4', memberCount: 4, totalWins: 5, totalRaces: 40, performanceLevel: 'beginner', isRecruiting: true, createdAt: '2023-04-01' }, ], recruitingCount: 2, groupsBySkillLevel: 'elite,advanced,intermediate,beginner', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].position).toBe(1); expect(result.teams[1].position).toBe(2); expect(result.teams[2].position).toBe(3); expect(result.teams[3].position).toBe(4); }); }); describe('data transformation', () => { it('should preserve all DTO fields in the output', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-123', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo.jpg', memberCount: 15, rating: 1500, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 5, groupsBySkillLevel: 'elite,advanced', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].name).toBe(teamDTO.teams[0].name); expect(result.teams[0].tag).toBe(teamDTO.teams[0].tag); expect(result.teams[0].logoUrl).toBe(teamDTO.teams[0].logoUrl); expect(result.teams[0].memberCount).toBe(teamDTO.teams[0].memberCount); expect(result.teams[0].rating).toBe(teamDTO.teams[0].rating); expect(result.teams[0].totalWins).toBe(teamDTO.teams[0].totalWins); expect(result.teams[0].totalRaces).toBe(teamDTO.teams[0].totalRaces); expect(result.teams[0].performanceLevel).toBe(teamDTO.teams[0].performanceLevel); expect(result.teams[0].isRecruiting).toBe(teamDTO.teams[0].isRecruiting); }); it('should not modify the input DTO', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-123', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo.jpg', memberCount: 15, rating: 1500, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 5, groupsBySkillLevel: 'elite,advanced', topTeams: [], }; const originalDTO = JSON.parse(JSON.stringify(teamDTO)); TeamRankingsViewDataBuilder.build(teamDTO); expect(teamDTO).toEqual(originalDTO); }); it('should handle large numbers correctly', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: 'https://example.com/logo.jpg', memberCount: 100, rating: 999999, totalWins: 5000, totalRaces: 10000, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].rating).toBe(999999); expect(result.teams[0].totalWins).toBe(5000); expect(result.teams[0].totalRaces).toBe(10000); }); }); describe('edge cases', () => { it('should handle null/undefined logo URLs', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', logoUrl: null as any, memberCount: 15, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].logoUrl).toBe(''); }); it('should handle null/undefined rating', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', memberCount: 15, rating: null as any, totalWins: 50, totalRaces: 200, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].rating).toBe(0); }); it('should handle null/undefined totalWins and totalRaces', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', memberCount: 15, totalWins: null as any, totalRaces: null as any, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].totalWins).toBe(0); expect(result.teams[0].totalRaces).toBe(0); }); it('should handle empty performance level', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Racing Team Alpha', tag: 'RTA', memberCount: 15, totalWins: 50, totalRaces: 200, performanceLevel: '', isRecruiting: false, createdAt: '2023-01-01', }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].performanceLevel).toBe('N/A'); }); it('should handle position 0', () => { const teamDTO: GetTeamsLeaderboardOutputDTO = { teams: [ { id: 'team-1', name: 'Team 1', tag: 'T1', memberCount: 10, totalWins: 30, totalRaces: 150, performanceLevel: 'elite', isRecruiting: false, createdAt: '2023-01-01' }, ], recruitingCount: 0, groupsBySkillLevel: '', topTeams: [], }; const result = TeamRankingsViewDataBuilder.build(teamDTO); expect(result.teams[0].position).toBe(1); }); }); });