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

352 lines
12 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { LeaguesViewDataBuilder } from './LeaguesViewDataBuilder';
import type { AllLeaguesWithCapacityAndScoringDTO } from '@/lib/types/generated/AllLeaguesWithCapacityAndScoringDTO';
describe('LeaguesViewDataBuilder', () => {
describe('happy paths', () => {
it('should transform AllLeaguesWithCapacityAndScoringDTO to LeaguesViewData correctly', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Pro League',
description: 'A competitive league for experienced drivers',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
qualifyingFormat: 'Solo • 32 max',
},
usedSlots: 25,
category: 'competitive',
scoring: {
gameId: 'game-1',
gameName: 'iRacing',
primaryChampionshipType: 'Single Championship',
scoringPresetId: 'preset-1',
scoringPresetName: 'Standard',
dropPolicySummary: 'Drop 2 worst races',
scoringPatternSummary: 'Points based on finish position',
},
timingSummary: 'Weekly races on Sundays',
logoUrl: 'https://example.com/logo.png',
pendingJoinRequestsCount: 3,
pendingProtestsCount: 1,
walletBalance: 1000,
},
{
id: 'league-2',
name: 'Rookie League',
description: null,
ownerId: 'owner-2',
createdAt: '2024-02-01T00:00:00.000Z',
settings: {
maxDrivers: 16,
qualifyingFormat: 'Solo • 16 max',
},
usedSlots: 10,
category: 'rookie',
scoring: {
gameId: 'game-1',
gameName: 'iRacing',
primaryChampionshipType: 'Single Championship',
scoringPresetId: 'preset-2',
scoringPresetName: 'Rookie',
dropPolicySummary: 'No drops',
scoringPatternSummary: 'Points based on finish position',
},
timingSummary: 'Bi-weekly races',
logoUrl: null,
pendingJoinRequestsCount: 0,
pendingProtestsCount: 0,
walletBalance: 0,
},
],
totalCount: 2,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues).toHaveLength(2);
expect(result.leagues[0]).toEqual({
id: 'league-1',
name: 'Pro League',
description: 'A competitive league for experienced drivers',
logoUrl: 'https://example.com/logo.png',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
maxDrivers: 32,
usedDriverSlots: 25,
activeDriversCount: undefined,
nextRaceAt: undefined,
maxTeams: undefined,
usedTeamSlots: undefined,
structureSummary: 'Solo • 32 max',
timingSummary: 'Weekly races on Sundays',
category: 'competitive',
scoring: {
gameId: 'game-1',
gameName: 'iRacing',
primaryChampionshipType: 'Single Championship',
scoringPresetId: 'preset-1',
scoringPresetName: 'Standard',
dropPolicySummary: 'Drop 2 worst races',
scoringPatternSummary: 'Points based on finish position',
},
});
expect(result.leagues[1]).toEqual({
id: 'league-2',
name: 'Rookie League',
description: null,
logoUrl: null,
ownerId: 'owner-2',
createdAt: '2024-02-01T00:00:00.000Z',
maxDrivers: 16,
usedDriverSlots: 10,
activeDriversCount: undefined,
nextRaceAt: undefined,
maxTeams: undefined,
usedTeamSlots: undefined,
structureSummary: 'Solo • 16 max',
timingSummary: 'Bi-weekly races',
category: 'rookie',
scoring: {
gameId: 'game-1',
gameName: 'iRacing',
primaryChampionshipType: 'Single Championship',
scoringPresetId: 'preset-2',
scoringPresetName: 'Rookie',
dropPolicySummary: 'No drops',
scoringPatternSummary: 'Points based on finish position',
},
});
});
it('should handle empty leagues list', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [],
totalCount: 0,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues).toHaveLength(0);
});
it('should handle leagues with missing optional fields', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Minimal League',
description: '',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 20,
},
usedSlots: 5,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].description).toBe(null);
expect(result.leagues[0].logoUrl).toBe(null);
expect(result.leagues[0].category).toBe(null);
expect(result.leagues[0].scoring).toBeUndefined();
expect(result.leagues[0].timingSummary).toBe('');
});
});
describe('data transformation', () => {
it('should preserve all DTO fields in the output', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Test League',
description: 'Test description',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
qualifyingFormat: 'Solo • 32 max',
},
usedSlots: 20,
category: 'test',
scoring: {
gameId: 'game-1',
gameName: 'Test Game',
primaryChampionshipType: 'Test Type',
scoringPresetId: 'preset-1',
scoringPresetName: 'Test Preset',
dropPolicySummary: 'Test drop policy',
scoringPatternSummary: 'Test pattern',
},
timingSummary: 'Test timing',
logoUrl: 'https://example.com/test.png',
pendingJoinRequestsCount: 5,
pendingProtestsCount: 2,
walletBalance: 500,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].id).toBe(leaguesDTO.leagues[0].id);
expect(result.leagues[0].name).toBe(leaguesDTO.leagues[0].name);
expect(result.leagues[0].description).toBe(leaguesDTO.leagues[0].description);
expect(result.leagues[0].logoUrl).toBe(leaguesDTO.leagues[0].logoUrl);
expect(result.leagues[0].ownerId).toBe(leaguesDTO.leagues[0].ownerId);
expect(result.leagues[0].createdAt).toBe(leaguesDTO.leagues[0].createdAt);
expect(result.leagues[0].maxDrivers).toBe(leaguesDTO.leagues[0].settings.maxDrivers);
expect(result.leagues[0].usedDriverSlots).toBe(leaguesDTO.leagues[0].usedSlots);
expect(result.leagues[0].structureSummary).toBe(leaguesDTO.leagues[0].settings.qualifyingFormat);
expect(result.leagues[0].timingSummary).toBe(leaguesDTO.leagues[0].timingSummary);
expect(result.leagues[0].category).toBe(leaguesDTO.leagues[0].category);
expect(result.leagues[0].scoring).toEqual(leaguesDTO.leagues[0].scoring);
});
it('should not modify the input DTO', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Test League',
description: 'Test description',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
qualifyingFormat: 'Solo • 32 max',
},
usedSlots: 20,
category: 'test',
scoring: {
gameId: 'game-1',
gameName: 'Test Game',
primaryChampionshipType: 'Test Type',
scoringPresetId: 'preset-1',
scoringPresetName: 'Test Preset',
dropPolicySummary: 'Test drop policy',
scoringPatternSummary: 'Test pattern',
},
timingSummary: 'Test timing',
logoUrl: 'https://example.com/test.png',
pendingJoinRequestsCount: 5,
pendingProtestsCount: 2,
walletBalance: 500,
},
],
totalCount: 1,
};
const originalDTO = JSON.parse(JSON.stringify(leaguesDTO));
LeaguesViewDataBuilder.build(leaguesDTO);
expect(leaguesDTO).toEqual(originalDTO);
});
});
describe('edge cases', () => {
it('should handle leagues with very long descriptions', () => {
const longDescription = 'A'.repeat(1000);
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Test League',
description: longDescription,
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
},
usedSlots: 20,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].description).toBe(longDescription);
});
it('should handle leagues with special characters in name', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'League & Co. (2024)',
description: 'Test league',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
},
usedSlots: 20,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].name).toBe('League & Co. (2024)');
});
it('should handle leagues with zero used slots', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Empty League',
description: 'No members yet',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
},
usedSlots: 0,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].usedDriverSlots).toBe(0);
});
it('should handle leagues with maximum capacity', () => {
const leaguesDTO: AllLeaguesWithCapacityAndScoringDTO = {
leagues: [
{
id: 'league-1',
name: 'Full League',
description: 'At maximum capacity',
ownerId: 'owner-1',
createdAt: '2024-01-01T00:00:00.000Z',
settings: {
maxDrivers: 32,
},
usedSlots: 32,
},
],
totalCount: 1,
};
const result = LeaguesViewDataBuilder.build(leaguesDTO);
expect(result.leagues[0].usedDriverSlots).toBe(32);
expect(result.leagues[0].maxDrivers).toBe(32);
});
});
});