import { describe, it, expect } from 'vitest'; import { StandingEntryViewModel } from './StandingEntryViewModel'; import type { LeagueStandingDTO } from '../types/generated/LeagueStandingDTO'; describe('StandingEntryViewModel', () => { const createMockStanding = (overrides?: Partial): LeagueStandingDTO => ({ driverId: 'driver-1', position: 1, points: 100, wins: 3, podiums: 5, races: 8, ...overrides, }); it('should create instance with all properties', () => { const dto = createMockStanding(); const viewModel = new StandingEntryViewModel(dto, 100, 85, 'driver-1'); expect(viewModel.driverId).toBe('driver-1'); expect(viewModel.position).toBe(1); expect(viewModel.points).toBe(100); expect(viewModel.wins).toBe(3); expect(viewModel.podiums).toBe(5); expect(viewModel.races).toBe(8); }); it('should return position as badge string', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 5 }), 100, 85, 'driver-1' ); expect(viewModel.positionBadge).toBe('5'); }); it('should calculate points gap to leader correctly', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 2, points: 85 }), 100, // leader points 70, // next points 'driver-2' ); expect(viewModel.pointsGapToLeader).toBe(-15); }); it('should show zero gap when driver is leader', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 1, points: 100 }), 100, // leader points 85, // next points 'driver-1' ); expect(viewModel.pointsGapToLeader).toBe(0); }); it('should calculate points gap to next position correctly', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 2, points: 85 }), 100, // leader points 70, // next points 'driver-2' ); expect(viewModel.pointsGapToNext).toBe(15); }); it('should identify current user correctly', () => { const viewModel1 = new StandingEntryViewModel( createMockStanding({ driverId: 'driver-1' }), 100, 85, 'driver-1' ); const viewModel2 = new StandingEntryViewModel( createMockStanding({ driverId: 'driver-1' }), 100, 85, 'driver-2' ); expect(viewModel1.isCurrentUser).toBe(true); expect(viewModel2.isCurrentUser).toBe(false); }); it('should return "same" trend when no previous position', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 1 }), 100, 85, 'driver-1' ); expect(viewModel.trend).toBe('same'); }); it('should return "up" trend when position improved', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 1 }), 100, 85, 'driver-1', 3 // previous position was 3rd ); expect(viewModel.trend).toBe('up'); }); it('should return "down" trend when position worsened', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 5 }), 100, 85, 'driver-1', 2 // previous position was 2nd ); expect(viewModel.trend).toBe('down'); }); it('should return "same" trend when position unchanged', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 3 }), 100, 85, 'driver-1', 3 // same position ); expect(viewModel.trend).toBe('same'); }); it('should return correct trend arrow for up', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 1 }), 100, 85, 'driver-1', 3 ); expect(viewModel.trendArrow).toBe('↑'); }); it('should return correct trend arrow for down', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 5 }), 100, 85, 'driver-1', 2 ); expect(viewModel.trendArrow).toBe('↓'); }); it('should return correct trend arrow for same', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 3 }), 100, 85, 'driver-1' ); expect(viewModel.trendArrow).toBe('-'); }); it('should handle edge case of last place with no one behind', () => { const viewModel = new StandingEntryViewModel( createMockStanding({ position: 10, points: 20 }), 100, // leader points 20, // same points (last place) 'driver-10' ); expect(viewModel.pointsGapToNext).toBe(0); expect(viewModel.pointsGapToLeader).toBe(-80); }); });