import { describe, it, expect, vi, beforeEach } from 'vitest'; import { GetLeagueDriverSeasonStatsUseCase } from './GetLeagueDriverSeasonStatsUseCase'; import type { IStandingRepository } from '../../domain/repositories/IStandingRepository'; import type { IResultRepository } from '../../domain/repositories/IResultRepository'; import type { IPenaltyRepository } from '../../domain/repositories/IPenaltyRepository'; import type { IRaceRepository } from '../../domain/repositories/IRaceRepository'; import type { DriverRatingPort } from '../ports/DriverRatingPort'; describe('GetLeagueDriverSeasonStatsUseCase', () => { const mockStandingFindByLeagueId = vi.fn(); const mockResultFindByDriverIdAndLeagueId = vi.fn(); const mockPenaltyFindByRaceId = vi.fn(); const mockRaceFindByLeagueId = vi.fn(); const mockDriverRatingGetRating = vi.fn(); let useCase: GetLeagueDriverSeasonStatsUseCase; let standingRepository: IStandingRepository; let resultRepository: IResultRepository; let penaltyRepository: IPenaltyRepository; let raceRepository: IRaceRepository; let driverRatingPort: DriverRatingPort; beforeEach(() => { standingRepository = { findByLeagueId: mockStandingFindByLeagueId, findByDriverIdAndLeagueId: vi.fn(), findAll: vi.fn(), save: vi.fn(), saveMany: vi.fn(), delete: vi.fn(), deleteByLeagueId: vi.fn(), exists: vi.fn(), recalculate: vi.fn(), }; resultRepository = { findByDriverIdAndLeagueId: mockResultFindByDriverIdAndLeagueId, }; penaltyRepository = { findByRaceId: mockPenaltyFindByRaceId, }; raceRepository = { findById: vi.fn(), findAll: vi.fn(), findByLeagueId: mockRaceFindByLeagueId, findUpcomingByLeagueId: vi.fn(), findCompletedByLeagueId: vi.fn(), findByStatus: vi.fn(), findByDateRange: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn(), exists: vi.fn(), }; driverRatingPort = { getRating: mockDriverRatingGetRating, }; useCase = new GetLeagueDriverSeasonStatsUseCase( standingRepository, resultRepository, penaltyRepository, raceRepository, driverRatingPort, ); }); it('should return league driver season stats for given league id', async () => { const params = { leagueId: 'league-1' }; const mockStandings = [ { driverId: 'driver-1', position: 1, points: 100, racesCompleted: 5 }, { driverId: 'driver-2', position: 2, points: 80, racesCompleted: 5 }, ]; const mockRaces = [ { id: 'race-1' }, { id: 'race-2' }, ]; const mockPenalties = [ { driverId: 'driver-1', status: 'applied', type: 'points_deduction', value: 10 }, ]; const mockResults = [{ position: 1 }]; const mockRating = { rating: 1500, ratingChange: 50 }; standingRepository.findByLeagueId.mockResolvedValue(mockStandings); raceRepository.findByLeagueId.mockResolvedValue(mockRaces); penaltyRepository.findByRaceId.mockImplementation((raceId) => { if (raceId === 'race-1') return Promise.resolve(mockPenalties); return Promise.resolve([]); }); driverRatingPort.getRating.mockReturnValue(mockRating); resultRepository.findByDriverIdAndLeagueId.mockResolvedValue(mockResults); const result = await useCase.execute(params); expect(result.isOk()).toBe(true); const dto = result.value!; expect(dto.leagueId).toBe('league-1'); expect(dto.standings).toEqual([ { driverId: 'driver-1', position: 1, points: 100, racesCompleted: 5 }, { driverId: 'driver-2', position: 2, points: 80, racesCompleted: 5 }, ]); expect(dto.penalties.get('driver-1')).toEqual({ baseDelta: -10, bonusDelta: 0 }); expect(dto.driverRatings.get('driver-1')).toEqual(mockRating); expect(dto.driverResults.get('driver-1')).toEqual(mockResults); }); it('should handle no penalties', async () => { const params = { leagueId: 'league-1' }; const mockStandings = [{ driverId: 'driver-1', position: 1, points: 100, racesCompleted: 5 }]; const mockRaces = [{ id: 'race-1' }]; const mockResults = [{ position: 1 }]; const mockRating = { rating: null, ratingChange: null }; standingRepository.findByLeagueId.mockResolvedValue(mockStandings); raceRepository.findByLeagueId.mockResolvedValue(mockRaces); penaltyRepository.findByRaceId.mockResolvedValue([]); driverRatingPort.getRating.mockReturnValue(mockRating); resultRepository.findByDriverIdAndLeagueId.mockResolvedValue(mockResults); const result = await useCase.execute(params); expect(result.isOk()).toBe(true); const dto = result.value!; expect(dto.penalties.size).toBe(0); }); });