view data tests
This commit is contained in:
@@ -0,0 +1,407 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { RulebookViewDataBuilder } from './RulebookViewDataBuilder';
|
||||
import type { RulebookApiDto } from '@/lib/types/tbd/RulebookApiDto';
|
||||
|
||||
describe('RulebookViewDataBuilder', () => {
|
||||
describe('happy paths', () => {
|
||||
it('should transform RulebookApiDto to RulebookViewData correctly', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-123',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
{ sessionType: 'race', position: 2, points: 18 },
|
||||
{ sessionType: 'race', position: 3, points: 15 },
|
||||
],
|
||||
bonusSummary: [
|
||||
{ type: 'fastest_lap', points: 5, description: 'Fastest lap' },
|
||||
],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'Drop 2 worst results',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result).toEqual({
|
||||
leagueId: 'league-123',
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championshipsCount: 1,
|
||||
sessionTypes: 'race',
|
||||
dropPolicySummary: 'Drop 2 worst results',
|
||||
hasActiveDropPolicy: true,
|
||||
positionPoints: [
|
||||
{ position: 1, points: 25 },
|
||||
{ position: 2, points: 18 },
|
||||
{ position: 3, points: 15 },
|
||||
],
|
||||
bonusPoints: [
|
||||
{ type: 'fastest_lap', points: 5, description: 'Fastest lap' },
|
||||
],
|
||||
hasBonusPoints: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle championship without driver type', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-456',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'team',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.positionPoints).toEqual([{ position: 1, points: 25 }]);
|
||||
});
|
||||
|
||||
it('should handle multiple championships', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-789',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
{
|
||||
type: 'team',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.championshipsCount).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle empty bonus points', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-101',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.bonusPoints).toEqual([]);
|
||||
expect(result.hasBonusPoints).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('data transformation', () => {
|
||||
it('should preserve all DTO fields in the output', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-102',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [
|
||||
{ type: 'fastest_lap', points: 5, description: 'Fastest lap' },
|
||||
],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'Drop 2 worst results',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.leagueId).toBe(rulebookApiDto.leagueId);
|
||||
expect(result.gameName).toBe(rulebookApiDto.scoringConfig.gameName);
|
||||
expect(result.scoringPresetName).toBe(rulebookApiDto.scoringConfig.scoringPresetName);
|
||||
expect(result.dropPolicySummary).toBe(rulebookApiDto.scoringConfig.dropPolicySummary);
|
||||
});
|
||||
|
||||
it('should not modify the input DTO', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-103',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const originalDto = { ...rulebookApiDto };
|
||||
RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(rulebookApiDto).toEqual(originalDto);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle empty drop policy', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-104',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: '',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.hasActiveDropPolicy).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle drop policy with "All" keyword', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-105',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'Drop all results',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.hasActiveDropPolicy).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle multiple session types', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-106',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race', 'qualifying', 'practice'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.sessionTypes).toBe('race, qualifying, practice');
|
||||
});
|
||||
|
||||
it('should handle single session type', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-107',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.sessionTypes).toBe('race');
|
||||
});
|
||||
|
||||
it('should handle empty points preview', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-108',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.positionPoints).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle points preview with different session types', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-109',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
{ sessionType: 'qualifying', position: 1, points: 10 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.positionPoints).toEqual([{ position: 1, points: 25 }]);
|
||||
});
|
||||
|
||||
it('should handle points preview with non-sequential positions', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-110',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
{ sessionType: 'race', position: 3, points: 15 },
|
||||
{ sessionType: 'race', position: 2, points: 18 },
|
||||
],
|
||||
bonusSummary: [],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.positionPoints).toEqual([
|
||||
{ position: 1, points: 25 },
|
||||
{ position: 2, points: 18 },
|
||||
{ position: 3, points: 15 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle multiple bonus points', () => {
|
||||
const rulebookApiDto: RulebookApiDto = {
|
||||
leagueId: 'league-111',
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Standard',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
sessionTypes: ['race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'race', position: 1, points: 25 },
|
||||
],
|
||||
bonusSummary: [
|
||||
{ type: 'fastest_lap', points: 5, description: 'Fastest lap' },
|
||||
{ type: 'pole_position', points: 3, description: 'Pole position' },
|
||||
{ type: 'clean_race', points: 2, description: 'Clean race' },
|
||||
],
|
||||
},
|
||||
],
|
||||
dropPolicySummary: 'No drops',
|
||||
},
|
||||
};
|
||||
|
||||
const result = RulebookViewDataBuilder.build(rulebookApiDto);
|
||||
|
||||
expect(result.bonusPoints).toHaveLength(3);
|
||||
expect(result.hasBonusPoints).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user