import { describe, it, expect, vi, beforeEach } from 'vitest'; import { GetDriverRankingsUseCase, GetDriverRankingsUseCasePorts } from './GetDriverRankingsUseCase'; import { ValidationError } from '../../../shared/errors/ValidationError'; describe('GetDriverRankingsUseCase', () => { let mockLeaderboardsRepository: any; let mockEventPublisher: any; let ports: GetDriverRankingsUseCasePorts; let useCase: GetDriverRankingsUseCase; const mockDrivers = [ { id: '1', name: 'Alice', rating: 2000, raceCount: 10, teamId: 't1', teamName: 'Team A' }, { id: '2', name: 'Bob', rating: 1500, raceCount: 5, teamId: 't2', teamName: 'Team B' }, { id: '3', name: 'Charlie', rating: 1800, raceCount: 8 }, ]; beforeEach(() => { mockLeaderboardsRepository = { findAllDrivers: vi.fn().mockResolvedValue([...mockDrivers]), }; mockEventPublisher = { publishDriverRankingsAccessed: vi.fn().mockResolvedValue(undefined), publishLeaderboardsError: vi.fn().mockResolvedValue(undefined), }; ports = { leaderboardsRepository: mockLeaderboardsRepository, eventPublisher: mockEventPublisher, }; useCase = new GetDriverRankingsUseCase(ports); }); it('should return all drivers sorted by rating DESC by default', async () => { const result = await useCase.execute(); expect(result.drivers).toHaveLength(3); expect(result.drivers[0].name).toBe('Alice'); expect(result.drivers[1].name).toBe('Charlie'); expect(result.drivers[2].name).toBe('Bob'); expect(result.drivers[0].rank).toBe(1); expect(result.drivers[1].rank).toBe(2); expect(result.drivers[2].rank).toBe(3); expect(mockEventPublisher.publishDriverRankingsAccessed).toHaveBeenCalled(); }); it('should filter drivers by search term', async () => { const result = await useCase.execute({ search: 'ali' }); expect(result.drivers).toHaveLength(1); expect(result.drivers[0].name).toBe('Alice'); }); it('should filter drivers by minRating', async () => { const result = await useCase.execute({ minRating: 1700 }); expect(result.drivers).toHaveLength(2); expect(result.drivers.map(d => d.name)).toContain('Alice'); expect(result.drivers.map(d => d.name)).toContain('Charlie'); }); it('should filter drivers by teamId', async () => { const result = await useCase.execute({ teamId: 't1' }); expect(result.drivers).toHaveLength(1); expect(result.drivers[0].name).toBe('Alice'); }); it('should sort drivers by name ASC', async () => { const result = await useCase.execute({ sortBy: 'name', sortOrder: 'asc' }); expect(result.drivers[0].name).toBe('Alice'); expect(result.drivers[1].name).toBe('Bob'); expect(result.drivers[2].name).toBe('Charlie'); }); it('should paginate results', async () => { const result = await useCase.execute({ page: 2, limit: 1 }); expect(result.drivers).toHaveLength(1); expect(result.drivers[0].name).toBe('Charlie'); // Alice (1), Charlie (2), Bob (3) expect(result.pagination.total).toBe(3); expect(result.pagination.totalPages).toBe(3); expect(result.pagination.page).toBe(2); }); it('should throw ValidationError for invalid page', async () => { await expect(useCase.execute({ page: 0 })).rejects.toThrow(ValidationError); expect(mockEventPublisher.publishLeaderboardsError).toHaveBeenCalled(); }); it('should throw ValidationError for invalid limit', async () => { await expect(useCase.execute({ limit: 0 })).rejects.toThrow(ValidationError); }); it('should throw ValidationError for invalid sortBy', async () => { await expect(useCase.execute({ sortBy: 'invalid' as any })).rejects.toThrow(ValidationError); }); });