import { describe, it, expect } from 'vitest'; import { DriverLeaderboardViewModel } from './DriverLeaderboardViewModel'; import { DriverLeaderboardItemViewModel } from './DriverLeaderboardItemViewModel'; import type { DriverLeaderboardItemDTO } from '../types/generated/DriverLeaderboardItemDTO'; const createDriver = (overrides: Partial = {}): DriverLeaderboardItemDTO & { avatarUrl: string } => ({ id: 'driver-1', name: 'Driver One', rating: 1500, skillLevel: 'advanced', nationality: 'DE', racesCompleted: 10, wins: 3, podiums: 5, isActive: true, rank: 1, avatarUrl: 'https://example.com/avatar-1.jpg', ...overrides, }); describe('DriverLeaderboardViewModel', () => { it('wraps DTO drivers into DriverLeaderboardItemViewModel instances', () => { const drivers = [createDriver({ id: 'driver-1' }), createDriver({ id: 'driver-2', name: 'Driver Two' })]; const viewModel = new DriverLeaderboardViewModel({ drivers }); expect(viewModel.drivers).toHaveLength(2); expect(viewModel.drivers[0]).toBeInstanceOf(DriverLeaderboardItemViewModel); expect(viewModel.drivers[0].position).toBe(1); expect(viewModel.drivers[1].position).toBe(2); }); it('computes aggregate totals and active count', () => { const drivers = [ createDriver({ id: 'driver-1', racesCompleted: 10, wins: 3, isActive: true }), createDriver({ id: 'driver-2', racesCompleted: 5, wins: 1, isActive: false }), ]; const viewModel = new DriverLeaderboardViewModel({ drivers }); expect(viewModel.totalRaces).toBe(15); expect(viewModel.totalWins).toBe(4); expect(viewModel.activeCount).toBe(1); }); it('passes previous rating to items when provided', () => { const currentDrivers = [ createDriver({ id: 'driver-1', rating: 1550 }), createDriver({ id: 'driver-2', rating: 1400 }), ]; const previousDrivers: (DriverLeaderboardItemDTO & { avatarUrl: string })[] = [ { ...createDriver({ id: 'driver-1', rating: 1500 }) }, { ...createDriver({ id: 'driver-2', rating: 1450 }) }, ]; const viewModel = new DriverLeaderboardViewModel({ drivers: currentDrivers }, previousDrivers); expect(viewModel.drivers[0].ratingTrend).toBe('up'); expect(viewModel.drivers[1].ratingTrend).toBe('down'); }); });