Files
gridpilot.gg/apps/website/lib/view-models/RacesPageViewModel.test.ts
Marc Mintel 6c07abe5e7
Some checks failed
Contract Testing / contract-snapshot (pull_request) Has been cancelled
Contract Testing / contract-tests (pull_request) Has been cancelled
view data fixes
2026-01-25 00:12:30 +01:00

132 lines
4.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { RaceListItemViewModel } from './RaceListItemViewModel';
import { RacesPageViewModel } from './RacesPageViewModel';
describe('RaceListItemViewModel', () => {
const baseDto = {
id: 'race-123',
track: 'Spa-Francorchamps',
car: 'GT3',
scheduledAt: '2025-01-01T20:00:00Z',
status: 'scheduled',
leagueId: 'league-1',
leagueName: 'Test League',
strengthOfField: 2500,
isUpcoming: true,
isLive: false,
isPast: false,
};
it('maps DTO fields to properties', () => {
const viewModel = new RaceListItemViewModel(baseDto);
expect(viewModel.id).toBe('race-123');
expect(viewModel.track).toBe('Spa-Francorchamps');
expect(viewModel.car).toBe('GT3');
expect(viewModel.scheduledAt).toBe('2025-01-01T20:00:00Z');
expect(viewModel.status).toBe('scheduled');
expect(viewModel.leagueId).toBe('league-1');
expect(viewModel.leagueName).toBe('Test League');
expect(viewModel.strengthOfField).toBe(2500);
expect(viewModel.isUpcoming).toBe(true);
expect(viewModel.isLive).toBe(false);
expect(viewModel.isPast).toBe(false);
});
it('formats scheduled time as locale string', () => {
const viewModel = new RaceListItemViewModel(baseDto);
const formatted = viewModel.formattedScheduledTime;
expect(formatted).toContain('2025');
});
it('computes status badge variants', () => {
const scheduled = new RaceListItemViewModel({ ...baseDto, status: 'scheduled' });
const running = new RaceListItemViewModel({ ...baseDto, status: 'running' });
const completed = new RaceListItemViewModel({ ...baseDto, status: 'completed' });
const cancelled = new RaceListItemViewModel({ ...baseDto, status: 'cancelled' });
const other = new RaceListItemViewModel({ ...baseDto, status: 'unknown' });
expect(scheduled.statusBadgeVariant).toBe('primary');
expect(running.statusBadgeVariant).toBe('success');
expect(completed.statusBadgeVariant).toBe('default');
expect(cancelled.statusBadgeVariant).toBe('warning');
expect(other.statusBadgeVariant).toBe('neutral');
});
});
describe('RacesPageViewModel', () => {
const createDto = () => ({
races: [
{
id: 'race-1',
track: 'Spa',
car: 'GT3',
scheduledAt: '2025-01-01T20:00:00Z',
status: 'scheduled',
leagueId: 'league-1',
leagueName: 'League 1',
strengthOfField: 2500,
isUpcoming: true,
isLive: false,
isPast: false,
},
{
id: 'race-2',
track: 'Nürburgring',
car: 'GT4',
scheduledAt: '2025-01-02T20:00:00Z',
status: 'running',
leagueId: 'league-2',
leagueName: 'League 2',
strengthOfField: null,
isUpcoming: true,
isLive: true,
isPast: false,
},
{
id: 'race-3',
track: 'Daytona',
car: 'LMP2',
scheduledAt: '2024-12-31T20:00:00Z',
status: 'completed',
leagueId: 'league-3',
leagueName: 'League 3',
strengthOfField: 2000,
isUpcoming: false,
isLive: false,
isPast: true,
},
],
});
it('wraps races DTOs in RaceListItemViewModel instances', () => {
const viewModel = new RacesPageViewModel(createDto());
expect(viewModel.races).toHaveLength(3);
expect(viewModel.races[0]).toBeInstanceOf(RaceListItemViewModel);
});
it('computes total count from races length', () => {
const viewModel = new RacesPageViewModel(createDto());
expect(viewModel.totalCount).toBe(3);
});
it('filters upcoming, live and past races', () => {
const viewModel = new RacesPageViewModel(createDto());
expect(viewModel.upcomingRaces).toHaveLength(2);
expect(viewModel.liveRaces).toHaveLength(1);
expect(viewModel.pastRaces).toHaveLength(1);
});
it('filters scheduled, running and completed races by status', () => {
const viewModel = new RacesPageViewModel(createDto());
expect(viewModel.scheduledRaces).toHaveLength(1);
expect(viewModel.runningRaces).toHaveLength(1);
expect(viewModel.completedRaces).toHaveLength(1);
});
});