import { describe, it, expect, vi, type Mock } from 'vitest'; import { AwardPrizeUseCase, type AwardPrizeInput } from './AwardPrizeUseCase'; import type { IPrizeRepository } from '../../domain/repositories/IPrizeRepository'; import { PrizeType, type Prize } from '../../domain/entities/Prize'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; describe('AwardPrizeUseCase', () => { let prizeRepository: { findById: Mock; update: Mock }; let output: { present: Mock }; let useCase: AwardPrizeUseCase; beforeEach(() => { prizeRepository = { findById: vi.fn(), update: vi.fn(), }; output = { present: vi.fn(), }; useCase = new AwardPrizeUseCase( prizeRepository as unknown as IPrizeRepository, output as unknown as UseCaseOutputPort, ); }); it('returns PRIZE_NOT_FOUND when prize does not exist', async () => { prizeRepository.findById.mockResolvedValue(null); const input: AwardPrizeInput = { prizeId: 'prize-1', driverId: 'driver-1' }; const result = await useCase.execute(input); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('PRIZE_NOT_FOUND'); expect(prizeRepository.update).not.toHaveBeenCalled(); expect(output.present).not.toHaveBeenCalled(); }); it('returns PRIZE_ALREADY_AWARDED when prize is already awarded', async () => { const prize: Prize = { id: 'prize-1', leagueId: 'league-1', seasonId: 'season-1', position: 1, name: 'Winner', amount: 100, type: PrizeType.CASH, awarded: true, awardedTo: 'driver-x', awardedAt: new Date(), createdAt: new Date(), }; prizeRepository.findById.mockResolvedValue(prize); const input: AwardPrizeInput = { prizeId: 'prize-1', driverId: 'driver-1' }; const result = await useCase.execute(input); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('PRIZE_ALREADY_AWARDED'); expect(prizeRepository.update).not.toHaveBeenCalled(); expect(output.present).not.toHaveBeenCalled(); }); it('awards prize and presents updated prize', async () => { const prize: Prize = { id: 'prize-1', leagueId: 'league-1', seasonId: 'season-1', position: 1, name: 'Winner', amount: 100, type: PrizeType.CASH, awarded: false, createdAt: new Date('2024-01-01T00:00:00.000Z'), }; prizeRepository.findById.mockResolvedValue(prize); prizeRepository.update.mockImplementation(async (p: Prize) => p); const input: AwardPrizeInput = { prizeId: 'prize-1', driverId: 'driver-1' }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(prizeRepository.update).toHaveBeenCalledWith( expect.objectContaining({ id: 'prize-1', awarded: true, awardedTo: 'driver-1', awardedAt: expect.any(Date), }), ); expect(output.present).toHaveBeenCalledWith({ prize: expect.objectContaining({ id: 'prize-1', awarded: true, awardedTo: 'driver-1', awardedAt: expect.any(Date), }), }); }); });