Files
gridpilot.gg/core/racing/application/use-cases/AcceptSponsorshipRequestUseCase.test.ts
2025-12-21 00:43:42 +01:00

185 lines
5.5 KiB
TypeScript

import type { NotificationService } from '@/notifications/application/ports/NotificationService';
import type { IWalletRepository } from '@core/payments/domain/repositories/IWalletRepository';
import type { Logger } from '@core/shared/application';
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
import { LeagueWallet } from '../../domain/entities/league-wallet/LeagueWallet';
import { Season } from '../../domain/entities/season/Season';
import { SponsorshipRequest } from '../../domain/entities/SponsorshipRequest';
import type { ILeagueWalletRepository } from '../../domain/repositories/ILeagueWalletRepository';
import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
import type { ISeasonSponsorshipRepository } from '../../domain/repositories/ISeasonSponsorshipRepository';
import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository';
import { Money } from '../../domain/value-objects/Money';
import { AcceptSponsorshipRequestUseCase } from './AcceptSponsorshipRequestUseCase';
describe('AcceptSponsorshipRequestUseCase', () => {
let mockSponsorshipRequestRepo: {
findById: Mock;
update: Mock;
};
let mockSeasonSponsorshipRepo: {
create: Mock;
};
let mockSeasonRepo: {
findById: Mock;
};
let mockNotificationService: {
sendNotification: Mock;
};
let processPayment: Mock;
let mockWalletRepo: {
findById: Mock;
update: Mock;
};
let mockLeagueWalletRepo: {
findById: Mock;
update: Mock;
};
let mockLogger: {
debug: Mock;
info: Mock;
warn: Mock;
error: Mock;
};
beforeEach(() => {
mockSponsorshipRequestRepo = {
findById: vi.fn(),
update: vi.fn(),
};
mockSeasonSponsorshipRepo = {
create: vi.fn(),
};
mockSeasonRepo = {
findById: vi.fn(),
};
mockNotificationService = {
sendNotification: vi.fn(),
};
processPayment = vi.fn();
mockWalletRepo = {
findById: vi.fn(),
update: vi.fn(),
};
mockLeagueWalletRepo = {
findById: vi.fn(),
update: vi.fn(),
};
mockLogger = {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
};
});
it('should send notification to sponsor, process payment, update wallets, and present result when accepting season sponsorship', async () => {
const output = {
present: vi.fn(),
};
const useCase = new AcceptSponsorshipRequestUseCase(
mockSponsorshipRequestRepo as unknown as ISponsorshipRequestRepository,
mockSeasonSponsorshipRepo as unknown as ISeasonSponsorshipRepository,
mockSeasonRepo as unknown as ISeasonRepository,
mockNotificationService as unknown as NotificationService,
processPayment,
mockWalletRepo as unknown as IWalletRepository,
mockLeagueWalletRepo as unknown as ILeagueWalletRepository,
mockLogger as unknown as Logger,
output,
);
const request = SponsorshipRequest.create({
id: 'req1',
sponsorId: 'sponsor1',
entityId: 'season1',
entityType: 'season',
tier: 'main',
offeredAmount: Money.create(1000),
status: 'pending',
});
const season = Season.create({
id: 'season1',
leagueId: 'league1',
gameId: 'game1',
name: 'Season 1',
startDate: new Date(),
endDate: new Date(),
});
mockSponsorshipRequestRepo.findById.mockResolvedValue(request);
mockSeasonRepo.findById.mockResolvedValue(season);
mockNotificationService.sendNotification.mockResolvedValue(undefined);
processPayment.mockResolvedValue({
success: true,
transactionId: 'txn1',
timestamp: new Date(),
});
mockWalletRepo.findById.mockResolvedValue({
id: 'sponsor1',
leagueId: 'league1',
balance: 2000,
totalRevenue: 0,
totalPlatformFees: 0,
totalWithdrawn: 0,
currency: 'USD',
createdAt: new Date(),
});
const leagueWallet = LeagueWallet.create({
id: 'league1',
leagueId: 'league1',
balance: Money.create(500),
});
mockLeagueWalletRepo.findById.mockResolvedValue(leagueWallet);
const result = await useCase.execute({
requestId: 'req1',
respondedBy: 'driver1',
});
expect(result.isOk()).toBe(true);
expect(result.unwrap()).toBeUndefined();
expect(mockNotificationService.sendNotification).toHaveBeenCalledWith({
recipientId: 'sponsor1',
type: 'sponsorship_request_accepted',
title: 'Sponsorship Accepted',
body: 'Your sponsorship request for Season 1 has been accepted.',
channel: 'in_app',
urgency: 'toast',
data: {
requestId: 'req1',
sponsorshipId: expect.any(String),
},
});
expect(processPayment).toHaveBeenCalledWith({
amount: 1000,
payerId: 'sponsor1',
description: 'Sponsorship payment for season season1',
metadata: { requestId: 'req1' },
});
expect(mockWalletRepo.update).toHaveBeenCalledWith(
expect.objectContaining({
id: 'sponsor1',
balance: 1000,
}),
);
expect(mockLeagueWalletRepo.update).toHaveBeenCalledWith(
expect.objectContaining({
id: 'league1',
balance: expect.objectContaining({ amount: 1400 }),
}),
);
expect(output.present).toHaveBeenCalledWith({
requestId: 'req1',
sponsorshipId: expect.any(String),
status: 'accepted',
acceptedAt: expect.any(Date),
platformFee: expect.any(Number),
netAmount: expect.any(Number),
});
});
});