import { describe, it, expect, vi, beforeEach } from 'vitest'; import { GetLeagueFullConfigUseCase } from './GetLeagueFullConfigUseCase'; import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository'; import type { ILeagueScoringConfigRepository } from '../../domain/repositories/ILeagueScoringConfigRepository'; import type { IGameRepository } from '../../domain/repositories/IGameRepository'; import type { ILeagueFullConfigPresenter, LeagueConfigFormViewModel } from '../presenters/ILeagueFullConfigPresenter'; describe('GetLeagueFullConfigUseCase', () => { let useCase: GetLeagueFullConfigUseCase; let leagueRepository: ILeagueRepository; let seasonRepository: ISeasonRepository; let leagueScoringConfigRepository: ILeagueScoringConfigRepository; let gameRepository: IGameRepository; let presenter: ILeagueFullConfigPresenter; beforeEach(() => { leagueRepository = { findById: vi.fn(), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any; seasonRepository = { findByLeagueId: vi.fn(), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any; leagueScoringConfigRepository = { findBySeasonId: vi.fn(), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any; gameRepository = { findById: vi.fn(), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any; presenter = { reset: vi.fn(), present: vi.fn(), getViewModel: vi.fn(), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any; useCase = new GetLeagueFullConfigUseCase( leagueRepository, seasonRepository, leagueScoringConfigRepository, gameRepository, presenter, ); }); it('should return league config when league exists', async () => { const params = { leagueId: 'league-1' }; const mockLeague = { id: 'league-1', name: 'Test League', description: 'A test league', settings: { maxDrivers: 32, stewarding: { decisionMode: 'admin_only', requireDefense: false, defenseTimeLimit: 48, voteTimeLimit: 72, protestDeadlineHours: 48, stewardingClosesHours: 168, notifyAccusedOnProtest: true, notifyOnVoteRequired: true, }, }, }; const mockSeasons = [{ id: 'season-1', status: 'active', gameId: 'game-1' }]; const mockScoringConfig = { id: 'config-1' }; const mockGame = { id: 'game-1' }; const mockViewModel: LeagueConfigFormViewModel = { leagueId: 'league-1', basics: { name: 'Test League', description: 'A test league', visibility: 'public', gameId: 'iracing', }, structure: { mode: 'solo', maxDrivers: 32, multiClassEnabled: false, }, championships: { enableDriverChampionship: true, enableTeamChampionship: false, enableNationsChampionship: false, enableTrophyChampionship: false, }, scoring: { customScoringEnabled: false, }, dropPolicy: { strategy: 'none', }, timings: { practiceMinutes: 30, qualifyingMinutes: 15, mainRaceMinutes: 60, sessionCount: 1, roundsPlanned: 10, }, stewarding: { decisionMode: 'admin_only', requireDefense: false, defenseTimeLimit: 48, voteTimeLimit: 72, protestDeadlineHours: 48, stewardingClosesHours: 168, notifyAccusedOnProtest: true, notifyOnVoteRequired: true, }, }; leagueRepository.findById.mockResolvedValue(mockLeague); seasonRepository.findByLeagueId.mockResolvedValue(mockSeasons); leagueScoringConfigRepository.findBySeasonId.mockResolvedValue(mockScoringConfig); gameRepository.findById.mockResolvedValue(mockGame); presenter.getViewModel.mockReturnValue(mockViewModel); const result = await useCase.execute(params); expect(result.isOk()).toBe(true); const viewModel = result.value!; expect(viewModel).toEqual(mockViewModel); expect(presenter.reset).toHaveBeenCalled(); expect(presenter.present).toHaveBeenCalledWith({ league: mockLeague, activeSeason: mockSeasons[0], scoringConfig: mockScoringConfig, game: mockGame, }); }); it('should return error when league not found', async () => { const params = { leagueId: 'league-1' }; leagueRepository.findById.mockResolvedValue(null); const result = await useCase.execute(params); expect(result.isErr()).toBe(true); const error = result.unwrapErr(); expect(error.code).toBe('LEAGUE_NOT_FOUND'); expect(error.details!.message).toBe('League with id league-1 not found'); }); it('should handle no active season', async () => { const params = { leagueId: 'league-1' }; const mockLeague = { id: 'league-1', name: 'Test League', description: 'A test league', settings: { maxDrivers: 32 }, }; const mockViewModel: LeagueConfigFormViewModel = { leagueId: 'league-1', basics: { name: 'Test League', description: 'A test league', visibility: 'public', gameId: 'iracing' }, structure: { mode: 'solo', maxDrivers: 32, multiClassEnabled: false }, championships: { enableDriverChampionship: true, enableTeamChampionship: false, enableNationsChampionship: false, enableTrophyChampionship: false }, scoring: { customScoringEnabled: false }, dropPolicy: { strategy: 'none' }, timings: { practiceMinutes: 30, qualifyingMinutes: 15, mainRaceMinutes: 60, sessionCount: 1, roundsPlanned: 10 }, stewarding: { decisionMode: 'admin_only', requireDefense: false, defenseTimeLimit: 48, voteTimeLimit: 72, protestDeadlineHours: 48, stewardingClosesHours: 168, notifyAccusedOnProtest: true, notifyOnVoteRequired: true }, }; leagueRepository.findById.mockResolvedValue(mockLeague); seasonRepository.findByLeagueId.mockResolvedValue([]); presenter.getViewModel.mockReturnValue(mockViewModel); const result = await useCase.execute(params); expect(result.isOk()).toBe(true); expect(presenter.present).toHaveBeenCalledWith({ league: mockLeague, }); }); });