387 lines
11 KiB
TypeScript
387 lines
11 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { LeagueScheduleViewDataBuilder } from '../../../apps/website/lib/builders/view-data/LeagueScheduleViewDataBuilder';
|
|
import type { LeagueScheduleApiDto } from '../../../apps/website/lib/types/tbd/LeagueScheduleApiDto';
|
|
|
|
describe('LeagueScheduleViewDataBuilder', () => {
|
|
const mockApiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-1',
|
|
name: 'Race 1',
|
|
date: '2024-02-01T18:00:00Z',
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Qualifying',
|
|
},
|
|
{
|
|
id: 'race-2',
|
|
name: 'Race 2',
|
|
date: '2024-02-08T18:00:00Z',
|
|
track: 'Track B',
|
|
car: 'Car B',
|
|
sessionType: 'Race',
|
|
},
|
|
{
|
|
id: 'race-3',
|
|
name: 'Race 3',
|
|
date: '2024-02-15T18:00:00Z',
|
|
track: 'Track C',
|
|
car: 'Car C',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
describe('build()', () => {
|
|
it('should transform all races correctly', () => {
|
|
const result = LeagueScheduleViewDataBuilder.build(mockApiDto);
|
|
|
|
expect(result.leagueId).toBe('league-123');
|
|
expect(result.races).toHaveLength(3);
|
|
|
|
// Check first race
|
|
expect(result.races[0].id).toBe('race-1');
|
|
expect(result.races[0].name).toBe('Race 1');
|
|
expect(result.races[0].scheduledAt).toBe('2024-02-01T18:00:00Z');
|
|
expect(result.races[0].track).toBe('Track A');
|
|
expect(result.races[0].car).toBe('Car A');
|
|
expect(result.races[0].sessionType).toBe('Qualifying');
|
|
});
|
|
|
|
it('should mark past races correctly', () => {
|
|
const now = new Date();
|
|
const pastDate = new Date(now.getTime() - 86400000).toISOString(); // 1 day ago
|
|
const futureDate = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-past',
|
|
name: 'Past Race',
|
|
date: pastDate,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
{
|
|
id: 'race-future',
|
|
name: 'Future Race',
|
|
date: futureDate,
|
|
track: 'Track B',
|
|
car: 'Car B',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].isPast).toBe(true);
|
|
expect(result.races[0].isUpcoming).toBe(false);
|
|
expect(result.races[0].status).toBe('completed');
|
|
|
|
expect(result.races[1].isPast).toBe(false);
|
|
expect(result.races[1].isUpcoming).toBe(true);
|
|
expect(result.races[1].status).toBe('scheduled');
|
|
});
|
|
|
|
it('should mark upcoming races correctly', () => {
|
|
const now = new Date();
|
|
const futureDate = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-future',
|
|
name: 'Future Race',
|
|
date: futureDate,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].isPast).toBe(false);
|
|
expect(result.races[0].isUpcoming).toBe(true);
|
|
expect(result.races[0].status).toBe('scheduled');
|
|
});
|
|
|
|
it('should handle empty schedule', () => {
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.leagueId).toBe('league-123');
|
|
expect(result.races).toHaveLength(0);
|
|
});
|
|
|
|
it('should handle races with missing optional fields', () => {
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-1',
|
|
name: 'Race 1',
|
|
date: '2024-02-01T18:00:00Z',
|
|
track: undefined,
|
|
car: undefined,
|
|
sessionType: undefined,
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].track).toBeUndefined();
|
|
expect(result.races[0].car).toBeUndefined();
|
|
expect(result.races[0].sessionType).toBeUndefined();
|
|
});
|
|
|
|
it('should handle current driver ID parameter', () => {
|
|
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456');
|
|
|
|
expect(result.currentDriverId).toBe('driver-456');
|
|
});
|
|
|
|
it('should handle admin permission parameter', () => {
|
|
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456', true);
|
|
|
|
expect(result.isAdmin).toBe(true);
|
|
expect(result.races[0].canEdit).toBe(true);
|
|
expect(result.races[0].canReschedule).toBe(true);
|
|
});
|
|
|
|
it('should handle non-admin permission parameter', () => {
|
|
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456', false);
|
|
|
|
expect(result.isAdmin).toBe(false);
|
|
expect(result.races[0].canEdit).toBe(false);
|
|
expect(result.races[0].canReschedule).toBe(false);
|
|
});
|
|
|
|
it('should handle default admin parameter as false', () => {
|
|
const result = LeagueScheduleViewDataBuilder.build(mockApiDto, 'driver-456');
|
|
|
|
expect(result.isAdmin).toBe(false);
|
|
expect(result.races[0].canEdit).toBe(false);
|
|
expect(result.races[0].canReschedule).toBe(false);
|
|
});
|
|
|
|
it('should handle registration status for upcoming races', () => {
|
|
const now = new Date();
|
|
const futureDate = new Date(now.getTime() + 86400000).toISOString();
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-future',
|
|
name: 'Future Race',
|
|
date: futureDate,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].isUserRegistered).toBe(false);
|
|
expect(result.races[0].canRegister).toBe(true);
|
|
});
|
|
|
|
it('should handle registration status for past races', () => {
|
|
const now = new Date();
|
|
const pastDate = new Date(now.getTime() - 86400000).toISOString();
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-past',
|
|
name: 'Past Race',
|
|
date: pastDate,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].isUserRegistered).toBe(false);
|
|
expect(result.races[0].canRegister).toBe(false);
|
|
});
|
|
|
|
it('should handle races exactly at current time', () => {
|
|
const now = new Date();
|
|
const exactDate = now.toISOString();
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-exact',
|
|
name: 'Exact Race',
|
|
date: exactDate,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
// Race at exact current time is considered upcoming (not past)
|
|
// because the comparison uses < (strictly less than)
|
|
expect(result.races[0].isPast).toBe(false);
|
|
expect(result.races[0].isUpcoming).toBe(true);
|
|
expect(result.races[0].status).toBe('scheduled');
|
|
});
|
|
|
|
it('should handle races with different session types', () => {
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-qualifying',
|
|
name: 'Qualifying',
|
|
date: '2024-02-01T18:00:00Z',
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Qualifying',
|
|
},
|
|
{
|
|
id: 'race-practice',
|
|
name: 'Practice',
|
|
date: '2024-02-02T18:00:00Z',
|
|
track: 'Track B',
|
|
car: 'Car B',
|
|
sessionType: 'Practice',
|
|
},
|
|
{
|
|
id: 'race-race',
|
|
name: 'Race',
|
|
date: '2024-02-03T18:00:00Z',
|
|
track: 'Track C',
|
|
car: 'Car C',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].sessionType).toBe('Qualifying');
|
|
expect(result.races[1].sessionType).toBe('Practice');
|
|
expect(result.races[2].sessionType).toBe('Race');
|
|
});
|
|
|
|
it('should handle races without session type', () => {
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-1',
|
|
name: 'Race 1',
|
|
date: '2024-02-01T18:00:00Z',
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].sessionType).toBeUndefined();
|
|
});
|
|
|
|
it('should handle races with empty track and car', () => {
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-1',
|
|
name: 'Race 1',
|
|
date: '2024-02-01T18:00:00Z',
|
|
track: '',
|
|
car: '',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races[0].track).toBe('');
|
|
expect(result.races[0].car).toBe('');
|
|
});
|
|
|
|
it('should handle multiple races with mixed dates', () => {
|
|
const now = new Date();
|
|
const pastDate1 = new Date(now.getTime() - 172800000).toISOString(); // 2 days ago
|
|
const pastDate2 = new Date(now.getTime() - 86400000).toISOString(); // 1 day ago
|
|
const futureDate1 = new Date(now.getTime() + 86400000).toISOString(); // 1 day from now
|
|
const futureDate2 = new Date(now.getTime() + 172800000).toISOString(); // 2 days from now
|
|
|
|
const apiDto: LeagueScheduleApiDto = {
|
|
leagueId: 'league-123',
|
|
races: [
|
|
{
|
|
id: 'race-past-2',
|
|
name: 'Past Race 2',
|
|
date: pastDate1,
|
|
track: 'Track A',
|
|
car: 'Car A',
|
|
sessionType: 'Race',
|
|
},
|
|
{
|
|
id: 'race-past-1',
|
|
name: 'Past Race 1',
|
|
date: pastDate2,
|
|
track: 'Track B',
|
|
car: 'Car B',
|
|
sessionType: 'Race',
|
|
},
|
|
{
|
|
id: 'race-future-1',
|
|
name: 'Future Race 1',
|
|
date: futureDate1,
|
|
track: 'Track C',
|
|
car: 'Car C',
|
|
sessionType: 'Race',
|
|
},
|
|
{
|
|
id: 'race-future-2',
|
|
name: 'Future Race 2',
|
|
date: futureDate2,
|
|
track: 'Track D',
|
|
car: 'Car D',
|
|
sessionType: 'Race',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = LeagueScheduleViewDataBuilder.build(apiDto);
|
|
|
|
expect(result.races).toHaveLength(4);
|
|
expect(result.races[0].isPast).toBe(true);
|
|
expect(result.races[1].isPast).toBe(true);
|
|
expect(result.races[2].isPast).toBe(false);
|
|
expect(result.races[3].isPast).toBe(false);
|
|
});
|
|
});
|
|
});
|