import { describe, it, expect, vi } from 'vitest'; import { GetDriversLeaderboardUseCase, type GetDriversLeaderboardInput, GetDriversLeaderboardResult } from './GetDriversLeaderboardUseCase'; import type { IDriverRepository } from '../../domain/repositories/IDriverRepository'; import type { IRankingUseCase } from './IRankingUseCase'; import type { IDriverStatsUseCase } from './IDriverStatsUseCase'; import type { Logger } from '@core/shared/application'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; describe('GetDriversLeaderboardUseCase', () => { const mockDriverFindAll = vi.fn(); const mockDriverRepo: IDriverRepository = { findById: vi.fn(), findByIRacingId: vi.fn(), existsByIRacingId: vi.fn(), findAll: mockDriverFindAll, create: vi.fn(), update: vi.fn(), delete: vi.fn(), exists: vi.fn(), }; const mockRankingGetAllDriverRankings = vi.fn(); const mockRankingUseCase: IRankingUseCase = { getAllDriverRankings: mockRankingGetAllDriverRankings, }; const mockDriverStatsGetDriverStats = vi.fn(); const mockDriverStatsUseCase: IDriverStatsUseCase = { getDriverStats: mockDriverStatsGetDriverStats, }; const mockLogger: Logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), }; const mockOutput: UseCaseOutputPort = { present: vi.fn(), }; it('should return drivers leaderboard data', async () => { const useCase = new GetDriversLeaderboardUseCase( mockDriverRepo, mockRankingUseCase, mockDriverStatsUseCase, mockLogger, mockOutput, ); const driver1 = { id: 'driver1', name: { value: 'Driver One' }, country: { value: 'US' }, avatarRef: { type: 'system-default', variant: 'avatar' } }; const driver2 = { id: 'driver2', name: { value: 'Driver Two' }, country: { value: 'US' }, avatarRef: { type: 'system-default', variant: 'avatar' } }; const rankings = [ { driverId: 'driver1', rating: 2500, overallRank: 1 }, { driverId: 'driver2', rating: 2400, overallRank: 2 }, ]; const stats1 = { totalRaces: 10, wins: 5, podiums: 7 }; const stats2 = { totalRaces: 8, wins: 3, podiums: 4 }; mockDriverFindAll.mockResolvedValue([driver1, driver2]); mockRankingGetAllDriverRankings.mockReturnValue(rankings); mockDriverStatsGetDriverStats.mockImplementation((id: string) => { if (id === 'driver1') return stats1; if (id === 'driver2') return stats2; return null; }); const input: GetDriversLeaderboardInput = { leagueId: 'league-1' }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(mockOutput.present).toHaveBeenCalledWith({ items: [ expect.objectContaining({ driver: driver1, rating: 2500, skillLevel: 'advanced', racesCompleted: 10, wins: 5, podiums: 7, isActive: true, rank: 1, avatarRef: driver1.avatarRef, }), expect.objectContaining({ driver: driver2, rating: 2400, skillLevel: 'intermediate', racesCompleted: 8, wins: 3, podiums: 4, isActive: true, rank: 2, avatarRef: driver2.avatarRef, }), ], totalRaces: 18, totalWins: 8, activeCount: 2, }); }); it('should return empty result when no drivers', async () => { const useCase = new GetDriversLeaderboardUseCase( mockDriverRepo, mockRankingUseCase, mockDriverStatsUseCase, mockLogger, mockOutput, ); mockDriverFindAll.mockResolvedValue([]); mockRankingGetAllDriverRankings.mockReturnValue([]); const input: GetDriversLeaderboardInput = { leagueId: 'league-1' }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(mockOutput.present).toHaveBeenCalledWith({ items: [], totalRaces: 0, totalWins: 0, activeCount: 0, }); }); it('should handle drivers without stats', async () => { const useCase = new GetDriversLeaderboardUseCase( mockDriverRepo, mockRankingUseCase, mockDriverStatsUseCase, mockLogger, mockOutput, ); const driver1 = { id: 'driver1', name: { value: 'Driver One' }, country: { value: 'US' }, avatarRef: { type: 'system-default', variant: 'avatar' } }; const rankings = [{ driverId: 'driver1', rating: 2500, overallRank: 1 }]; mockDriverFindAll.mockResolvedValue([driver1]); mockRankingGetAllDriverRankings.mockReturnValue(rankings); mockDriverStatsGetDriverStats.mockReturnValue(null); const input: GetDriversLeaderboardInput = { leagueId: 'league-1' }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(mockOutput.present).toHaveBeenCalledWith({ items: [ expect.objectContaining({ driver: driver1, rating: 2500, skillLevel: 'advanced', racesCompleted: 0, wins: 0, podiums: 0, isActive: false, rank: 1, avatarRef: driver1.avatarRef, }), ], totalRaces: 0, totalWins: 0, activeCount: 0, }); }); it('should return error when repository throws', async () => { const useCase = new GetDriversLeaderboardUseCase( mockDriverRepo, mockRankingUseCase, mockDriverStatsUseCase, mockLogger, mockOutput, ); const error = new Error('Repository error'); mockDriverFindAll.mockRejectedValue(error); const input: GetDriversLeaderboardInput = { leagueId: 'league-1' }; const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr(); expect(err.code).toBe('REPOSITORY_ERROR'); if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) { expect(err.details.message).toBe('Repository error'); } }); });