Files
gridpilot.gg/apps/website/lib/builders/view-data/DriverRankingsViewDataBuilder.test.ts
Marc Mintel 1f4f837282
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m58s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data tests
2026-01-22 18:06:46 +01:00

442 lines
13 KiB
TypeScript

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