Files
gridpilot.gg/apps/website/lib/services/payments/WalletService.test.ts
2025-12-17 22:17:02 +01:00

131 lines
3.8 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { WalletService } from './WalletService';
import { PaymentsApiClient } from '../../api/payments/PaymentsApiClient';
import type { GetWalletOutputDto } from '../../dtos';
import { presentWallet } from '../../presenters/WalletPresenter';
// Mock the presenter
vi.mock('../../presenters/WalletPresenter', () => ({
presentWallet: vi.fn(),
}));
describe('WalletService', () => {
let mockApiClient: PaymentsApiClient;
let service: WalletService;
beforeEach(() => {
mockApiClient = {
getWallet: vi.fn(),
getMembershipFees: vi.fn(),
getPayments: vi.fn(),
createPayment: vi.fn(),
getPrizes: vi.fn(),
} as unknown as PaymentsApiClient;
service = new WalletService(mockApiClient);
});
describe('getWallet', () => {
it('should get wallet via API client and present it', async () => {
// Arrange
const driverId = 'driver-1';
const dto: GetWalletOutputDto = {
balance: 1000,
currency: 'USD',
transactions: [],
};
const expectedViewModel = {
balance: 1000,
currency: 'USD',
transactions: [],
};
vi.mocked(mockApiClient.getWallet).mockResolvedValue(dto);
vi.mocked(presentWallet).mockReturnValue(expectedViewModel);
// Act
const result = await service.getWallet(driverId);
// Assert
expect(mockApiClient.getWallet).toHaveBeenCalledWith(driverId);
expect(mockApiClient.getWallet).toHaveBeenCalledTimes(1);
expect(presentWallet).toHaveBeenCalledWith(dto);
expect(result).toBe(expectedViewModel);
});
it('should propagate API client errors', async () => {
// Arrange
const driverId = 'driver-1';
const error = new Error('API Error: Failed to get wallet');
vi.mocked(mockApiClient.getWallet).mockRejectedValue(error);
// Act & Assert
await expect(service.getWallet(driverId)).rejects.toThrow(
'API Error: Failed to get wallet'
);
expect(mockApiClient.getWallet).toHaveBeenCalledWith(driverId);
expect(mockApiClient.getWallet).toHaveBeenCalledTimes(1);
});
it('should handle different driver IDs', async () => {
// Arrange
const driverId = 'driver-2';
const dto: GetWalletOutputDto = {
balance: 500,
currency: 'EUR',
transactions: [],
};
const expectedViewModel = {
balance: 500,
currency: 'EUR',
transactions: [],
};
vi.mocked(mockApiClient.getWallet).mockResolvedValue(dto);
vi.mocked(presentWallet).mockReturnValue(expectedViewModel);
// Act
const result = await service.getWallet(driverId);
// Assert
expect(mockApiClient.getWallet).toHaveBeenCalledWith(driverId);
expect(result).toBe(expectedViewModel);
});
});
describe('Constructor Dependency Injection', () => {
it('should require apiClient', () => {
// This test verifies the constructor signature
expect(() => {
new WalletService(mockApiClient);
}).not.toThrow();
});
it('should use injected apiClient', async () => {
// Arrange
const customApiClient = {
getWallet: vi.fn().mockResolvedValue({ balance: 200, currency: 'USD', transactions: [] }),
getMembershipFees: vi.fn(),
getPayments: vi.fn(),
createPayment: vi.fn(),
getPrizes: vi.fn(),
} as unknown as PaymentsApiClient;
const customService = new WalletService(customApiClient);
vi.mocked(presentWallet).mockReturnValue({ balance: 200, currency: 'USD', transactions: [] });
// Act
await customService.getWallet('driver-1');
// Assert
expect(customApiClient.getWallet).toHaveBeenCalledWith('driver-1');
});
});
});