Files
gridpilot.gg/apps/website/lib/builders/view-data/LeagueStandingsViewDataBuilder.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

465 lines
14 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { LeagueStandingsViewDataBuilder } from './LeagueStandingsViewDataBuilder';
describe('LeagueStandingsViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform standings DTOs to LeagueStandingsViewData correctly', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: ['race-1', 'race-2'],
},
{
driverId: 'driver-2',
driver: {
id: 'driver-2',
name: 'Bob',
iracingId: '22222',
country: 'Germany',
},
points: 1100,
position: 2,
wins: 3,
podiums: 8,
races: 15,
positionChange: -1,
lastRacePoints: 15,
droppedRaceIds: [],
},
],
};
const membershipsDto = {
members: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
joinedAt: '2023-06-01T00:00:00.000Z',
},
role: 'member',
joinedAt: '2023-06-01T00:00:00.000Z',
},
{
driverId: 'driver-2',
driver: {
id: 'driver-2',
name: 'Bob',
iracingId: '22222',
country: 'Germany',
joinedAt: '2023-07-01T00:00:00.000Z',
},
role: 'member',
joinedAt: '2023-07-01T00:00:00.000Z',
},
],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.leagueId).toBe('league-1');
expect(result.isTeamChampionship).toBe(false);
expect(result.currentDriverId).toBeNull();
expect(result.isAdmin).toBe(false);
expect(result.standings).toHaveLength(2);
expect(result.standings[0].driverId).toBe('driver-1');
expect(result.standings[0].position).toBe(1);
expect(result.standings[0].totalPoints).toBe(1250);
expect(result.standings[0].racesFinished).toBe(15);
expect(result.standings[0].racesStarted).toBe(15);
expect(result.standings[0].avgFinish).toBeNull();
expect(result.standings[0].penaltyPoints).toBe(0);
expect(result.standings[0].bonusPoints).toBe(0);
expect(result.standings[0].positionChange).toBe(2);
expect(result.standings[0].lastRacePoints).toBe(25);
expect(result.standings[0].droppedRaceIds).toEqual(['race-1', 'race-2']);
expect(result.standings[0].wins).toBe(5);
expect(result.standings[0].podiums).toBe(10);
expect(result.standings[1].driverId).toBe('driver-2');
expect(result.standings[1].position).toBe(2);
expect(result.standings[1].totalPoints).toBe(1100);
expect(result.standings[1].racesFinished).toBe(15);
expect(result.standings[1].racesStarted).toBe(15);
expect(result.standings[1].avgFinish).toBeNull();
expect(result.standings[1].penaltyPoints).toBe(0);
expect(result.standings[1].bonusPoints).toBe(0);
expect(result.standings[1].positionChange).toBe(-1);
expect(result.standings[1].lastRacePoints).toBe(15);
expect(result.standings[1].droppedRaceIds).toEqual([]);
expect(result.standings[1].wins).toBe(3);
expect(result.standings[1].podiums).toBe(8);
expect(result.drivers).toHaveLength(2);
expect(result.drivers[0].id).toBe('driver-1');
expect(result.drivers[0].name).toBe('Alice');
expect(result.drivers[0].iracingId).toBe('11111');
expect(result.drivers[0].country).toBe('UK');
expect(result.drivers[0].avatarUrl).toBeNull();
expect(result.drivers[1].id).toBe('driver-2');
expect(result.drivers[1].name).toBe('Bob');
expect(result.drivers[1].iracingId).toBe('22222');
expect(result.drivers[1].country).toBe('Germany');
expect(result.drivers[1].avatarUrl).toBeNull();
expect(result.memberships).toHaveLength(2);
expect(result.memberships[0].driverId).toBe('driver-1');
expect(result.memberships[0].leagueId).toBe('league-1');
expect(result.memberships[0].role).toBe('member');
expect(result.memberships[0].joinedAt).toBe('2023-06-01T00:00:00.000Z');
expect(result.memberships[0].status).toBe('active');
expect(result.memberships[1].driverId).toBe('driver-2');
expect(result.memberships[1].leagueId).toBe('league-1');
expect(result.memberships[1].role).toBe('member');
expect(result.memberships[1].joinedAt).toBe('2023-07-01T00:00:00.000Z');
expect(result.memberships[1].status).toBe('active');
});
it('should handle empty standings and memberships', () => {
const standingsDto = {
standings: [],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.standings).toHaveLength(0);
expect(result.drivers).toHaveLength(0);
expect(result.memberships).toHaveLength(0);
});
it('should handle team championship mode', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: [],
},
],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
true
);
expect(result.isTeamChampionship).toBe(true);
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: ['race-1'],
},
],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.standings[0].driverId).toBe(standingsDto.standings[0].driverId);
expect(result.standings[0].position).toBe(standingsDto.standings[0].position);
expect(result.standings[0].totalPoints).toBe(standingsDto.standings[0].points);
expect(result.standings[0].racesFinished).toBe(standingsDto.standings[0].races);
expect(result.standings[0].racesStarted).toBe(standingsDto.standings[0].races);
expect(result.standings[0].positionChange).toBe(standingsDto.standings[0].positionChange);
expect(result.standings[0].lastRacePoints).toBe(standingsDto.standings[0].lastRacePoints);
expect(result.standings[0].droppedRaceIds).toEqual(standingsDto.standings[0].droppedRaceIds);
expect(result.standings[0].wins).toBe(standingsDto.standings[0].wins);
expect(result.standings[0].podiums).toBe(standingsDto.standings[0].podiums);
expect(result.drivers[0].id).toBe(standingsDto.standings[0].driver.id);
expect(result.drivers[0].name).toBe(standingsDto.standings[0].driver.name);
expect(result.drivers[0].iracingId).toBe(standingsDto.standings[0].driver.iracingId);
expect(result.drivers[0].country).toBe(standingsDto.standings[0].driver.country);
});
it('should not modify the input DTOs', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: ['race-1'],
},
],
};
const membershipsDto = {
members: [],
};
const originalStandings = JSON.parse(JSON.stringify(standingsDto));
const originalMemberships = JSON.parse(JSON.stringify(membershipsDto));
LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(standingsDto).toEqual(originalStandings);
expect(membershipsDto).toEqual(originalMemberships);
});
});
describe('edge cases', () => {
it('should handle standings with missing optional fields', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
},
],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.standings[0].positionChange).toBe(0);
expect(result.standings[0].lastRacePoints).toBe(0);
expect(result.standings[0].droppedRaceIds).toEqual([]);
});
it('should handle standings with missing driver field', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: undefined as any,
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: [],
},
],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.drivers).toHaveLength(0);
});
it('should handle duplicate drivers in standings', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: [],
},
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1100,
position: 2,
wins: 3,
podiums: 8,
races: 15,
positionChange: -1,
lastRacePoints: 15,
droppedRaceIds: [],
},
],
};
const membershipsDto = {
members: [],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
// Should only have one driver entry
expect(result.drivers).toHaveLength(1);
expect(result.drivers[0].id).toBe('driver-1');
});
it('should handle members with different roles', () => {
const standingsDto = {
standings: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
},
points: 1250,
position: 1,
wins: 5,
podiums: 10,
races: 15,
positionChange: 2,
lastRacePoints: 25,
droppedRaceIds: [],
},
],
};
const membershipsDto = {
members: [
{
driverId: 'driver-1',
driver: {
id: 'driver-1',
name: 'Alice',
iracingId: '11111',
country: 'UK',
joinedAt: '2023-06-01T00:00:00.000Z',
},
role: 'admin',
joinedAt: '2023-06-01T00:00:00.000Z',
},
],
};
const result = LeagueStandingsViewDataBuilder.build(
standingsDto,
membershipsDto,
'league-1',
false
);
expect(result.memberships[0].role).toBe('admin');
});
});
});