Files
gridpilot.gg/apps/website/tests/view-data/leaderboards.test.ts
Marc Mintel fb1221701d
Some checks failed
Contract Testing / contract-tests (push) Failing after 6m7s
Contract Testing / contract-snapshot (push) Failing after 4m46s
add tests
2026-01-22 11:52:42 +01:00

2054 lines
63 KiB
TypeScript

/**
* View Data Layer Tests - Leaderboards Functionality
*
* This test file covers the view data layer for leaderboards functionality.
*
* The view data layer is responsible for:
* - DTO → UI model mapping
* - Formatting, sorting, and grouping
* - Derived fields and defaults
* - UI-specific semantics
*
* This layer isolates the UI from API churn by providing a stable interface
* between the API layer and the presentation layer.
*
* Test coverage includes:
* - Leaderboard data transformation and ranking calculations
* - Driver leaderboard view models (overall, per-race, per-season)
* - Team leaderboard view models (constructor standings, team performance)
* - Leaderboard statistics and metrics formatting
* - Derived leaderboard fields (points, positions, gaps, intervals, etc.)
* - Default values and fallbacks for leaderboard views
* - Leaderboard-specific formatting (lap times, gaps, points, positions, etc.)
* - Data grouping and categorization for leaderboard components
* - Leaderboard sorting and filtering view models
* - Real-time leaderboard updates and state management
* - Historical leaderboard data transformation
* - Leaderboard comparison and trend analysis view models
*/
import { LeaderboardsViewDataBuilder } from '@/lib/builders/view-data/LeaderboardsViewDataBuilder';
import { DriverRankingsViewDataBuilder } from '@/lib/builders/view-data/DriverRankingsViewDataBuilder';
import { TeamRankingsViewDataBuilder } from '@/lib/builders/view-data/TeamRankingsViewDataBuilder';
import { WinRateDisplay } from '@/lib/display-objects/WinRateDisplay';
import { MedalDisplay } from '@/lib/display-objects/MedalDisplay';
import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';
import type { GetTeamsLeaderboardOutputDTO } from '@/lib/types/generated/GetTeamsLeaderboardOutputDTO';
import type { TeamLeaderboardItemDTO } from '@/lib/types/generated/TeamLeaderboardItemDTO';
import type { DriversLeaderboardDTO } from '@/lib/types/generated/DriversLeaderboardDTO';
describe('LeaderboardsViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform Leaderboards DTO to LeaderboardsViewData correctly', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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',
},
],
totalRaces: 250,
totalWins: 40,
activeCount: 2,
},
teams: {
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: 5,
groupsBySkillLevel: 'pro,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 = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// Verify drivers
expect(result.drivers).toHaveLength(2);
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].wins).toBe(25);
expect(result.drivers[0].podiums).toBe(60);
expect(result.drivers[0].racesCompleted).toBe(150);
expect(result.drivers[0].rank).toBe(1);
expect(result.drivers[0].avatarUrl).toBe('https://example.com/avatar1.jpg');
expect(result.drivers[0].position).toBe(1);
// Verify teams
expect(result.teams).toHaveLength(2);
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();
});
it('should handle empty driver and team arrays', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers).toEqual([]);
expect(result.teams).toEqual([]);
});
it('should handle missing avatar URLs with empty string fallback', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
id: 'driver-1',
name: 'John Doe',
rating: 1234.56,
skillLevel: 'pro',
nationality: 'USA',
racesCompleted: 150,
wins: 25,
podiums: 60,
isActive: true,
rank: 1,
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
memberCount: 15,
totalWins: 50,
totalRaces: 200,
performanceLevel: 'elite',
isRecruiting: false,
createdAt: '2023-01-01',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers[0].avatarUrl).toBe('');
expect(result.teams[0].logoUrl).toBe('');
});
it('should handle missing optional team fields with defaults', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
memberCount: 15,
totalWins: 50,
totalRaces: 200,
performanceLevel: 'elite',
isRecruiting: false,
createdAt: '2023-01-01',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.teams[0].rating).toBe(0);
expect(result.teams[0].logoUrl).toBe('');
});
it('should calculate position based on index', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{ id: 'driver-1', name: 'Driver 1', rating: 1000, skillLevel: 'pro', nationality: 'USA', racesCompleted: 100, wins: 10, podiums: 30, isActive: true, rank: 1 },
{ id: 'driver-2', name: 'Driver 2', rating: 900, skillLevel: 'advanced', nationality: 'Canada', racesCompleted: 80, wins: 8, podiums: 25, isActive: true, rank: 2 },
{ id: 'driver-3', name: 'Driver 3', rating: 800, skillLevel: 'intermediate', nationality: 'UK', racesCompleted: 60, wins: 5, podiums: 15, isActive: true, rank: 3 },
],
totalRaces: 240,
totalWins: 23,
activeCount: 3,
},
teams: {
teams: [],
recruitingCount: 1,
groupsBySkillLevel: 'elite,advanced,intermediate',
topTeams: [
{ 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' },
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers[0].position).toBe(1);
expect(result.drivers[1].position).toBe(2);
expect(result.drivers[2].position).toBe(3);
expect(result.teams[0].position).toBe(1);
expect(result.teams[1].position).toBe(2);
expect(result.teams[2].position).toBe(3);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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',
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 5,
groupsBySkillLevel: 'pro,advanced',
topTeams: [
{
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers[0].name).toBe(leaderboardsDTO.drivers.drivers[0].name);
expect(result.drivers[0].nationality).toBe(leaderboardsDTO.drivers.drivers[0].nationality);
expect(result.drivers[0].avatarUrl).toBe(leaderboardsDTO.drivers.drivers[0].avatarUrl);
expect(result.teams[0].name).toBe(leaderboardsDTO.teams.topTeams[0].name);
expect(result.teams[0].tag).toBe(leaderboardsDTO.teams.topTeams[0].tag);
expect(result.teams[0].logoUrl).toBe(leaderboardsDTO.teams.topTeams[0].logoUrl);
});
it('should not modify the input DTO', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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',
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 5,
groupsBySkillLevel: 'pro,advanced',
topTeams: [
{
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',
},
],
},
};
const originalDTO = JSON.parse(JSON.stringify(leaderboardsDTO));
LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(leaderboardsDTO).toEqual(originalDTO);
});
it('should handle large numbers correctly', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
id: 'driver-1',
name: 'John Doe',
rating: 999999.99,
skillLevel: 'pro',
nationality: 'USA',
racesCompleted: 10000,
wins: 2500,
podiums: 5000,
isActive: true,
rank: 1,
avatarUrl: 'https://example.com/avatar.jpg',
},
],
totalRaces: 10000,
totalWins: 2500,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
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.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 avatar URLs', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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,
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
logoUrl: undefined as any,
memberCount: 15,
totalWins: 50,
totalRaces: 200,
performanceLevel: 'elite',
isRecruiting: false,
createdAt: '2023-01-01',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers[0].avatarUrl).toBe('');
expect(result.teams[0].logoUrl).toBe('');
});
it('should handle null/undefined rating', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
id: 'driver-1',
name: 'John Doe',
rating: null as any,
skillLevel: 'pro',
nationality: 'USA',
racesCompleted: 150,
wins: 25,
podiums: 60,
isActive: true,
rank: 1,
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.drivers[0].rating).toBeNull();
expect(result.teams[0].rating).toBe(0);
});
it('should handle null/undefined totalWins and totalRaces', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.teams[0].totalWins).toBe(0);
expect(result.teams[0].totalRaces).toBe(0);
});
it('should handle empty performance level', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
memberCount: 15,
totalWins: 50,
totalRaces: 200,
performanceLevel: '',
isRecruiting: false,
createdAt: '2023-01-01',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.teams[0].performanceLevel).toBe('N/A');
});
});
});
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');
});
});
});
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);
});
});
});
describe('WinRateDisplay', () => {
describe('happy paths', () => {
it('should calculate win rate correctly', () => {
expect(WinRateDisplay.calculate(100, 25)).toBe('25.0');
expect(WinRateDisplay.calculate(50, 10)).toBe('20.0');
expect(WinRateDisplay.calculate(200, 50)).toBe('25.0');
});
it('should handle zero races completed', () => {
expect(WinRateDisplay.calculate(0, 0)).toBe('0.0');
expect(WinRateDisplay.calculate(0, 10)).toBe('0.0');
});
it('should handle zero wins', () => {
expect(WinRateDisplay.calculate(100, 0)).toBe('0.0');
});
it('should format rate correctly', () => {
expect(WinRateDisplay.format(25.0)).toBe('25.0%');
expect(WinRateDisplay.format(0)).toBe('0.0%');
expect(WinRateDisplay.format(100)).toBe('100.0%');
});
});
describe('edge cases', () => {
it('should handle null rate in format', () => {
expect(WinRateDisplay.format(null)).toBe('0.0%');
});
it('should handle undefined rate in format', () => {
expect(WinRateDisplay.format(undefined)).toBe('0.0%');
});
it('should handle decimal win rates', () => {
expect(WinRateDisplay.calculate(100, 25)).toBe('25.0');
expect(WinRateDisplay.calculate(100, 33)).toBe('33.0');
expect(WinRateDisplay.calculate(100, 66)).toBe('66.0');
});
it('should handle large numbers', () => {
expect(WinRateDisplay.calculate(10000, 2500)).toBe('25.0');
expect(WinRateDisplay.calculate(10000, 5000)).toBe('50.0');
});
});
});
describe('MedalDisplay', () => {
describe('happy paths', () => {
it('should return correct variant for positions', () => {
expect(MedalDisplay.getVariant(1)).toBe('warning');
expect(MedalDisplay.getVariant(2)).toBe('high');
expect(MedalDisplay.getVariant(3)).toBe('warning');
expect(MedalDisplay.getVariant(4)).toBe('low');
expect(MedalDisplay.getVariant(10)).toBe('low');
});
it('should return correct medal icon for top 3 positions', () => {
expect(MedalDisplay.getMedalIcon(1)).toBe('🏆');
expect(MedalDisplay.getMedalIcon(2)).toBe('🏆');
expect(MedalDisplay.getMedalIcon(3)).toBe('🏆');
});
it('should return null for positions outside top 3', () => {
expect(MedalDisplay.getMedalIcon(4)).toBeNull();
expect(MedalDisplay.getMedalIcon(10)).toBeNull();
expect(MedalDisplay.getMedalIcon(100)).toBeNull();
});
it('should return correct background color for positions', () => {
expect(MedalDisplay.getBg(1)).toBe('bg-warning-amber');
expect(MedalDisplay.getBg(2)).toBe('bg-gray-300');
expect(MedalDisplay.getBg(3)).toBe('bg-orange-700');
expect(MedalDisplay.getBg(4)).toBe('bg-gray-800');
expect(MedalDisplay.getBg(10)).toBe('bg-gray-800');
});
it('should return correct text color for positions', () => {
expect(MedalDisplay.getColor(1)).toBe('text-warning-amber');
expect(MedalDisplay.getColor(2)).toBe('text-gray-300');
expect(MedalDisplay.getColor(3)).toBe('text-orange-700');
expect(MedalDisplay.getColor(4)).toBe('text-gray-400');
expect(MedalDisplay.getColor(10)).toBe('text-gray-400');
});
});
describe('edge cases', () => {
it('should handle position 0', () => {
expect(MedalDisplay.getVariant(0)).toBe('low');
expect(MedalDisplay.getMedalIcon(0)).toBe('🏆');
expect(MedalDisplay.getBg(0)).toBe('bg-gray-800');
expect(MedalDisplay.getColor(0)).toBe('text-gray-400');
});
it('should handle large positions', () => {
expect(MedalDisplay.getVariant(999)).toBe('low');
expect(MedalDisplay.getMedalIcon(999)).toBeNull();
expect(MedalDisplay.getBg(999)).toBe('bg-gray-800');
expect(MedalDisplay.getColor(999)).toBe('text-gray-400');
});
it('should handle negative positions', () => {
expect(MedalDisplay.getVariant(-1)).toBe('low');
expect(MedalDisplay.getMedalIcon(-1)).toBe('🏆');
expect(MedalDisplay.getBg(-1)).toBe('bg-gray-800');
expect(MedalDisplay.getColor(-1)).toBe('text-gray-400');
});
});
});
describe('Leaderboards View Data - Cross-Component Consistency', () => {
describe('common patterns', () => {
it('should all use consistent formatting for numeric values', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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/avatar.jpg',
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [],
recruitingCount: 5,
groupsBySkillLevel: 'elite,advanced',
topTeams: [
{
id: 'team-1',
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// All numeric values should be preserved as numbers (not formatted as strings)
expect(typeof result.drivers[0].rating).toBe('number');
expect(typeof result.drivers[0].wins).toBe('number');
expect(typeof result.drivers[0].podiums).toBe('number');
expect(typeof result.drivers[0].racesCompleted).toBe('number');
expect(typeof result.drivers[0].rank).toBe('number');
expect(typeof result.teams[0].rating).toBe('number');
expect(typeof result.teams[0].totalWins).toBe('number');
expect(typeof result.teams[0].totalRaces).toBe('number');
});
it('should all handle missing data gracefully', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// All fields should have safe defaults
expect(result.drivers).toEqual([]);
expect(result.teams).toEqual([]);
});
it('should all preserve ISO timestamps for serialization', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [
{
id: 'team-1',
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-01T00:00:00Z',
},
],
recruitingCount: 0,
groupsBySkillLevel: '',
topTeams: [
{
id: 'team-1',
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-01T00:00:00Z',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// Verify that the view data model is correctly built
expect(result.teams).toHaveLength(1);
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].logoUrl).toBe('https://example.com/logo.jpg');
expect(result.teams[0].memberCount).toBe(15);
expect(result.teams[0].rating).toBe(1500);
expect(result.teams[0].totalWins).toBe(50);
expect(result.teams[0].totalRaces).toBe(200);
expect(result.teams[0].performanceLevel).toBe('elite');
expect(result.teams[0].isRecruiting).toBe(false);
expect(result.teams[0].position).toBe(1);
});
it('should all handle boolean flags correctly', () => {
const leaderboardsDTO = {
drivers: {
drivers: [],
totalRaces: 0,
totalWins: 0,
activeCount: 0,
},
teams: {
teams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
logoUrl: 'https://example.com/logo.jpg',
memberCount: 15,
rating: 1500,
totalWins: 50,
totalRaces: 200,
performanceLevel: 'elite',
isRecruiting: true,
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: false,
createdAt: '2023-06-01',
},
],
recruitingCount: 1,
groupsBySkillLevel: 'elite,advanced',
topTeams: [
{
id: 'team-1',
name: 'Racing Team Alpha',
tag: 'RTA',
logoUrl: 'https://example.com/logo.jpg',
memberCount: 15,
rating: 1500,
totalWins: 50,
totalRaces: 200,
performanceLevel: 'elite',
isRecruiting: true,
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: false,
createdAt: '2023-06-01',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
expect(result.teams[0].isRecruiting).toBe(true);
expect(result.teams[1].isRecruiting).toBe(false);
});
});
describe('data integrity', () => {
it('should maintain data consistency across transformations', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
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/avatar.jpg',
},
],
totalRaces: 150,
totalWins: 25,
activeCount: 1,
},
teams: {
teams: [
{
id: 'team-1',
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: [
{
id: 'team-1',
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// Verify derived fields match their source data
expect(result.drivers[0].position).toBe(result.drivers[0].rank);
expect(result.teams[0].position).toBe(1);
});
it('should handle complex real-world scenarios', () => {
const leaderboardsDTO = {
drivers: {
drivers: [
{
id: 'driver-1',
name: 'John Doe',
rating: 2456.78,
skillLevel: 'pro',
nationality: 'USA',
racesCompleted: 250,
wins: 45,
podiums: 120,
isActive: true,
rank: 1,
avatarUrl: 'https://example.com/avatar1.jpg',
},
{
id: 'driver-2',
name: 'Jane Smith',
rating: 2100.0,
skillLevel: 'pro',
nationality: 'Canada',
racesCompleted: 200,
wins: 35,
podiums: 100,
isActive: true,
rank: 2,
avatarUrl: 'https://example.com/avatar2.jpg',
},
{
id: 'driver-3',
name: 'Bob Johnson',
rating: 1800.0,
skillLevel: 'advanced',
nationality: 'UK',
racesCompleted: 180,
wins: 25,
podiums: 80,
isActive: true,
rank: 3,
avatarUrl: 'https://example.com/avatar3.jpg',
},
],
totalRaces: 630,
totalWins: 105,
activeCount: 3,
},
teams: {
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: 1,
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',
},
{
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',
},
],
},
};
const result = LeaderboardsViewDataBuilder.build(leaderboardsDTO);
// Verify all transformations
expect(result.drivers).toHaveLength(3);
expect(result.drivers[0].name).toBe('John Doe');
expect(result.drivers[0].rating).toBe(2456.78);
expect(result.drivers[0].rank).toBe(1);
expect(result.drivers[0].position).toBe(1);
expect(result.teams).toHaveLength(3);
expect(result.teams[0].name).toBe('Racing Team Alpha');
expect(result.teams[0].rating).toBe(1500);
expect(result.teams[0].position).toBe(1);
expect(result.teams[0].isRecruiting).toBe(false);
expect(result.teams[1].isRecruiting).toBe(true);
expect(result.teams[2].isRecruiting).toBe(false);
});
});
});