view data tests
This commit is contained in:
@@ -0,0 +1,351 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user