465 lines
14 KiB
TypeScript
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');
|
|
});
|
|
});
|
|
});
|