import { describe, it, expect, vi, type Mock } from 'vitest'; import { ProcessWalletTransactionUseCase, type ProcessWalletTransactionInput } from './ProcessWalletTransactionUseCase'; import type { IWalletRepository, ITransactionRepository } from '../../domain/repositories/IWalletRepository'; import { TransactionType, ReferenceType } from '../../domain/entities/Wallet'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; describe('ProcessWalletTransactionUseCase', () => { let walletRepository: { findByLeagueId: Mock; create: Mock; update: Mock; }; let transactionRepository: { create: Mock; }; let output: { present: Mock; }; let useCase: ProcessWalletTransactionUseCase; beforeEach(() => { walletRepository = { findByLeagueId: vi.fn(), create: vi.fn(), update: vi.fn(), } as unknown as IWalletRepository as any; transactionRepository = { create: vi.fn(), } as unknown as ITransactionRepository as any; output = { present: vi.fn(), }; useCase = new ProcessWalletTransactionUseCase( walletRepository as unknown as IWalletRepository, transactionRepository as unknown as ITransactionRepository, output as unknown as UseCaseOutputPort, ); }); it('processes a deposit transaction and presents the result', async () => { const input: ProcessWalletTransactionInput = { leagueId: 'league-1', type: TransactionType.DEPOSIT, amount: 100, description: 'Test deposit', referenceId: 'ref-1', referenceType: ReferenceType.SPONSORSHIP, }; const wallet = { id: 'wallet-1', leagueId: 'league-1', balance: 50, totalRevenue: 50, totalPlatformFees: 0, totalWithdrawn: 0, currency: 'USD', createdAt: new Date(), }; const transaction = { id: 'txn-1', walletId: 'wallet-1', type: TransactionType.DEPOSIT, amount: 100, description: 'Test deposit', referenceId: 'ref-1', referenceType: ReferenceType.SPONSORSHIP, createdAt: new Date(), }; walletRepository.findByLeagueId.mockResolvedValue(wallet); transactionRepository.create.mockResolvedValue(transaction); walletRepository.update.mockResolvedValue({ ...wallet, balance: 150, totalRevenue: 150 }); const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(output.present).toHaveBeenCalledWith({ wallet: { ...wallet, balance: 150, totalRevenue: 150 }, transaction, }); }); it('returns error for insufficient balance on withdrawal', async () => { const input: ProcessWalletTransactionInput = { leagueId: 'league-1', type: TransactionType.WITHDRAWAL, amount: 100, description: 'Test withdrawal', }; const wallet = { id: 'wallet-1', leagueId: 'league-1', balance: 50, totalRevenue: 50, totalPlatformFees: 0, totalWithdrawn: 0, currency: 'USD', createdAt: new Date(), }; walletRepository.findByLeagueId.mockResolvedValue(wallet); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('INSUFFICIENT_BALANCE'); }); });