253 lines
11 KiB
TypeScript
253 lines
11 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { Result } from '@core/shared/application/Result';
|
|
import { PaymentsService } from './PaymentsService';
|
|
|
|
describe('PaymentsService', () => {
|
|
const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
|
|
|
function makeService(overrides?: Partial<Record<string, any>>) {
|
|
const getPaymentsUseCase = overrides?.getPaymentsUseCase ?? { execute: vi.fn(async () => Result.ok({ payments: [] })) };
|
|
const createPaymentUseCase = overrides?.createPaymentUseCase ?? { execute: vi.fn(async () => Result.ok({ paymentId: 'p1' })) };
|
|
const updatePaymentStatusUseCase =
|
|
overrides?.updatePaymentStatusUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const getMembershipFeesUseCase =
|
|
overrides?.getMembershipFeesUseCase ?? { execute: vi.fn(async () => Result.ok({ fee: null, payments: [] })) };
|
|
const upsertMembershipFeeUseCase =
|
|
overrides?.upsertMembershipFeeUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const updateMemberPaymentUseCase =
|
|
overrides?.updateMemberPaymentUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const getPrizesUseCase = overrides?.getPrizesUseCase ?? { execute: vi.fn(async () => Result.ok({ prizes: [] })) };
|
|
const createPrizeUseCase = overrides?.createPrizeUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const awardPrizeUseCase = overrides?.awardPrizeUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const deletePrizeUseCase = overrides?.deletePrizeUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const getWalletUseCase = overrides?.getWalletUseCase ?? { execute: vi.fn(async () => Result.ok({ balance: 0 })) };
|
|
const processWalletTransactionUseCase =
|
|
overrides?.processWalletTransactionUseCase ?? { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
|
|
const service = new PaymentsService(
|
|
getPaymentsUseCase as any,
|
|
createPaymentUseCase as any,
|
|
updatePaymentStatusUseCase as any,
|
|
getMembershipFeesUseCase as any,
|
|
upsertMembershipFeeUseCase as any,
|
|
updateMemberPaymentUseCase as any,
|
|
getPrizesUseCase as any,
|
|
createPrizeUseCase as any,
|
|
awardPrizeUseCase as any,
|
|
deletePrizeUseCase as any,
|
|
getWalletUseCase as any,
|
|
processWalletTransactionUseCase as any,
|
|
logger as any,
|
|
);
|
|
|
|
return {
|
|
service,
|
|
getPaymentsUseCase,
|
|
createPaymentUseCase,
|
|
updatePaymentStatusUseCase,
|
|
getMembershipFeesUseCase,
|
|
upsertMembershipFeeUseCase,
|
|
updateMemberPaymentUseCase,
|
|
getPrizesUseCase,
|
|
createPrizeUseCase,
|
|
awardPrizeUseCase,
|
|
deletePrizeUseCase,
|
|
getWalletUseCase,
|
|
processWalletTransactionUseCase,
|
|
};
|
|
}
|
|
|
|
it('getPayments returns presenter model on success', async () => {
|
|
const { service, getPaymentsUseCase } = makeService();
|
|
await expect(service.getPayments({ leagueId: 'l1' } as any)).resolves.toEqual({ payments: [] });
|
|
expect(getPaymentsUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('getPayments throws when use case returns error (code message)', async () => {
|
|
const { service } = makeService({
|
|
getPaymentsUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' })) },
|
|
});
|
|
await expect(service.getPayments({ leagueId: 'l1' } as any)).rejects.toThrow('REPOSITORY_ERROR');
|
|
});
|
|
|
|
it('createPayment returns presenter model on success', async () => {
|
|
const { service, createPaymentUseCase } = makeService();
|
|
await expect(service.createPayment({ leagueId: 'l1' } as any)).resolves.toEqual({ paymentId: 'p1' });
|
|
expect(createPaymentUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('createPayment throws when use case returns error', async () => {
|
|
const { service } = makeService({
|
|
createPaymentUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' })) },
|
|
});
|
|
await expect(service.createPayment({ leagueId: 'l1' } as any)).rejects.toThrow('REPOSITORY_ERROR');
|
|
});
|
|
|
|
it('updatePaymentStatus returns presenter model on success', async () => {
|
|
const { service, updatePaymentStatusUseCase } = makeService();
|
|
await expect(service.updatePaymentStatus({ paymentId: 'p1' } as any)).resolves.toEqual({ success: true });
|
|
expect(updatePaymentStatusUseCase.execute).toHaveBeenCalledWith({ paymentId: 'p1' });
|
|
});
|
|
|
|
it('updatePaymentStatus throws when use case returns error', async () => {
|
|
const { service } = makeService({
|
|
updatePaymentStatusUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' })) },
|
|
});
|
|
await expect(service.updatePaymentStatus({ paymentId: 'p1' } as any)).rejects.toThrow('REPOSITORY_ERROR');
|
|
});
|
|
|
|
it('getMembershipFees returns viewModel on success', async () => {
|
|
const { service, getMembershipFeesUseCase } = makeService({
|
|
getMembershipFeesUseCase: { execute: vi.fn(async () => Result.ok({ fee: { amount: 1 }, payments: [] })) }
|
|
});
|
|
|
|
await expect(service.getMembershipFees({ leagueId: 'l1', driverId: 'd1' } as any)).resolves.toEqual({
|
|
fee: { amount: 1 },
|
|
payments: [],
|
|
});
|
|
expect(getMembershipFeesUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1', driverId: 'd1' });
|
|
});
|
|
|
|
it('getMembershipFees throws when use case returns error', async () => {
|
|
const { service } = makeService({
|
|
getMembershipFeesUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' })) },
|
|
});
|
|
await expect(service.getMembershipFees({ leagueId: 'l1' } as any)).rejects.toThrow('REPOSITORY_ERROR');
|
|
});
|
|
|
|
it('upsertMembershipFee returns viewModel on success', async () => {
|
|
const { service, upsertMembershipFeeUseCase } = makeService();
|
|
|
|
await expect(service.upsertMembershipFee({ leagueId: 'l1' } as any)).resolves.toEqual({ success: true });
|
|
expect(upsertMembershipFeeUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('upsertMembershipFee throws on error branch (defensive check)', async () => {
|
|
const { service } = makeService({
|
|
upsertMembershipFeeUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' } as any)) },
|
|
});
|
|
|
|
await expect(service.upsertMembershipFee({ leagueId: 'l1' } as any)).rejects.toThrow(
|
|
'Failed to upsert membership fee',
|
|
);
|
|
});
|
|
|
|
it('updateMemberPayment returns viewModel on success', async () => {
|
|
const { service, updateMemberPaymentUseCase } = makeService();
|
|
|
|
await expect(service.updateMemberPayment({ leagueId: 'l1' } as any)).resolves.toEqual({ success: true });
|
|
expect(updateMemberPaymentUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('updateMemberPayment throws when use case returns error', async () => {
|
|
const { service } = makeService({
|
|
updateMemberPaymentUseCase: { execute: vi.fn(async () => Result.err({ code: 'REPOSITORY_ERROR' })) },
|
|
});
|
|
|
|
await expect(service.updateMemberPayment({ leagueId: 'l1' } as any)).rejects.toThrow('REPOSITORY_ERROR');
|
|
});
|
|
|
|
it('getPrizes maps seasonId optional', async () => {
|
|
const getPrizesUseCase = { execute: vi.fn(async () => Result.ok({ prizes: [] })) };
|
|
const { service } = makeService({
|
|
getPrizesUseCase,
|
|
});
|
|
|
|
await expect(service.getPrizes({ leagueId: 'l1' } as any)).resolves.toEqual({ prizes: [] });
|
|
expect(getPrizesUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
|
|
await expect(service.getPrizes({ leagueId: 'l1', seasonId: 's1' } as any)).resolves.toEqual({ prizes: [] });
|
|
expect(getPrizesUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1', seasonId: 's1' });
|
|
});
|
|
|
|
it('createPrize calls use case and returns viewModel', async () => {
|
|
const createPrizeUseCase = { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const { service } = makeService({
|
|
createPrizeUseCase,
|
|
});
|
|
|
|
await expect(service.createPrize({ leagueId: 'l1' } as any)).resolves.toEqual({ success: true });
|
|
expect(createPrizeUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('awardPrize calls use case and returns viewModel', async () => {
|
|
const awardPrizeUseCase = { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const { service } = makeService({
|
|
awardPrizeUseCase,
|
|
});
|
|
|
|
await expect(service.awardPrize({ prizeId: 'p1' } as any)).resolves.toEqual({ success: true });
|
|
expect(awardPrizeUseCase.execute).toHaveBeenCalledWith({ prizeId: 'p1' });
|
|
});
|
|
|
|
it('deletePrize calls use case and returns viewModel', async () => {
|
|
const deletePrizeUseCase = { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const { service } = makeService({
|
|
deletePrizeUseCase,
|
|
});
|
|
|
|
await expect(service.deletePrize({ prizeId: 'p1' } as any)).resolves.toEqual({ success: true });
|
|
expect(deletePrizeUseCase.execute).toHaveBeenCalledWith({ prizeId: 'p1' });
|
|
});
|
|
|
|
it('getWallet calls use case and returns viewModel', async () => {
|
|
const getWalletUseCase = { execute: vi.fn(async () => Result.ok({ balance: 10 })) };
|
|
const { service } = makeService({
|
|
getWalletUseCase,
|
|
});
|
|
|
|
await expect(service.getWallet({ leagueId: 'l1' } as any)).resolves.toEqual({ balance: 10 });
|
|
expect(getWalletUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('processWalletTransaction calls use case and returns viewModel', async () => {
|
|
const processWalletTransactionUseCase = { execute: vi.fn(async () => Result.ok({ success: true })) };
|
|
const { service } = makeService({
|
|
processWalletTransactionUseCase,
|
|
});
|
|
|
|
await expect(service.processWalletTransaction({ leagueId: 'l1' } as any)).resolves.toEqual({ success: true });
|
|
expect(processWalletTransactionUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
|
});
|
|
|
|
it('getPayments throws fallback message when error has no code', async () => {
|
|
const { service } = makeService({
|
|
getPaymentsUseCase: { execute: vi.fn(async () => Result.err({} as any)) },
|
|
});
|
|
|
|
await expect(service.getPayments({ leagueId: 'l1' } as any)).rejects.toThrow('Failed to get payments');
|
|
});
|
|
|
|
it('createPayment throws fallback message when error has no code', async () => {
|
|
const { service } = makeService({
|
|
createPaymentUseCase: { execute: vi.fn(async () => Result.err({} as any)) },
|
|
});
|
|
|
|
await expect(service.createPayment({ leagueId: 'l1' } as any)).rejects.toThrow('Failed to create payment');
|
|
});
|
|
|
|
it('updatePaymentStatus throws fallback message when error has no code', async () => {
|
|
const { service } = makeService({
|
|
updatePaymentStatusUseCase: { execute: vi.fn(async () => Result.err({} as any)) },
|
|
});
|
|
|
|
await expect(service.updatePaymentStatus({ paymentId: 'p1' } as any)).rejects.toThrow('Failed to update payment status');
|
|
});
|
|
|
|
it('getMembershipFees throws fallback message when error has no code', async () => {
|
|
const { service } = makeService({
|
|
getMembershipFeesUseCase: { execute: vi.fn(async () => Result.err({} as any)) },
|
|
});
|
|
|
|
await expect(service.getMembershipFees({ leagueId: 'l1', driverId: 'd1' } as any)).rejects.toThrow('Failed to get membership fees');
|
|
});
|
|
|
|
it('updateMemberPayment throws fallback message when error has no code', async () => {
|
|
const { service } = makeService({
|
|
updateMemberPaymentUseCase: { execute: vi.fn(async () => Result.err({} as any)) },
|
|
});
|
|
|
|
await expect(service.updateMemberPayment({ leagueId: 'l1' } as any)).rejects.toThrow('Failed to update member payment');
|
|
});
|
|
});
|