98 lines
4.0 KiB
TypeScript
98 lines
4.0 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { LeagueDetailViewModel, LeagueViewModel, DriverViewModel, RaceViewModel } from './LeagueDetailViewModel';
|
|
|
|
describe('LeagueDetailViewModel', () => {
|
|
const baseLeague = {
|
|
id: 'league-1',
|
|
name: 'Pro Series',
|
|
game: 'iRacing',
|
|
tier: 'premium' as const,
|
|
season: '2025 Season 1',
|
|
description: 'High level competition',
|
|
drivers: 24,
|
|
races: 10,
|
|
completedRaces: 4,
|
|
totalImpressions: 100_000,
|
|
avgViewsPerRace: 10_000,
|
|
engagement: 3.5,
|
|
rating: 4.7,
|
|
seasonStatus: 'active' as const,
|
|
seasonDates: { start: '2025-01-01', end: '2025-04-01' },
|
|
nextRace: { name: 'Round 5', date: '2025-02-01' },
|
|
sponsorSlots: {
|
|
main: { available: true, price: 5_000, benefits: ['Branding', 'Mentions'] },
|
|
secondary: { available: 2, total: 3, price: 2_000, benefits: ['Branding'] },
|
|
},
|
|
};
|
|
|
|
const drivers = [
|
|
{ id: 'd1', name: 'Alice', country: 'US', position: 1, races: 4, impressions: 30_000, team: 'Alpha' },
|
|
{ id: 'd2', name: 'Bob', country: 'DE', position: 2, races: 4, impressions: 25_000, team: 'Beta' },
|
|
];
|
|
|
|
const races = [
|
|
{ id: 'r1', name: 'Round 1', date: '2025-01-01', views: 12_000, status: 'completed' as const },
|
|
{ id: 'r2', name: 'Round 2', date: '2025-01-08', views: 11_000, status: 'upcoming' as const },
|
|
];
|
|
|
|
it('maps nested league, drivers and races into view models', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
expect(vm.league).toBeInstanceOf(LeagueViewModel);
|
|
expect(vm.drivers).toHaveLength(2);
|
|
expect(vm.drivers[0]).toBeInstanceOf(DriverViewModel);
|
|
expect(vm.races).toHaveLength(2);
|
|
expect(vm.races[0]).toBeInstanceOf(RaceViewModel);
|
|
});
|
|
|
|
it('keeps core league metrics available on LeagueViewModel', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
expect(vm.league.id).toBe('league-1');
|
|
expect(vm.league.drivers).toBe(24);
|
|
expect(vm.league.races).toBe(10);
|
|
expect(vm.league.completedRaces).toBe(4);
|
|
expect(vm.league.totalImpressions).toBe(100_000);
|
|
expect(vm.league.avgViewsPerRace).toBe(10_000);
|
|
});
|
|
|
|
it('exposes formatted impression and views statistics', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
expect(vm.league.formattedTotalImpressions).toBe(baseLeague.totalImpressions.toLocaleString());
|
|
expect(vm.league.formattedAvgViewsPerRace).toBe(baseLeague.avgViewsPerRace.toLocaleString());
|
|
expect(vm.league.projectedTotalViews).toBe(baseLeague.avgViewsPerRace * baseLeague.races);
|
|
expect(vm.league.formattedProjectedTotal).toBe(vm.league.projectedTotalViews.toLocaleString());
|
|
});
|
|
|
|
it('calculates CPM for main sponsor from projected total views', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
const expectedCpm = Math.round((baseLeague.sponsorSlots.main.price / vm.league.projectedTotalViews) * 1000);
|
|
|
|
expect(vm.league.mainSponsorCpm).toBe(expectedCpm);
|
|
expect(vm.league.formattedMainSponsorCpm).toBe(`$${expectedCpm.toFixed(2)}`);
|
|
});
|
|
|
|
it('derives races left and tier configuration', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
expect(vm.league.racesLeft).toBe(baseLeague.races - baseLeague.completedRaces);
|
|
const tierConfig = vm.league.tierConfig;
|
|
expect(tierConfig.color).toBeDefined();
|
|
expect(tierConfig.bgColor).toBeDefined();
|
|
expect(tierConfig.border).toBeDefined();
|
|
});
|
|
|
|
it('formats driver impressions and race date/views', () => {
|
|
const vm = new LeagueDetailViewModel({ league: baseLeague, drivers, races });
|
|
|
|
expect(vm.drivers[0].formattedImpressions).toBe(drivers[0].impressions.toLocaleString());
|
|
// formattedDate uses a short, locale-specific date string like "Jan 1"
|
|
const formattedDate = vm.races[0].formattedDate;
|
|
expect(typeof formattedDate).toBe('string');
|
|
expect(formattedDate.length).toBeGreaterThan(0);
|
|
expect(vm.races[0].formattedViews).toBe(races[0].views.toLocaleString());
|
|
});
|
|
});
|