add tests to core
This commit is contained in:
104
core/payments/application/use-cases/AwardPrizeUseCase.test.ts
Normal file
104
core/payments/application/use-cases/AwardPrizeUseCase.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
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<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
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),
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
102
core/payments/application/use-cases/CreatePrizeUseCase.test.ts
Normal file
102
core/payments/application/use-cases/CreatePrizeUseCase.test.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { describe, it, expect, vi, type Mock } from 'vitest';
|
||||
import { CreatePrizeUseCase, type CreatePrizeInput } from './CreatePrizeUseCase';
|
||||
import type { IPrizeRepository } from '../../domain/repositories/IPrizeRepository';
|
||||
import { PrizeType, type Prize } from '../../domain/entities/Prize';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('CreatePrizeUseCase', () => {
|
||||
let prizeRepository: { findByPosition: Mock; create: Mock };
|
||||
let output: { present: Mock };
|
||||
let useCase: CreatePrizeUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
prizeRepository = {
|
||||
findByPosition: vi.fn(),
|
||||
create: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new CreatePrizeUseCase(
|
||||
prizeRepository as unknown as IPrizeRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns PRIZE_ALREADY_EXISTS when prize already exists for position', async () => {
|
||||
const existingPrize: Prize = {
|
||||
id: 'prize-existing',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'Winner',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
prizeRepository.findByPosition.mockResolvedValue(existingPrize);
|
||||
|
||||
const input: CreatePrizeInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'Winner',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
};
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('PRIZE_ALREADY_EXISTS');
|
||||
expect(prizeRepository.create).not.toHaveBeenCalled();
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('creates prize and presents created prize', async () => {
|
||||
prizeRepository.findByPosition.mockResolvedValue(null);
|
||||
prizeRepository.create.mockImplementation(async (p: Prize) => p);
|
||||
|
||||
const input: CreatePrizeInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'Winner',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
description: 'Top prize',
|
||||
};
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(prizeRepository.findByPosition).toHaveBeenCalledWith('league-1', 'season-1', 1);
|
||||
|
||||
expect(prizeRepository.create).toHaveBeenCalledWith({
|
||||
id: expect.stringContaining('prize-'),
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'Winner',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: expect.any(Date),
|
||||
description: 'Top prize',
|
||||
});
|
||||
|
||||
expect(output.present).toHaveBeenCalledWith({
|
||||
prize: expect.objectContaining({
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
awarded: false,
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
import { describe, it, expect, vi, type Mock } from 'vitest';
|
||||
import { DeletePrizeUseCase, type DeletePrizeInput } from './DeletePrizeUseCase';
|
||||
import type { IPrizeRepository } from '../../domain/repositories/IPrizeRepository';
|
||||
import { PrizeType, type Prize } from '../../domain/entities/Prize';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('DeletePrizeUseCase', () => {
|
||||
let prizeRepository: { findById: Mock; delete: Mock };
|
||||
let output: { present: Mock };
|
||||
let useCase: DeletePrizeUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
prizeRepository = {
|
||||
findById: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new DeletePrizeUseCase(
|
||||
prizeRepository as unknown as IPrizeRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns PRIZE_NOT_FOUND when prize does not exist', async () => {
|
||||
prizeRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const input: DeletePrizeInput = { prizeId: 'prize-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('PRIZE_NOT_FOUND');
|
||||
expect(prizeRepository.delete).not.toHaveBeenCalled();
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns CANNOT_DELETE_AWARDED_PRIZE when prize is 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-1',
|
||||
awardedAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
};
|
||||
prizeRepository.findById.mockResolvedValue(prize);
|
||||
|
||||
const input: DeletePrizeInput = { prizeId: 'prize-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('CANNOT_DELETE_AWARDED_PRIZE');
|
||||
expect(prizeRepository.delete).not.toHaveBeenCalled();
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deletes prize and presents success', 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(),
|
||||
};
|
||||
prizeRepository.findById.mockResolvedValue(prize);
|
||||
prizeRepository.delete.mockResolvedValue(undefined);
|
||||
|
||||
const input: DeletePrizeInput = { prizeId: 'prize-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(prizeRepository.delete).toHaveBeenCalledWith('prize-1');
|
||||
expect(output.present).toHaveBeenCalledWith({ success: true });
|
||||
});
|
||||
});
|
||||
110
core/payments/application/use-cases/GetPrizesUseCase.test.ts
Normal file
110
core/payments/application/use-cases/GetPrizesUseCase.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { describe, it, expect, vi, type Mock } from 'vitest';
|
||||
import { GetPrizesUseCase, type GetPrizesInput } from './GetPrizesUseCase';
|
||||
import type { IPrizeRepository } from '../../domain/repositories/IPrizeRepository';
|
||||
import { PrizeType, type Prize } from '../../domain/entities/Prize';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('GetPrizesUseCase', () => {
|
||||
let prizeRepository: {
|
||||
findByLeagueId: Mock;
|
||||
findByLeagueIdAndSeasonId: Mock;
|
||||
};
|
||||
let output: { present: Mock };
|
||||
let useCase: GetPrizesUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
prizeRepository = {
|
||||
findByLeagueId: vi.fn(),
|
||||
findByLeagueIdAndSeasonId: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetPrizesUseCase(
|
||||
prizeRepository as unknown as IPrizeRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('retrieves and sorts prizes by leagueId when seasonId is not provided', async () => {
|
||||
const prizes: Prize[] = [
|
||||
{
|
||||
id: 'p2',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 2,
|
||||
name: 'Second',
|
||||
amount: 50,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'p1',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'First',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
];
|
||||
prizeRepository.findByLeagueId.mockResolvedValue(prizes);
|
||||
|
||||
const input: GetPrizesInput = { leagueId: 'league-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(prizeRepository.findByLeagueId).toHaveBeenCalledWith('league-1');
|
||||
expect(prizeRepository.findByLeagueIdAndSeasonId).not.toHaveBeenCalled();
|
||||
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
const presented = (output.present as unknown as Mock).mock.calls[0]![0]!.prizes as Prize[];
|
||||
expect(presented.map(p => p.position)).toEqual([1, 2]);
|
||||
expect(presented.map(p => p.id)).toEqual(['p1', 'p2']);
|
||||
});
|
||||
|
||||
it('retrieves and sorts prizes by leagueId and seasonId when provided', async () => {
|
||||
const prizes: Prize[] = [
|
||||
{
|
||||
id: 'p3',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 3,
|
||||
name: 'Third',
|
||||
amount: 25,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
{
|
||||
id: 'p1',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
position: 1,
|
||||
name: 'First',
|
||||
amount: 100,
|
||||
type: PrizeType.CASH,
|
||||
awarded: false,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
];
|
||||
prizeRepository.findByLeagueIdAndSeasonId.mockResolvedValue(prizes);
|
||||
|
||||
const input: GetPrizesInput = { leagueId: 'league-1', seasonId: 'season-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(prizeRepository.findByLeagueIdAndSeasonId).toHaveBeenCalledWith('league-1', 'season-1');
|
||||
expect(prizeRepository.findByLeagueId).not.toHaveBeenCalled();
|
||||
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
const presented = (output.present as unknown as Mock).mock.calls[0]![0]!.prizes as Prize[];
|
||||
expect(presented.map(p => p.position)).toEqual([1, 3]);
|
||||
expect(presented.map(p => p.id)).toEqual(['p1', 'p3']);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
import { describe, it, expect, vi, type Mock } from 'vitest';
|
||||
import { GetSponsorBillingUseCase, type GetSponsorBillingInput } from './GetSponsorBillingUseCase';
|
||||
import type { IPaymentRepository } from '../../domain/repositories/IPaymentRepository';
|
||||
import type { Payment } from '../../domain/entities/Payment';
|
||||
import { PaymentStatus, PaymentType, PayerType } from '../../domain/entities/Payment';
|
||||
import type { ISeasonSponsorshipRepository } from '@core/racing/domain/repositories/ISeasonSponsorshipRepository';
|
||||
import { SeasonSponsorship } from '@core/racing/domain/entities/season/SeasonSponsorship';
|
||||
import { Money } from '@core/racing/domain/value-objects/Money';
|
||||
|
||||
describe('GetSponsorBillingUseCase', () => {
|
||||
let paymentRepository: { findByFilters: Mock };
|
||||
let seasonSponsorshipRepository: { findBySponsorId: Mock };
|
||||
let useCase: GetSponsorBillingUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
paymentRepository = {
|
||||
findByFilters: vi.fn(),
|
||||
};
|
||||
|
||||
seasonSponsorshipRepository = {
|
||||
findBySponsorId: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetSponsorBillingUseCase(
|
||||
paymentRepository as unknown as IPaymentRepository,
|
||||
seasonSponsorshipRepository as unknown as ISeasonSponsorshipRepository,
|
||||
);
|
||||
});
|
||||
|
||||
it('derives invoices and stats from payments and sponsorships', async () => {
|
||||
const sponsorId = 'sponsor-1';
|
||||
|
||||
const payments: Payment[] = [
|
||||
{
|
||||
id: 'pay-1',
|
||||
type: PaymentType.SPONSORSHIP,
|
||||
amount: 100,
|
||||
platformFee: 10,
|
||||
netAmount: 90,
|
||||
payerId: sponsorId,
|
||||
payerType: PayerType.SPONSOR,
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
completedAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
},
|
||||
{
|
||||
id: 'pay-2',
|
||||
type: PaymentType.SPONSORSHIP,
|
||||
amount: 50,
|
||||
platformFee: 5,
|
||||
netAmount: 45,
|
||||
payerId: sponsorId,
|
||||
payerType: PayerType.SPONSOR,
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
status: PaymentStatus.PENDING,
|
||||
createdAt: new Date('2024-02-01T00:00:00.000Z'),
|
||||
},
|
||||
];
|
||||
|
||||
paymentRepository.findByFilters.mockResolvedValue(payments);
|
||||
|
||||
const sponsorships = [
|
||||
SeasonSponsorship.create({
|
||||
id: 'ss-1',
|
||||
seasonId: 'season-1',
|
||||
leagueId: 'league-1',
|
||||
sponsorId,
|
||||
tier: 'main',
|
||||
pricing: Money.create(100, 'USD'),
|
||||
status: 'active',
|
||||
}),
|
||||
SeasonSponsorship.create({
|
||||
id: 'ss-2',
|
||||
seasonId: 'season-2',
|
||||
leagueId: 'league-1',
|
||||
sponsorId,
|
||||
tier: 'secondary',
|
||||
pricing: Money.create(50, 'USD'),
|
||||
status: 'pending',
|
||||
}),
|
||||
];
|
||||
|
||||
seasonSponsorshipRepository.findBySponsorId.mockResolvedValue(sponsorships);
|
||||
|
||||
const input: GetSponsorBillingInput = { sponsorId };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const value = result.unwrap();
|
||||
|
||||
expect(paymentRepository.findByFilters).toHaveBeenCalledWith({
|
||||
payerId: sponsorId,
|
||||
type: PaymentType.SPONSORSHIP,
|
||||
});
|
||||
|
||||
expect(seasonSponsorshipRepository.findBySponsorId).toHaveBeenCalledWith(sponsorId);
|
||||
|
||||
expect(value.paymentMethods).toEqual([]);
|
||||
expect(value.invoices).toHaveLength(2);
|
||||
|
||||
// totals: each invoice adds 19% VAT
|
||||
// pay-1 total: 100 + 19 = 119 (paid)
|
||||
// pay-2 total: 50 + 9.5 = 59.5 (pending)
|
||||
expect(value.stats.totalSpent).toBeCloseTo(119, 5);
|
||||
expect(value.stats.pendingAmount).toBeCloseTo(59.5, 5);
|
||||
|
||||
expect(value.stats.activeSponsorships).toBe(1);
|
||||
expect(value.stats.nextPaymentDate).not.toBeNull();
|
||||
expect(value.stats.nextPaymentAmount).not.toBeNull();
|
||||
});
|
||||
});
|
||||
142
core/payments/application/use-cases/GetWalletUseCase.test.ts
Normal file
142
core/payments/application/use-cases/GetWalletUseCase.test.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { GetWalletUseCase, type GetWalletInput } from './GetWalletUseCase';
|
||||
import type { ITransactionRepository, IWalletRepository } from '../../domain/repositories/IWalletRepository';
|
||||
import type { Transaction, Wallet } from '../../domain/entities/Wallet';
|
||||
import { TransactionType } from '../../domain/entities/Wallet';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('GetWalletUseCase', () => {
|
||||
let walletRepository: {
|
||||
findByLeagueId: Mock;
|
||||
create: Mock;
|
||||
};
|
||||
|
||||
let transactionRepository: {
|
||||
findByWalletId: Mock;
|
||||
};
|
||||
|
||||
let output: {
|
||||
present: Mock;
|
||||
};
|
||||
|
||||
let useCase: GetWalletUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
walletRepository = {
|
||||
findByLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
};
|
||||
|
||||
transactionRepository = {
|
||||
findByWalletId: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetWalletUseCase(
|
||||
walletRepository as unknown as IWalletRepository,
|
||||
transactionRepository as unknown as ITransactionRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns INVALID_INPUT when leagueId is missing', async () => {
|
||||
const input = { leagueId: '' } as unknown as GetWalletInput;
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('INVALID_INPUT');
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('presents existing wallet and transactions sorted desc by createdAt', async () => {
|
||||
const input: GetWalletInput = { leagueId: 'league-1' };
|
||||
|
||||
const wallet: Wallet = {
|
||||
id: 'wallet-1',
|
||||
leagueId: 'league-1',
|
||||
balance: 50,
|
||||
totalRevenue: 100,
|
||||
totalPlatformFees: 5,
|
||||
totalWithdrawn: 10,
|
||||
currency: 'USD',
|
||||
createdAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
const older: Transaction = {
|
||||
id: 'txn-older',
|
||||
walletId: 'wallet-1',
|
||||
type: TransactionType.DEPOSIT,
|
||||
amount: 25,
|
||||
description: 'Older',
|
||||
createdAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
const newer: Transaction = {
|
||||
id: 'txn-newer',
|
||||
walletId: 'wallet-1',
|
||||
type: TransactionType.WITHDRAWAL,
|
||||
amount: 10,
|
||||
description: 'Newer',
|
||||
createdAt: new Date('2025-01-02T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
walletRepository.findByLeagueId.mockResolvedValue(wallet);
|
||||
transactionRepository.findByWalletId.mockResolvedValue([older, newer]);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(transactionRepository.findByWalletId).toHaveBeenCalledWith('wallet-1');
|
||||
expect(output.present).toHaveBeenCalledWith({
|
||||
wallet,
|
||||
transactions: [newer, older],
|
||||
});
|
||||
});
|
||||
|
||||
it('creates wallet when missing, then presents wallet and transactions', async () => {
|
||||
const input: GetWalletInput = { leagueId: 'league-1' };
|
||||
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-01T00:00:00.000Z'));
|
||||
vi.spyOn(Math, 'random').mockReturnValue(0.123456789);
|
||||
|
||||
try {
|
||||
walletRepository.findByLeagueId.mockResolvedValue(null);
|
||||
|
||||
walletRepository.create.mockImplementation(async (w: Wallet) => w);
|
||||
|
||||
transactionRepository.findByWalletId.mockResolvedValue([]);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(walletRepository.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^wallet-1735689600000-[a-z0-9]{9}$/),
|
||||
leagueId: 'league-1',
|
||||
balance: 0,
|
||||
totalRevenue: 0,
|
||||
totalPlatformFees: 0,
|
||||
totalWithdrawn: 0,
|
||||
currency: 'USD',
|
||||
createdAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const createdWalletArg = walletRepository.create.mock.calls[0]?.[0] as Wallet;
|
||||
expect(transactionRepository.findByWalletId).toHaveBeenCalledWith(createdWalletArg.id);
|
||||
|
||||
expect(output.present).toHaveBeenCalledWith({
|
||||
wallet: createdWalletArg,
|
||||
transactions: [],
|
||||
});
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,170 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { UpdateMemberPaymentUseCase, type UpdateMemberPaymentInput } from './UpdateMemberPaymentUseCase';
|
||||
import type { IMembershipFeeRepository, IMemberPaymentRepository } from '../../domain/repositories/IMembershipFeeRepository';
|
||||
import { MemberPaymentStatus, type MemberPayment } from '../../domain/entities/MemberPayment';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('UpdateMemberPaymentUseCase', () => {
|
||||
let membershipFeeRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
|
||||
let memberPaymentRepository: {
|
||||
findByFeeIdAndDriverId: Mock;
|
||||
create: Mock;
|
||||
update: Mock;
|
||||
};
|
||||
|
||||
let output: {
|
||||
present: Mock;
|
||||
};
|
||||
|
||||
let useCase: UpdateMemberPaymentUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
membershipFeeRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
|
||||
memberPaymentRepository = {
|
||||
findByFeeIdAndDriverId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new UpdateMemberPaymentUseCase(
|
||||
membershipFeeRepository as unknown as IMembershipFeeRepository,
|
||||
memberPaymentRepository as unknown as IMemberPaymentRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns MEMBERSHIP_FEE_NOT_FOUND when fee does not exist', async () => {
|
||||
const input: UpdateMemberPaymentInput = {
|
||||
feeId: 'fee-1',
|
||||
driverId: 'driver-1',
|
||||
};
|
||||
|
||||
membershipFeeRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('MEMBERSHIP_FEE_NOT_FOUND');
|
||||
expect(memberPaymentRepository.findByFeeIdAndDriverId).not.toHaveBeenCalled();
|
||||
expect(memberPaymentRepository.create).not.toHaveBeenCalled();
|
||||
expect(memberPaymentRepository.update).not.toHaveBeenCalled();
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('creates a new payment when missing, applies status and paidAt when PAID', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-01T00:00:00.000Z'));
|
||||
vi.spyOn(Math, 'random').mockReturnValue(0.123456789);
|
||||
|
||||
try {
|
||||
const input: UpdateMemberPaymentInput = {
|
||||
feeId: 'fee-1',
|
||||
driverId: 'driver-1',
|
||||
status: MemberPaymentStatus.PAID,
|
||||
};
|
||||
|
||||
const fee = {
|
||||
id: 'fee-1',
|
||||
leagueId: 'league-1',
|
||||
type: 'season',
|
||||
amount: 100,
|
||||
enabled: true,
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
membershipFeeRepository.findById.mockResolvedValue(fee);
|
||||
memberPaymentRepository.findByFeeIdAndDriverId.mockResolvedValue(null);
|
||||
memberPaymentRepository.create.mockImplementation(async (p: MemberPayment) => ({ ...p }));
|
||||
memberPaymentRepository.update.mockImplementation(async (p: MemberPayment) => p);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(memberPaymentRepository.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^mp-1735689600000-[a-z0-9]{9}$/),
|
||||
feeId: 'fee-1',
|
||||
driverId: 'driver-1',
|
||||
amount: 100,
|
||||
platformFee: 10,
|
||||
netAmount: 90,
|
||||
status: MemberPaymentStatus.PENDING,
|
||||
dueDate: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(memberPaymentRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
status: MemberPaymentStatus.PAID,
|
||||
paidAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const updated = memberPaymentRepository.update.mock.calls[0]?.[0] as MemberPayment;
|
||||
expect(output.present).toHaveBeenCalledWith({ payment: updated });
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('updates existing payment status and parses paidAt string', async () => {
|
||||
const input: UpdateMemberPaymentInput = {
|
||||
feeId: 'fee-1',
|
||||
driverId: 'driver-1',
|
||||
status: MemberPaymentStatus.PAID,
|
||||
paidAt: '2025-02-01T00:00:00.000Z',
|
||||
};
|
||||
|
||||
const fee = {
|
||||
id: 'fee-1',
|
||||
leagueId: 'league-1',
|
||||
type: 'season',
|
||||
amount: 100,
|
||||
enabled: true,
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-02T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
const existingPayment: MemberPayment = {
|
||||
id: 'mp-1',
|
||||
feeId: 'fee-1',
|
||||
driverId: 'driver-1',
|
||||
amount: 100,
|
||||
platformFee: 10,
|
||||
netAmount: 90,
|
||||
status: MemberPaymentStatus.PENDING,
|
||||
dueDate: new Date('2025-01-01T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
membershipFeeRepository.findById.mockResolvedValue(fee);
|
||||
memberPaymentRepository.findByFeeIdAndDriverId.mockResolvedValue(existingPayment);
|
||||
memberPaymentRepository.update.mockImplementation(async (p: MemberPayment) => p);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(memberPaymentRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'mp-1',
|
||||
status: MemberPaymentStatus.PAID,
|
||||
paidAt: new Date('2025-02-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const updated = memberPaymentRepository.update.mock.calls[0]?.[0] as MemberPayment;
|
||||
expect(output.present).toHaveBeenCalledWith({ payment: updated });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { UpdatePaymentStatusUseCase, type UpdatePaymentStatusInput } from './UpdatePaymentStatusUseCase';
|
||||
import type { IPaymentRepository } from '../../domain/repositories/IPaymentRepository';
|
||||
import { PaymentStatus, PaymentType, PayerType, type Payment } from '../../domain/entities/Payment';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('UpdatePaymentStatusUseCase', () => {
|
||||
let paymentRepository: {
|
||||
findById: Mock;
|
||||
update: Mock;
|
||||
};
|
||||
|
||||
let output: {
|
||||
present: Mock;
|
||||
};
|
||||
|
||||
let useCase: UpdatePaymentStatusUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
paymentRepository = {
|
||||
findById: vi.fn(),
|
||||
update: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new UpdatePaymentStatusUseCase(
|
||||
paymentRepository as unknown as IPaymentRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns PAYMENT_NOT_FOUND when payment does not exist', async () => {
|
||||
const input: UpdatePaymentStatusInput = {
|
||||
paymentId: 'payment-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
};
|
||||
|
||||
paymentRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('PAYMENT_NOT_FOUND');
|
||||
expect(paymentRepository.update).not.toHaveBeenCalled();
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets completedAt when status becomes COMPLETED', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-01T00:00:00.000Z'));
|
||||
|
||||
try {
|
||||
const input: UpdatePaymentStatusInput = {
|
||||
paymentId: 'payment-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
};
|
||||
|
||||
const existingPayment: Payment = {
|
||||
id: 'payment-1',
|
||||
type: PaymentType.SPONSORSHIP,
|
||||
amount: 100,
|
||||
platformFee: 5,
|
||||
netAmount: 95,
|
||||
payerId: 'payer-1',
|
||||
payerType: PayerType.SPONSOR,
|
||||
leagueId: 'league-1',
|
||||
status: PaymentStatus.PENDING,
|
||||
createdAt: new Date('2024-12-31T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
paymentRepository.findById.mockResolvedValue(existingPayment);
|
||||
paymentRepository.update.mockImplementation(async (p: Payment) => ({ ...p }));
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(paymentRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'payment-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
completedAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const savedPayment = paymentRepository.update.mock.results[0]?.value;
|
||||
await expect(savedPayment).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'payment-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
completedAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const presentedPayment = (output.present.mock.calls[0]?.[0] as { payment: Payment }).payment;
|
||||
expect(presentedPayment.status).toBe(PaymentStatus.COMPLETED);
|
||||
expect(presentedPayment.completedAt).toEqual(new Date('2025-01-01T00:00:00.000Z'));
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('preserves completedAt when status is not COMPLETED', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2026-01-01T00:00:00.000Z'));
|
||||
|
||||
try {
|
||||
const input: UpdatePaymentStatusInput = {
|
||||
paymentId: 'payment-1',
|
||||
status: PaymentStatus.FAILED,
|
||||
};
|
||||
|
||||
const existingCompletedAt = new Date('2025-01-01T00:00:00.000Z');
|
||||
|
||||
const existingPayment: Payment = {
|
||||
id: 'payment-1',
|
||||
type: PaymentType.SPONSORSHIP,
|
||||
amount: 100,
|
||||
platformFee: 5,
|
||||
netAmount: 95,
|
||||
payerId: 'payer-1',
|
||||
payerType: PayerType.SPONSOR,
|
||||
leagueId: 'league-1',
|
||||
status: PaymentStatus.COMPLETED,
|
||||
createdAt: new Date('2024-12-31T00:00:00.000Z'),
|
||||
completedAt: existingCompletedAt,
|
||||
};
|
||||
|
||||
paymentRepository.findById.mockResolvedValue(existingPayment);
|
||||
paymentRepository.update.mockImplementation(async (p: Payment) => ({ ...p }));
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(paymentRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'payment-1',
|
||||
status: PaymentStatus.FAILED,
|
||||
completedAt: existingCompletedAt,
|
||||
}),
|
||||
);
|
||||
|
||||
const presentedPayment = (output.present.mock.calls[0]?.[0] as { payment: Payment }).payment;
|
||||
expect(presentedPayment.status).toBe(PaymentStatus.FAILED);
|
||||
expect(presentedPayment.completedAt).toEqual(existingCompletedAt);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,127 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { UpsertMembershipFeeUseCase, type UpsertMembershipFeeInput } from './UpsertMembershipFeeUseCase';
|
||||
import type { IMembershipFeeRepository } from '../../domain/repositories/IMembershipFeeRepository';
|
||||
import { MembershipFeeType, type MembershipFee } from '../../domain/entities/MembershipFee';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('UpsertMembershipFeeUseCase', () => {
|
||||
let membershipFeeRepository: {
|
||||
findByLeagueId: Mock;
|
||||
create: Mock;
|
||||
update: Mock;
|
||||
};
|
||||
|
||||
let output: {
|
||||
present: Mock;
|
||||
};
|
||||
|
||||
let useCase: UpsertMembershipFeeUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
membershipFeeRepository = {
|
||||
findByLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
};
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new UpsertMembershipFeeUseCase(
|
||||
membershipFeeRepository as unknown as IMembershipFeeRepository,
|
||||
output as unknown as UseCaseOutputPort<unknown>,
|
||||
);
|
||||
});
|
||||
|
||||
it('creates a fee when none exists and presents it', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-01T00:00:00.000Z'));
|
||||
vi.spyOn(Math, 'random').mockReturnValue(0.123456789);
|
||||
|
||||
try {
|
||||
const input: UpsertMembershipFeeInput = {
|
||||
leagueId: 'league-1',
|
||||
type: MembershipFeeType.SEASON,
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
membershipFeeRepository.findByLeagueId.mockResolvedValue(null);
|
||||
membershipFeeRepository.create.mockImplementation(async (fee: MembershipFee) => ({ ...fee }));
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(membershipFeeRepository.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: expect.stringMatching(/^fee-1735689600000-[a-z0-9]{9}$/),
|
||||
leagueId: 'league-1',
|
||||
type: MembershipFeeType.SEASON,
|
||||
amount: 100,
|
||||
enabled: true,
|
||||
createdAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2025-01-01T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const createdFee = (output.present.mock.calls[0]?.[0] as { fee: MembershipFee }).fee;
|
||||
expect(createdFee.enabled).toBe(true);
|
||||
expect(createdFee.amount).toBe(100);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('updates an existing fee and sets enabled=false when amount is 0', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-02T00:00:00.000Z'));
|
||||
|
||||
try {
|
||||
const input: UpsertMembershipFeeInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-2',
|
||||
type: MembershipFeeType.MONTHLY,
|
||||
amount: 0,
|
||||
};
|
||||
|
||||
const existingFee: MembershipFee = {
|
||||
id: 'fee-1',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
type: MembershipFeeType.SEASON,
|
||||
amount: 100,
|
||||
enabled: true,
|
||||
createdAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
};
|
||||
|
||||
membershipFeeRepository.findByLeagueId.mockResolvedValue(existingFee);
|
||||
membershipFeeRepository.update.mockImplementation(async (fee: MembershipFee) => ({ ...fee }));
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
|
||||
expect(membershipFeeRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'fee-1',
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-2',
|
||||
type: MembershipFeeType.MONTHLY,
|
||||
amount: 0,
|
||||
enabled: false,
|
||||
updatedAt: new Date('2025-01-02T00:00:00.000Z'),
|
||||
}),
|
||||
);
|
||||
|
||||
const updatedFee = (output.present.mock.calls[0]?.[0] as { fee: MembershipFee }).fee;
|
||||
expect(updatedFee.enabled).toBe(false);
|
||||
expect(updatedFee.amount).toBe(0);
|
||||
expect(updatedFee.seasonId).toBe('season-2');
|
||||
expect(updatedFee.type).toBe(MembershipFeeType.MONTHLY);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
28
core/payments/application/use-cases/index.test.ts
Normal file
28
core/payments/application/use-cases/index.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import * as useCases from './index';
|
||||
|
||||
describe('payments use-cases barrel exports', () => {
|
||||
it('re-exports all expected use cases', () => {
|
||||
const exported = useCases as unknown as Record<string, unknown>;
|
||||
|
||||
const expectedExports = [
|
||||
'AwardPrizeUseCase',
|
||||
'CreatePaymentUseCase',
|
||||
'CreatePrizeUseCase',
|
||||
'DeletePrizeUseCase',
|
||||
'GetMembershipFeesUseCase',
|
||||
'GetPaymentsUseCase',
|
||||
'GetPrizesUseCase',
|
||||
'GetSponsorBillingUseCase',
|
||||
'GetWalletUseCase',
|
||||
'ProcessWalletTransactionUseCase',
|
||||
'UpdateMemberPaymentUseCase',
|
||||
'UpdatePaymentStatusUseCase',
|
||||
'UpsertMembershipFeeUseCase',
|
||||
];
|
||||
|
||||
for (const name of expectedExports) {
|
||||
expect(exported[name], `missing export: ${name}`).toBeDefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user