394 lines
11 KiB
TypeScript
394 lines
11 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { RaceDetailViewDataBuilder } from './RaceDetailViewDataBuilder';
|
|
|
|
describe('RaceDetailViewDataBuilder', () => {
|
|
describe('happy paths', () => {
|
|
it('should transform API DTO to RaceDetailViewData correctly', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-123',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
league: {
|
|
id: 'league-456',
|
|
name: 'Test League',
|
|
description: 'Test Description',
|
|
settings: {
|
|
maxDrivers: 32,
|
|
qualifyingFormat: 'Open',
|
|
},
|
|
},
|
|
entryList: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
avatarUrl: 'avatar-url',
|
|
country: 'US',
|
|
rating: 1500,
|
|
isCurrentUser: false,
|
|
},
|
|
],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: true,
|
|
},
|
|
userResult: {
|
|
position: 5,
|
|
startPosition: 10,
|
|
positionChange: 5,
|
|
incidents: 2,
|
|
isClean: false,
|
|
isPodium: false,
|
|
ratingChange: 10,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result).toEqual({
|
|
race: {
|
|
id: 'race-123',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
league: {
|
|
id: 'league-456',
|
|
name: 'Test League',
|
|
description: 'Test Description',
|
|
settings: {
|
|
maxDrivers: 32,
|
|
qualifyingFormat: 'Open',
|
|
},
|
|
},
|
|
entryList: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
avatarUrl: 'avatar-url',
|
|
country: 'US',
|
|
rating: 1500,
|
|
isCurrentUser: false,
|
|
},
|
|
],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: true,
|
|
},
|
|
userResult: {
|
|
position: 5,
|
|
startPosition: 10,
|
|
positionChange: 5,
|
|
incidents: 2,
|
|
isClean: false,
|
|
isPodium: false,
|
|
ratingChange: 10,
|
|
},
|
|
canReopenRace: false,
|
|
});
|
|
});
|
|
|
|
it('should handle race without league', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-456',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.league).toBeUndefined();
|
|
});
|
|
|
|
it('should handle race without user result', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-789',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.userResult).toBeUndefined();
|
|
});
|
|
|
|
it('should handle multiple entries in entry list', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-101',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
avatarUrl: 'avatar-url',
|
|
country: 'US',
|
|
rating: 1500,
|
|
isCurrentUser: false,
|
|
},
|
|
{
|
|
id: 'driver-2',
|
|
name: 'Driver 2',
|
|
avatarUrl: 'avatar-url',
|
|
country: 'UK',
|
|
rating: 1600,
|
|
isCurrentUser: true,
|
|
},
|
|
],
|
|
registration: {
|
|
isUserRegistered: true,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.entryList).toHaveLength(2);
|
|
});
|
|
});
|
|
|
|
describe('data transformation', () => {
|
|
it('should preserve all DTO fields in the output', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-102',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
league: {
|
|
id: 'league-103',
|
|
name: 'Test League',
|
|
description: 'Test Description',
|
|
settings: {
|
|
maxDrivers: 32,
|
|
qualifyingFormat: 'Open',
|
|
},
|
|
},
|
|
entryList: [
|
|
{
|
|
id: 'driver-1',
|
|
name: 'Driver 1',
|
|
avatarUrl: 'avatar-url',
|
|
country: 'US',
|
|
rating: 1500,
|
|
isCurrentUser: false,
|
|
},
|
|
],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: true,
|
|
},
|
|
userResult: {
|
|
position: 5,
|
|
startPosition: 10,
|
|
positionChange: 5,
|
|
incidents: 2,
|
|
isClean: false,
|
|
isPodium: false,
|
|
ratingChange: 10,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.race.id).toBe(apiDto.race.id);
|
|
expect(result.race.track).toBe(apiDto.race.track);
|
|
expect(result.race.car).toBe(apiDto.race.car);
|
|
expect(result.race.scheduledAt).toBe(apiDto.race.scheduledAt);
|
|
expect(result.race.status).toBe(apiDto.race.status);
|
|
expect(result.race.sessionType).toBe(apiDto.race.sessionType);
|
|
expect(result.league?.id).toBe(apiDto.league.id);
|
|
expect(result.league?.name).toBe(apiDto.league.name);
|
|
expect(result.registration.isUserRegistered).toBe(apiDto.registration.isUserRegistered);
|
|
expect(result.registration.canRegister).toBe(apiDto.registration.canRegister);
|
|
expect(result.canReopenRace).toBe(apiDto.canReopenRace);
|
|
});
|
|
|
|
it('should not modify the input DTO', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-104',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const originalDto = { ...apiDto };
|
|
RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(apiDto).toEqual(originalDto);
|
|
});
|
|
});
|
|
|
|
describe('edge cases', () => {
|
|
it('should handle null API DTO', () => {
|
|
const result = RaceDetailViewDataBuilder.build(null);
|
|
|
|
expect(result.race.id).toBe('');
|
|
expect(result.race.track).toBe('');
|
|
expect(result.race.car).toBe('');
|
|
expect(result.race.scheduledAt).toBe('');
|
|
expect(result.race.status).toBe('scheduled');
|
|
expect(result.race.sessionType).toBe('race');
|
|
expect(result.entryList).toHaveLength(0);
|
|
expect(result.registration.isUserRegistered).toBe(false);
|
|
expect(result.registration.canRegister).toBe(false);
|
|
expect(result.canReopenRace).toBe(false);
|
|
});
|
|
|
|
it('should handle undefined API DTO', () => {
|
|
const result = RaceDetailViewDataBuilder.build(undefined);
|
|
|
|
expect(result.race.id).toBe('');
|
|
expect(result.race.track).toBe('');
|
|
expect(result.race.car).toBe('');
|
|
expect(result.race.scheduledAt).toBe('');
|
|
expect(result.race.status).toBe('scheduled');
|
|
expect(result.race.sessionType).toBe('race');
|
|
expect(result.entryList).toHaveLength(0);
|
|
expect(result.registration.isUserRegistered).toBe(false);
|
|
expect(result.registration.canRegister).toBe(false);
|
|
expect(result.canReopenRace).toBe(false);
|
|
});
|
|
|
|
it('should handle race without entry list', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-105',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'race',
|
|
},
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.entryList).toHaveLength(0);
|
|
});
|
|
|
|
it('should handle different race statuses', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-106',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'running',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.race.status).toBe('running');
|
|
});
|
|
|
|
it('should handle different session types', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-107',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'scheduled',
|
|
sessionType: 'qualifying',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: false,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.race.sessionType).toBe('qualifying');
|
|
});
|
|
|
|
it('should handle canReopenRace true', () => {
|
|
const apiDto = {
|
|
race: {
|
|
id: 'race-108',
|
|
track: 'Test Track',
|
|
car: 'Test Car',
|
|
scheduledAt: '2024-01-01T10:00:00Z',
|
|
status: 'completed',
|
|
sessionType: 'race',
|
|
},
|
|
entryList: [],
|
|
registration: {
|
|
isUserRegistered: false,
|
|
canRegister: false,
|
|
},
|
|
canReopenRace: true,
|
|
};
|
|
|
|
const result = RaceDetailViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.canReopenRace).toBe(true);
|
|
});
|
|
});
|
|
});
|