383 lines
12 KiB
TypeScript
383 lines
12 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { DriversViewDataBuilder } from './DriversViewDataBuilder';
|
|
import type { DriversLeaderboardDTO } from '@/lib/types/generated/DriversLeaderboardDTO';
|
|
|
|
describe('DriversViewDataBuilder', () => {
|
|
describe('happy paths', () => {
|
|
it('should transform DriversLeaderboardDTO to DriversViewData correctly', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 1234.56,
|
|
skillLevel: 'Pro',
|
|
category: 'Elite',
|
|
nationality: 'USA',
|
|
racesCompleted: 150,
|
|
wins: 25,
|
|
podiums: 60,
|
|
isActive: true,
|
|
rank: 1,
|
|
avatarUrl: 'https://example.com/john.jpg',
|
|
},
|
|
{
|
|
id: 'driver-2',
|
|
name: 'Jane Smith',
|
|
rating: 1100.75,
|
|
skillLevel: 'Advanced',
|
|
category: 'Pro',
|
|
nationality: 'Canada',
|
|
racesCompleted: 120,
|
|
wins: 15,
|
|
podiums: 45,
|
|
isActive: true,
|
|
rank: 2,
|
|
avatarUrl: 'https://example.com/jane.jpg',
|
|
},
|
|
],
|
|
totalRaces: 270,
|
|
totalWins: 40,
|
|
activeCount: 2,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
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].ratingLabel).toBe('1,235');
|
|
expect(result.drivers[0].skillLevel).toBe('Pro');
|
|
expect(result.drivers[0].category).toBe('Elite');
|
|
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].isActive).toBe(true);
|
|
expect(result.drivers[0].rank).toBe(1);
|
|
expect(result.drivers[0].avatarUrl).toBe('https://example.com/john.jpg');
|
|
|
|
expect(result.drivers[1].id).toBe('driver-2');
|
|
expect(result.drivers[1].name).toBe('Jane Smith');
|
|
expect(result.drivers[1].rating).toBe(1100.75);
|
|
expect(result.drivers[1].ratingLabel).toBe('1,101');
|
|
expect(result.drivers[1].skillLevel).toBe('Advanced');
|
|
expect(result.drivers[1].category).toBe('Pro');
|
|
expect(result.drivers[1].nationality).toBe('Canada');
|
|
expect(result.drivers[1].racesCompleted).toBe(120);
|
|
expect(result.drivers[1].wins).toBe(15);
|
|
expect(result.drivers[1].podiums).toBe(45);
|
|
expect(result.drivers[1].isActive).toBe(true);
|
|
expect(result.drivers[1].rank).toBe(2);
|
|
expect(result.drivers[1].avatarUrl).toBe('https://example.com/jane.jpg');
|
|
|
|
expect(result.totalRaces).toBe(270);
|
|
expect(result.totalRacesLabel).toBe('270');
|
|
expect(result.totalWins).toBe(40);
|
|
expect(result.totalWinsLabel).toBe('40');
|
|
expect(result.activeCount).toBe(2);
|
|
expect(result.activeCountLabel).toBe('2');
|
|
expect(result.totalDriversLabel).toBe('2');
|
|
});
|
|
|
|
it('should handle drivers with missing optional fields', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
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,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].category).toBeUndefined();
|
|
expect(result.drivers[0].avatarUrl).toBeUndefined();
|
|
});
|
|
|
|
it('should handle empty drivers array', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [],
|
|
totalRaces: 0,
|
|
totalWins: 0,
|
|
activeCount: 0,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers).toEqual([]);
|
|
expect(result.totalRaces).toBe(0);
|
|
expect(result.totalRacesLabel).toBe('0');
|
|
expect(result.totalWins).toBe(0);
|
|
expect(result.totalWinsLabel).toBe('0');
|
|
expect(result.activeCount).toBe(0);
|
|
expect(result.activeCountLabel).toBe('0');
|
|
expect(result.totalDriversLabel).toBe('0');
|
|
});
|
|
});
|
|
|
|
describe('data transformation', () => {
|
|
it('should preserve all DTO fields in the output', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 1234.56,
|
|
skillLevel: 'Pro',
|
|
category: 'Elite',
|
|
nationality: 'USA',
|
|
racesCompleted: 150,
|
|
wins: 25,
|
|
podiums: 60,
|
|
isActive: true,
|
|
rank: 1,
|
|
avatarUrl: 'https://example.com/john.jpg',
|
|
},
|
|
],
|
|
totalRaces: 150,
|
|
totalWins: 25,
|
|
activeCount: 1,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].name).toBe(driversDTO.drivers[0].name);
|
|
expect(result.drivers[0].nationality).toBe(driversDTO.drivers[0].nationality);
|
|
expect(result.drivers[0].skillLevel).toBe(driversDTO.drivers[0].skillLevel);
|
|
expect(result.totalRaces).toBe(driversDTO.totalRaces);
|
|
expect(result.totalWins).toBe(driversDTO.totalWins);
|
|
expect(result.activeCount).toBe(driversDTO.activeCount);
|
|
});
|
|
|
|
it('should not modify the input DTO', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 1234.56,
|
|
skillLevel: 'Pro',
|
|
category: 'Elite',
|
|
nationality: 'USA',
|
|
racesCompleted: 150,
|
|
wins: 25,
|
|
podiums: 60,
|
|
isActive: true,
|
|
rank: 1,
|
|
avatarUrl: 'https://example.com/john.jpg',
|
|
},
|
|
],
|
|
totalRaces: 150,
|
|
totalWins: 25,
|
|
activeCount: 1,
|
|
};
|
|
|
|
const originalDTO = JSON.parse(JSON.stringify(driversDTO));
|
|
DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(driversDTO).toEqual(originalDTO);
|
|
});
|
|
|
|
it('should transform all numeric fields to formatted strings where appropriate', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
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,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
// Rating label should be a formatted string
|
|
expect(typeof result.drivers[0].ratingLabel).toBe('string');
|
|
expect(result.drivers[0].ratingLabel).toBe('1,235');
|
|
|
|
// Total counts should be formatted strings
|
|
expect(typeof result.totalRacesLabel).toBe('string');
|
|
expect(result.totalRacesLabel).toBe('150');
|
|
expect(typeof result.totalWinsLabel).toBe('string');
|
|
expect(result.totalWinsLabel).toBe('25');
|
|
expect(typeof result.activeCountLabel).toBe('string');
|
|
expect(result.activeCountLabel).toBe('1');
|
|
expect(typeof result.totalDriversLabel).toBe('string');
|
|
expect(result.totalDriversLabel).toBe('1');
|
|
});
|
|
|
|
it('should handle large numbers correctly', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 999999.99,
|
|
skillLevel: 'Pro',
|
|
nationality: 'USA',
|
|
racesCompleted: 10000,
|
|
wins: 2500,
|
|
podiums: 5000,
|
|
isActive: true,
|
|
rank: 1,
|
|
},
|
|
],
|
|
totalRaces: 10000,
|
|
totalWins: 2500,
|
|
activeCount: 1,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].ratingLabel).toBe('1,000,000');
|
|
expect(result.totalRacesLabel).toBe('10,000');
|
|
expect(result.totalWinsLabel).toBe('2,500');
|
|
expect(result.activeCountLabel).toBe('1');
|
|
expect(result.totalDriversLabel).toBe('1');
|
|
});
|
|
});
|
|
|
|
describe('edge cases', () => {
|
|
it('should handle null/undefined rating', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 0,
|
|
skillLevel: 'Pro',
|
|
nationality: 'USA',
|
|
racesCompleted: 150,
|
|
wins: 25,
|
|
podiums: 60,
|
|
isActive: true,
|
|
rank: 1,
|
|
},
|
|
],
|
|
totalRaces: 150,
|
|
totalWins: 25,
|
|
activeCount: 1,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].ratingLabel).toBe('0');
|
|
});
|
|
|
|
it('should handle drivers with no category', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
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,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].category).toBeUndefined();
|
|
});
|
|
|
|
it('should handle inactive drivers', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'John Doe',
|
|
rating: 1234.56,
|
|
skillLevel: 'Pro',
|
|
nationality: 'USA',
|
|
racesCompleted: 150,
|
|
wins: 25,
|
|
podiums: 60,
|
|
isActive: false,
|
|
rank: 1,
|
|
},
|
|
],
|
|
totalRaces: 150,
|
|
totalWins: 25,
|
|
activeCount: 0,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.drivers[0].isActive).toBe(false);
|
|
expect(result.activeCount).toBe(0);
|
|
expect(result.activeCountLabel).toBe('0');
|
|
});
|
|
});
|
|
|
|
describe('derived fields', () => {
|
|
it('should correctly calculate total drivers label', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{ 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.75, skillLevel: 'Advanced', nationality: 'Canada', racesCompleted: 120, wins: 15, podiums: 45, isActive: true, rank: 2 },
|
|
{ id: 'driver-3', name: 'Bob Wilson', rating: 950.25, skillLevel: 'Intermediate', nationality: 'UK', racesCompleted: 80, wins: 5, podiums: 20, isActive: false, rank: 3 },
|
|
],
|
|
totalRaces: 350,
|
|
totalWins: 45,
|
|
activeCount: 2,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.totalDriversLabel).toBe('3');
|
|
});
|
|
|
|
it('should correctly calculate active count', () => {
|
|
const driversDTO: DriversLeaderboardDTO = {
|
|
drivers: [
|
|
{ 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.75, skillLevel: 'Advanced', nationality: 'Canada', racesCompleted: 120, wins: 15, podiums: 45, isActive: true, rank: 2 },
|
|
{ id: 'driver-3', name: 'Bob Wilson', rating: 950.25, skillLevel: 'Intermediate', nationality: 'UK', racesCompleted: 80, wins: 5, podiums: 20, isActive: false, rank: 3 },
|
|
],
|
|
totalRaces: 350,
|
|
totalWins: 45,
|
|
activeCount: 2,
|
|
};
|
|
|
|
const result = DriversViewDataBuilder.build(driversDTO);
|
|
|
|
expect(result.activeCount).toBe(2);
|
|
expect(result.activeCountLabel).toBe('2');
|
|
});
|
|
});
|
|
});
|