import { describe, expect, it, vi, type Mock } from 'vitest'; import type { MemberPaymentRepository, MembershipFeeRepository } from '../../domain/repositories/MembershipFeeRepository'; import { GetMembershipFeesUseCase, type GetMembershipFeesInput } from './GetMembershipFeesUseCase'; describe('GetMembershipFeesUseCase', () => { let membershipFeeRepository: { findByLeagueId: Mock; }; let memberPaymentRepository: { findByLeagueIdAndDriverId: Mock; }; let useCase: GetMembershipFeesUseCase; beforeEach(() => { membershipFeeRepository = { findByLeagueId: vi.fn(), }; memberPaymentRepository = { findByLeagueIdAndDriverId: vi.fn(), }; useCase = new GetMembershipFeesUseCase( membershipFeeRepository as unknown as MembershipFeeRepository, memberPaymentRepository as unknown as MemberPaymentRepository, ); }); it('retrieves membership fees and returns result', async () => { const input: GetMembershipFeesInput = { leagueId: 'league-1', driverId: 'driver-1', }; const fee = { id: 'fee-1', leagueId: 'league-1', type: 'monthly', amount: 50, enabled: true, createdAt: new Date(), updatedAt: new Date(), }; const payments = [ { id: 'payment-1', feeId: 'fee-1', driverId: 'driver-1', amount: 50, platformFee: 5, netAmount: 45, status: 'paid', dueDate: new Date(), paidAt: new Date(), }, ]; membershipFeeRepository.findByLeagueId.mockResolvedValue(fee); memberPaymentRepository.findByLeagueIdAndDriverId.mockResolvedValue(payments); const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(membershipFeeRepository.findByLeagueId).toHaveBeenCalledWith('league-1'); expect(memberPaymentRepository.findByLeagueIdAndDriverId).toHaveBeenCalledWith('league-1', 'driver-1', membershipFeeRepository); if (result.isOk()) { expect(result.value).toEqual({ fee, payments }); } }); it('returns error when leagueId is missing', async () => { const input: GetMembershipFeesInput = { leagueId: '', }; const result = await useCase.execute(input); expect(result.isErr()).toBe(true); if (result.isErr()) { expect(result.error.code).toBe('INVALID_INPUT'); } }); });