133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
|
import type { Transaction, Wallet } from '../../domain/entities/Wallet';
|
|
import { TransactionType } from '../../domain/entities/Wallet';
|
|
import type { TransactionRepository, WalletRepository } from '../../domain/repositories/WalletRepository';
|
|
import { GetWalletUseCase, type GetWalletInput } from './GetWalletUseCase';
|
|
|
|
describe('GetWalletUseCase', () => {
|
|
let walletRepository: {
|
|
findByLeagueId: Mock;
|
|
create: Mock;
|
|
};
|
|
|
|
let transactionRepository: {
|
|
findByWalletId: Mock;
|
|
};
|
|
|
|
let useCase: GetWalletUseCase;
|
|
|
|
beforeEach(() => {
|
|
walletRepository = {
|
|
findByLeagueId: vi.fn(),
|
|
create: vi.fn(),
|
|
};
|
|
|
|
transactionRepository = {
|
|
findByWalletId: vi.fn(),
|
|
};
|
|
|
|
useCase = new GetWalletUseCase(
|
|
walletRepository as unknown as WalletRepository,
|
|
transactionRepository as unknown as TransactionRepository,
|
|
);
|
|
});
|
|
|
|
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');
|
|
});
|
|
|
|
it('returns 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);
|
|
const value = result.value;
|
|
expect(value).toEqual({
|
|
wallet,
|
|
transactions: [newer, older],
|
|
});
|
|
expect(transactionRepository.findByWalletId).toHaveBeenCalledWith('wallet-1');
|
|
});
|
|
|
|
it('creates wallet when missing, then returns 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);
|
|
|
|
const value = result.value;
|
|
expect(value).toEqual({
|
|
wallet: createdWalletArg,
|
|
transactions: [],
|
|
});
|
|
} finally {
|
|
vi.useRealTimers();
|
|
}
|
|
});
|
|
}); |