147 lines
4.5 KiB
TypeScript
147 lines
4.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
DashboardOverviewViewModel,
|
|
DriverViewModel,
|
|
RaceViewModel,
|
|
LeagueStandingViewModel,
|
|
DashboardFeedItemSummaryViewModel,
|
|
FriendViewModel,
|
|
} from './DashboardOverviewViewModel';
|
|
import type { DashboardOverviewDto } from '../api/dashboard/DashboardApiClient';
|
|
|
|
const createDashboardOverviewDto = (): DashboardOverviewDto => ({
|
|
currentDriver: {
|
|
id: 'driver-1',
|
|
name: 'Test Driver',
|
|
avatarUrl: 'https://example.com/avatar.jpg',
|
|
country: 'DE',
|
|
totalRaces: 10,
|
|
wins: 3,
|
|
podiums: 5,
|
|
rating: 2500,
|
|
globalRank: 42,
|
|
consistency: 88,
|
|
},
|
|
nextRace: {
|
|
id: 'race-1',
|
|
track: 'Spa-Francorchamps',
|
|
car: 'GT3',
|
|
scheduledAt: '2025-01-01T12:00:00Z',
|
|
isMyLeague: true,
|
|
leagueName: 'Pro League',
|
|
},
|
|
upcomingRaces: [
|
|
{
|
|
id: 'race-2',
|
|
track: 'Nürburgring',
|
|
car: 'GT4',
|
|
scheduledAt: '2025-01-02T12:00:00Z',
|
|
isMyLeague: false,
|
|
leagueName: undefined,
|
|
},
|
|
],
|
|
leagueStandings: [
|
|
{
|
|
leagueId: 'league-1',
|
|
leagueName: 'Pro League',
|
|
position: 1,
|
|
points: 120,
|
|
totalDrivers: 50,
|
|
},
|
|
],
|
|
feedItems: [
|
|
{
|
|
id: 'feed-1',
|
|
type: 'news',
|
|
headline: 'Big race announced',
|
|
body: 'Details about the big race.',
|
|
timestamp: '2025-01-01T10:00:00Z',
|
|
ctaHref: '/races/race-1',
|
|
ctaLabel: 'View race',
|
|
},
|
|
],
|
|
friends: [
|
|
{
|
|
id: 'friend-1',
|
|
name: 'Racing Buddy',
|
|
avatarUrl: 'https://example.com/friend.jpg',
|
|
country: 'US',
|
|
},
|
|
],
|
|
activeLeaguesCount: 3,
|
|
});
|
|
|
|
describe('DashboardOverviewViewModel', () => {
|
|
it('wraps the current driver DTO in a DriverViewModel', () => {
|
|
const dto = createDashboardOverviewDto();
|
|
const viewModel = new DashboardOverviewViewModel(dto);
|
|
|
|
const currentDriver = viewModel.currentDriver;
|
|
|
|
expect(currentDriver).toBeInstanceOf(DriverViewModel);
|
|
expect(currentDriver.id).toBe('driver-1');
|
|
expect(currentDriver.name).toBe('Test Driver');
|
|
expect(currentDriver.avatarUrl).toBe('https://example.com/avatar.jpg');
|
|
expect(currentDriver.country).toBe('DE');
|
|
expect(currentDriver.totalRaces).toBe(10);
|
|
expect(currentDriver.wins).toBe(3);
|
|
expect(currentDriver.podiums).toBe(5);
|
|
expect(currentDriver.rating).toBe(2500);
|
|
expect(currentDriver.globalRank).toBe(42);
|
|
expect(currentDriver.consistency).toBe(88);
|
|
});
|
|
|
|
it('wraps nextRace DTO into a RaceViewModel and returns null when absent', () => {
|
|
const dtoWithRace = createDashboardOverviewDto();
|
|
const viewModelWithRace = new DashboardOverviewViewModel(dtoWithRace);
|
|
|
|
const nextRace = viewModelWithRace.nextRace;
|
|
|
|
expect(nextRace).toBeInstanceOf(RaceViewModel);
|
|
expect(nextRace?.id).toBe('race-1');
|
|
expect(nextRace?.track).toBe('Spa-Francorchamps');
|
|
expect(nextRace?.car).toBe('GT3');
|
|
expect(nextRace?.isMyLeague).toBe(true);
|
|
expect(nextRace?.leagueName).toBe('Pro League');
|
|
expect(nextRace?.scheduledAt).toBeInstanceOf(Date);
|
|
|
|
const dtoWithoutRace: DashboardOverviewDto = {
|
|
...dtoWithRace,
|
|
nextRace: null,
|
|
};
|
|
|
|
const viewModelWithoutRace = new DashboardOverviewViewModel(dtoWithoutRace);
|
|
|
|
expect(viewModelWithoutRace.nextRace).toBeNull();
|
|
});
|
|
|
|
it('maps upcoming races, league standings, feed items and friends into their respective view models', () => {
|
|
const dto = createDashboardOverviewDto();
|
|
const viewModel = new DashboardOverviewViewModel(dto);
|
|
|
|
expect(viewModel.upcomingRaces).toHaveLength(1);
|
|
expect(viewModel.upcomingRaces[0]).toBeInstanceOf(RaceViewModel);
|
|
expect(viewModel.upcomingRaces[0].id).toBe('race-2');
|
|
|
|
expect(viewModel.leagueStandings).toHaveLength(1);
|
|
expect(viewModel.leagueStandings[0]).toBeInstanceOf(LeagueStandingViewModel);
|
|
expect(viewModel.leagueStandings[0].leagueId).toBe('league-1');
|
|
|
|
expect(viewModel.feedItems).toHaveLength(1);
|
|
expect(viewModel.feedItems[0]).toBeInstanceOf(DashboardFeedItemSummaryViewModel);
|
|
expect(viewModel.feedItems[0].id).toBe('feed-1');
|
|
expect(viewModel.feedItems[0].timestamp).toBeInstanceOf(Date);
|
|
|
|
expect(viewModel.friends).toHaveLength(1);
|
|
expect(viewModel.friends[0]).toBeInstanceOf(FriendViewModel);
|
|
expect(viewModel.friends[0].id).toBe('friend-1');
|
|
});
|
|
|
|
it('exposes the activeLeaguesCount from the DTO', () => {
|
|
const dto = createDashboardOverviewDto();
|
|
const viewModel = new DashboardOverviewViewModel(dto);
|
|
|
|
expect(viewModel.activeLeaguesCount).toBe(3);
|
|
});
|
|
});
|