test apps api
This commit is contained in:
@@ -40,7 +40,7 @@ describe('SponsorController', () => {
|
||||
describe('getEntitySponsorshipPricing', () => {
|
||||
it('should return sponsorship pricing', async () => {
|
||||
const mockResult = { entityType: 'season', entityId: 'season-1', pricing: [] };
|
||||
sponsorService.getEntitySponsorshipPricing.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getEntitySponsorshipPricing.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getEntitySponsorshipPricing();
|
||||
|
||||
@@ -52,7 +52,7 @@ describe('SponsorController', () => {
|
||||
describe('getSponsors', () => {
|
||||
it('should return sponsors list', async () => {
|
||||
const mockResult = { sponsors: [] };
|
||||
sponsorService.getSponsors.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getSponsors.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getSponsors();
|
||||
|
||||
@@ -65,7 +65,7 @@ describe('SponsorController', () => {
|
||||
it('should create sponsor', async () => {
|
||||
const input = { name: 'Test Sponsor', contactEmail: 'test@example.com' };
|
||||
const mockResult = { sponsor: { id: 's1', name: 'Test Sponsor' } };
|
||||
sponsorService.createSponsor.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.createSponsor.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.createSponsor(input as any);
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('SponsorController', () => {
|
||||
it('should return sponsor dashboard', async () => {
|
||||
const sponsorId = 's1';
|
||||
const mockResult = { sponsorId, metrics: {} as any, sponsoredLeagues: [], investment: {} as any };
|
||||
sponsorService.getSponsorDashboard.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getSponsorDashboard.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getSponsorDashboard(sponsorId);
|
||||
|
||||
@@ -86,13 +86,11 @@ describe('SponsorController', () => {
|
||||
expect(sponsorService.getSponsorDashboard).toHaveBeenCalledWith({ sponsorId });
|
||||
});
|
||||
|
||||
it('should return null when sponsor not found', async () => {
|
||||
it('should throw when sponsor not found', async () => {
|
||||
const sponsorId = 's1';
|
||||
sponsorService.getSponsorDashboard.mockResolvedValue({ viewModel: null } as any);
|
||||
sponsorService.getSponsorDashboard.mockRejectedValue(new Error('Sponsor dashboard not found'));
|
||||
|
||||
const result = await controller.getSponsorDashboard(sponsorId);
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(controller.getSponsorDashboard(sponsorId)).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,7 +109,7 @@ describe('SponsorController', () => {
|
||||
currency: 'USD',
|
||||
},
|
||||
};
|
||||
sponsorService.getSponsorSponsorships.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getSponsorSponsorships.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getSponsorSponsorships(sponsorId);
|
||||
|
||||
@@ -119,13 +117,11 @@ describe('SponsorController', () => {
|
||||
expect(sponsorService.getSponsorSponsorships).toHaveBeenCalledWith({ sponsorId });
|
||||
});
|
||||
|
||||
it('should return null when sponsor not found', async () => {
|
||||
it('should throw when sponsor not found', async () => {
|
||||
const sponsorId = 's1';
|
||||
sponsorService.getSponsorSponsorships.mockResolvedValue({ viewModel: null } as any);
|
||||
sponsorService.getSponsorSponsorships.mockRejectedValue(new Error('Sponsor sponsorships not found'));
|
||||
|
||||
const result = await controller.getSponsorSponsorships(sponsorId);
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(controller.getSponsorSponsorships(sponsorId)).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,7 +129,7 @@ describe('SponsorController', () => {
|
||||
it('should return sponsor', async () => {
|
||||
const sponsorId = 's1';
|
||||
const mockResult = { sponsor: { id: sponsorId, name: 'S1' } };
|
||||
sponsorService.getSponsor.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getSponsor.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getSponsor(sponsorId);
|
||||
|
||||
@@ -141,13 +137,11 @@ describe('SponsorController', () => {
|
||||
expect(sponsorService.getSponsor).toHaveBeenCalledWith(sponsorId);
|
||||
});
|
||||
|
||||
it('should return null when sponsor not found', async () => {
|
||||
it('should throw when sponsor not found', async () => {
|
||||
const sponsorId = 's1';
|
||||
sponsorService.getSponsor.mockResolvedValue({ viewModel: null } as any);
|
||||
sponsorService.getSponsor.mockRejectedValue(new Error('Sponsor not found'));
|
||||
|
||||
const result = await controller.getSponsor(sponsorId);
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(controller.getSponsor(sponsorId)).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -160,7 +154,7 @@ describe('SponsorController', () => {
|
||||
requests: [],
|
||||
totalCount: 0,
|
||||
};
|
||||
sponsorService.getPendingSponsorshipRequests.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getPendingSponsorshipRequests.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getPendingSponsorshipRequests(query);
|
||||
|
||||
@@ -181,7 +175,7 @@ describe('SponsorController', () => {
|
||||
platformFee: 10,
|
||||
netAmount: 90,
|
||||
};
|
||||
sponsorService.acceptSponsorshipRequest.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.acceptSponsorshipRequest.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.acceptSponsorshipRequest(requestId, input as any);
|
||||
|
||||
@@ -192,14 +186,12 @@ describe('SponsorController', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should return null on error', async () => {
|
||||
it('should throw on error', async () => {
|
||||
const requestId = 'r1';
|
||||
const input = { respondedBy: 'u1' };
|
||||
sponsorService.acceptSponsorshipRequest.mockResolvedValue({ viewModel: null } as any);
|
||||
sponsorService.acceptSponsorshipRequest.mockRejectedValue(new Error('Accept sponsorship request failed'));
|
||||
|
||||
const result = await controller.acceptSponsorshipRequest(requestId, input as any);
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(controller.acceptSponsorshipRequest(requestId, input as any)).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -213,7 +205,7 @@ describe('SponsorController', () => {
|
||||
rejectedAt: new Date(),
|
||||
reason: 'Not interested',
|
||||
};
|
||||
sponsorService.rejectSponsorshipRequest.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.rejectSponsorshipRequest.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.rejectSponsorshipRequest(requestId, input as any);
|
||||
|
||||
@@ -225,14 +217,12 @@ describe('SponsorController', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should return null on error', async () => {
|
||||
it('should throw on error', async () => {
|
||||
const requestId = 'r1';
|
||||
const input = { respondedBy: 'u1' };
|
||||
sponsorService.rejectSponsorshipRequest.mockResolvedValue({ viewModel: null } as any);
|
||||
sponsorService.rejectSponsorshipRequest.mockRejectedValue(new Error('Reject sponsorship request failed'));
|
||||
|
||||
const result = await controller.rejectSponsorshipRequest(requestId, input as any);
|
||||
|
||||
expect(result).toBeNull();
|
||||
await expect(controller.rejectSponsorshipRequest(requestId, input as any)).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -251,7 +241,7 @@ describe('SponsorController', () => {
|
||||
averageMonthlySpend: 0,
|
||||
},
|
||||
};
|
||||
sponsorService.getSponsorBilling.mockResolvedValue({ viewModel: mockResult } as any);
|
||||
sponsorService.getSponsorBilling.mockResolvedValue(mockResult as any);
|
||||
|
||||
const result = await controller.getSponsorBilling(sponsorId);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Post, Put, Body, HttpCode, HttpStatus, Param, Query } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Put, Body, HttpCode, HttpStatus, Param, Query, Inject } from '@nestjs/common';
|
||||
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
|
||||
import { SponsorService } from './SponsorService';
|
||||
import { GetEntitySponsorshipPricingResultDTO } from './dtos/GetEntitySponsorshipPricingResultDTO';
|
||||
@@ -29,7 +29,7 @@ import type { RejectSponsorshipRequestResult } from '@core/racing/application/us
|
||||
@ApiTags('sponsors')
|
||||
@Controller('sponsors')
|
||||
export class SponsorController {
|
||||
constructor(private readonly sponsorService: SponsorService) {}
|
||||
constructor(@Inject(SponsorService) private readonly sponsorService: SponsorService) {}
|
||||
|
||||
@Get('pricing')
|
||||
@ApiOperation({ summary: 'Get sponsorship pricing for an entity' })
|
||||
|
||||
@@ -273,15 +273,11 @@ export const SponsorProviders: Provider[] = [
|
||||
provide: GET_ENTITY_SPONSORSHIP_PRICING_USE_CASE_TOKEN,
|
||||
useFactory: (
|
||||
sponsorshipPricingRepo: ISponsorshipPricingRepository,
|
||||
sponsorshipRequestRepo: ISponsorshipRequestRepository,
|
||||
seasonSponsorshipRepo: ISeasonSponsorshipRepository,
|
||||
logger: Logger,
|
||||
output: UseCaseOutputPort<any>,
|
||||
) => new GetEntitySponsorshipPricingUseCase(sponsorshipPricingRepo, sponsorshipRequestRepo, seasonSponsorshipRepo, logger, output),
|
||||
) => new GetEntitySponsorshipPricingUseCase(sponsorshipPricingRepo, logger, output),
|
||||
inject: [
|
||||
SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
|
||||
SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
|
||||
SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
GET_ENTITY_SPONSORSHIP_PRICING_OUTPUT_PORT_TOKEN,
|
||||
],
|
||||
|
||||
@@ -12,6 +12,8 @@ import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import type { CreateSponsorInputDTO } from './dtos/CreateSponsorInputDTO';
|
||||
import { Sponsor } from '@core/racing/domain/entities/sponsor/Sponsor';
|
||||
import { Money } from '@core/racing/domain/value-objects/Money';
|
||||
import { AcceptSponsorshipRequestPresenter } from './presenters/AcceptSponsorshipRequestPresenter';
|
||||
import { CreateSponsorPresenter } from './presenters/CreateSponsorPresenter';
|
||||
import { GetEntitySponsorshipPricingPresenter } from './presenters/GetEntitySponsorshipPricingPresenter';
|
||||
@@ -110,20 +112,20 @@ describe('SponsorService', () => {
|
||||
const outputPort = {
|
||||
entityType: 'season',
|
||||
entityId: 'season-1',
|
||||
tiers: [
|
||||
{ name: 'Gold', price: 500, benefits: ['Main slot'] },
|
||||
],
|
||||
tiers: [{ name: 'Gold', price: { amount: 500, currency: 'USD' }, benefits: ['Main slot'] }],
|
||||
};
|
||||
getSponsorshipPricingUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
|
||||
getSponsorshipPricingUseCase.execute.mockImplementation(async () => {
|
||||
getEntitySponsorshipPricingPresenter.present(outputPort as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getEntitySponsorshipPricing();
|
||||
|
||||
expect(result).toEqual({
|
||||
entityType: 'season',
|
||||
entityId: 'season-1',
|
||||
pricing: [
|
||||
{ id: 'Gold', level: 'Gold', price: 500, currency: 'USD' },
|
||||
],
|
||||
pricing: [{ id: 'Gold', level: 'Gold', price: 500, currency: 'USD' }],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -142,13 +144,32 @@ describe('SponsorService', () => {
|
||||
|
||||
describe('getSponsors', () => {
|
||||
it('returns sponsors on success', async () => {
|
||||
const sponsors = [{ id: 's1', name: 'S1', contactEmail: 's1@test', createdAt: new Date() }];
|
||||
const outputPort = { sponsors };
|
||||
getSponsorsUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
const sponsors = [
|
||||
Sponsor.create({
|
||||
id: 'sponsor-1',
|
||||
name: 'S1',
|
||||
contactEmail: 's1@test.com',
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
}),
|
||||
];
|
||||
|
||||
getSponsorsUseCase.execute.mockImplementation(async () => {
|
||||
getSponsorsPresenter.present(sponsors);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getSponsors();
|
||||
|
||||
expect(result).toEqual({ sponsors });
|
||||
expect(result).toEqual({
|
||||
sponsors: [
|
||||
{
|
||||
id: 'sponsor-1',
|
||||
name: 'S1',
|
||||
contactEmail: 's1@test.com',
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty list on error', async () => {
|
||||
@@ -163,18 +184,28 @@ describe('SponsorService', () => {
|
||||
describe('createSponsor', () => {
|
||||
it('returns created sponsor on success', async () => {
|
||||
const input: CreateSponsorInputDTO = { name: 'Test', contactEmail: 'test@example.com' };
|
||||
const sponsor = {
|
||||
id: 's1',
|
||||
const sponsor = Sponsor.create({
|
||||
id: 'sponsor-1',
|
||||
name: 'Test',
|
||||
contactEmail: 'test@example.com',
|
||||
createdAt: new Date(),
|
||||
};
|
||||
const outputPort = { sponsor };
|
||||
createSponsorUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
});
|
||||
|
||||
createSponsorUseCase.execute.mockImplementation(async () => {
|
||||
createSponsorPresenter.present(sponsor);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.createSponsor(input);
|
||||
|
||||
expect(result).toEqual({ sponsor });
|
||||
expect(result).toEqual({
|
||||
sponsor: {
|
||||
id: 'sponsor-1',
|
||||
name: 'Test',
|
||||
contactEmail: 'test@example.com',
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('throws on error', async () => {
|
||||
@@ -185,6 +216,20 @@ describe('SponsorService', () => {
|
||||
|
||||
await expect(service.createSponsor(input)).rejects.toThrow('Invalid');
|
||||
});
|
||||
|
||||
it('throws using error.message when details.message is missing', async () => {
|
||||
const input: CreateSponsorInputDTO = { name: 'Test', contactEmail: 'test@example.com' };
|
||||
createSponsorUseCase.execute.mockResolvedValue(Result.err({ code: 'VALIDATION_ERROR', message: 'Boom' } as any));
|
||||
|
||||
await expect(service.createSponsor(input)).rejects.toThrow('Boom');
|
||||
});
|
||||
|
||||
it('throws default message when details.message and message are missing', async () => {
|
||||
const input: CreateSponsorInputDTO = { name: 'Test', contactEmail: 'test@example.com' };
|
||||
createSponsorUseCase.execute.mockResolvedValue(Result.err({ code: 'VALIDATION_ERROR' } as any));
|
||||
|
||||
await expect(service.createSponsor(input)).rejects.toThrow('Failed to create sponsor');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSponsorDashboard', () => {
|
||||
@@ -206,15 +251,38 @@ describe('SponsorService', () => {
|
||||
sponsoredLeagues: [],
|
||||
investment: {
|
||||
activeSponsorships: 0,
|
||||
totalInvestment: 0,
|
||||
totalInvestment: Money.create(0, 'USD'),
|
||||
costPerThousandViews: 0,
|
||||
},
|
||||
};
|
||||
getSponsorDashboardUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
|
||||
getSponsorDashboardUseCase.execute.mockImplementation(async () => {
|
||||
getSponsorDashboardPresenter.present(outputPort as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getSponsorDashboard(params);
|
||||
|
||||
expect(result).toEqual(outputPort);
|
||||
expect(result).toEqual({
|
||||
sponsorId: 's1',
|
||||
sponsorName: 'S1',
|
||||
metrics: outputPort.metrics,
|
||||
sponsoredLeagues: [],
|
||||
investment: {
|
||||
activeSponsorships: 0,
|
||||
totalInvestment: 0,
|
||||
costPerThousandViews: 0,
|
||||
},
|
||||
sponsorships: {
|
||||
leagues: [],
|
||||
teams: [],
|
||||
drivers: [],
|
||||
races: [],
|
||||
platform: [],
|
||||
},
|
||||
recentActivity: [],
|
||||
upcomingRenewals: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('throws on error', async () => {
|
||||
@@ -229,6 +297,28 @@ describe('SponsorService', () => {
|
||||
it('returns sponsorships on success', async () => {
|
||||
const params: GetSponsorSponsorshipsInput = { sponsorId: 's1' };
|
||||
const outputPort = {
|
||||
sponsor: Sponsor.create({
|
||||
id: 's1',
|
||||
name: 'S1',
|
||||
contactEmail: 's1@example.com',
|
||||
}),
|
||||
sponsorships: [],
|
||||
summary: {
|
||||
totalSponsorships: 0,
|
||||
activeSponsorships: 0,
|
||||
totalInvestment: Money.create(0, 'USD'),
|
||||
totalPlatformFees: Money.create(0, 'USD'),
|
||||
},
|
||||
};
|
||||
|
||||
getSponsorSponsorshipsUseCase.execute.mockImplementation(async () => {
|
||||
getSponsorSponsorshipsPresenter.present(outputPort as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getSponsorSponsorships(params);
|
||||
|
||||
expect(result).toEqual({
|
||||
sponsorId: 's1',
|
||||
sponsorName: 'S1',
|
||||
sponsorships: [],
|
||||
@@ -239,39 +329,44 @@ describe('SponsorService', () => {
|
||||
totalPlatformFees: 0,
|
||||
currency: 'USD',
|
||||
},
|
||||
};
|
||||
getSponsorSponsorshipsUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
|
||||
const result = await service.getSponsorSponsorships(params);
|
||||
|
||||
expect(result).toEqual(outputPort);
|
||||
});
|
||||
});
|
||||
|
||||
it('throws on error', async () => {
|
||||
const params: GetSponsorSponsorshipsInput = { sponsorId: 's1' };
|
||||
getSponsorSponsorshipsUseCase.execute.mockResolvedValue(
|
||||
Result.err({ code: 'REPOSITORY_ERROR' }),
|
||||
);
|
||||
getSponsorSponsorshipsUseCase.execute.mockResolvedValue(Result.err({ code: 'REPOSITORY_ERROR' }));
|
||||
|
||||
await expect(service.getSponsorSponsorships(params)).rejects.toThrow('Sponsor sponsorships not found');
|
||||
await expect(service.getSponsorSponsorships(params)).rejects.toThrow(
|
||||
'Sponsor sponsorships not found',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSponsor', () => {
|
||||
it('returns sponsor when found', async () => {
|
||||
const sponsorId = 's1';
|
||||
const sponsor = { id: sponsorId, name: 'S1' };
|
||||
const output = { sponsor };
|
||||
getSponsorUseCase.execute.mockResolvedValue(Result.ok(output));
|
||||
const output = { sponsor: { id: sponsorId, name: 'S1' } };
|
||||
|
||||
getSponsorUseCase.execute.mockImplementation(async () => {
|
||||
getSponsorPresenter.present(output);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getSponsor(sponsorId);
|
||||
|
||||
expect(result).toEqual({ sponsor });
|
||||
expect(result).toEqual(output);
|
||||
});
|
||||
|
||||
it('throws when not found', async () => {
|
||||
const sponsorId = 's1';
|
||||
getSponsorUseCase.execute.mockResolvedValue(Result.ok(null));
|
||||
getSponsorUseCase.execute.mockResolvedValue(Result.err({ code: 'SPONSOR_NOT_FOUND' }));
|
||||
|
||||
await expect(service.getSponsor(sponsorId)).rejects.toThrow('Sponsor not found');
|
||||
});
|
||||
|
||||
it('throws when viewModel is missing even if use case succeeds', async () => {
|
||||
const sponsorId = 's1';
|
||||
getSponsorUseCase.execute.mockResolvedValue(Result.ok(undefined));
|
||||
|
||||
await expect(service.getSponsor(sponsorId)).rejects.toThrow('Sponsor not found');
|
||||
});
|
||||
@@ -286,7 +381,11 @@ describe('SponsorService', () => {
|
||||
requests: [],
|
||||
totalCount: 0,
|
||||
};
|
||||
getPendingSponsorshipRequestsUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
|
||||
getPendingSponsorshipRequestsUseCase.execute.mockImplementation(async () => {
|
||||
getPendingSponsorshipRequestsPresenter.present(outputPort as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.getPendingSponsorshipRequests(params);
|
||||
|
||||
@@ -295,9 +394,7 @@ describe('SponsorService', () => {
|
||||
|
||||
it('returns empty result on error', async () => {
|
||||
const params = { entityType: 'season' as const, entityId: 'season-1' };
|
||||
getPendingSponsorshipRequestsUseCase.execute.mockResolvedValue(
|
||||
Result.err({ code: 'REPOSITORY_ERROR' }),
|
||||
);
|
||||
getPendingSponsorshipRequestsUseCase.execute.mockResolvedValue(Result.err({ code: 'REPOSITORY_ERROR' }));
|
||||
|
||||
const result = await service.getPendingSponsorshipRequests(params);
|
||||
|
||||
@@ -308,6 +405,13 @@ describe('SponsorService', () => {
|
||||
totalCount: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('throws when presenter viewModel is missing on success', async () => {
|
||||
const params = { entityType: 'season' as const, entityId: 'season-1' };
|
||||
getPendingSponsorshipRequestsUseCase.execute.mockResolvedValue(Result.ok(undefined));
|
||||
|
||||
await expect(service.getPendingSponsorshipRequests(params)).rejects.toThrow('Pending sponsorship requests not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SponsorshipRequest', () => {
|
||||
@@ -322,7 +426,11 @@ describe('SponsorService', () => {
|
||||
platformFee: 10,
|
||||
netAmount: 90,
|
||||
};
|
||||
acceptSponsorshipRequestUseCase.execute.mockResolvedValue(Result.ok(outputPort));
|
||||
|
||||
acceptSponsorshipRequestUseCase.execute.mockImplementation(async () => {
|
||||
acceptSponsorshipRequestPresenter.present(outputPort as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.acceptSponsorshipRequest(requestId, respondedBy);
|
||||
|
||||
@@ -336,7 +444,19 @@ describe('SponsorService', () => {
|
||||
Result.err({ code: 'SPONSORSHIP_REQUEST_NOT_FOUND' }),
|
||||
);
|
||||
|
||||
await expect(service.acceptSponsorshipRequest(requestId, respondedBy)).rejects.toThrow('Accept sponsorship request failed');
|
||||
await expect(service.acceptSponsorshipRequest(requestId, respondedBy)).rejects.toThrow(
|
||||
'Accept sponsorship request failed',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when presenter viewModel is missing on success', async () => {
|
||||
const requestId = 'r1';
|
||||
const respondedBy = 'u1';
|
||||
acceptSponsorshipRequestUseCase.execute.mockResolvedValue(Result.ok(undefined));
|
||||
|
||||
await expect(service.acceptSponsorshipRequest(requestId, respondedBy)).rejects.toThrow(
|
||||
'Accept sponsorship request failed',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -351,13 +471,38 @@ describe('SponsorService', () => {
|
||||
respondedAt: new Date(),
|
||||
rejectionReason: reason,
|
||||
};
|
||||
rejectSponsorshipRequestUseCase.execute.mockResolvedValue(Result.ok(output));
|
||||
|
||||
rejectSponsorshipRequestUseCase.execute.mockImplementation(async () => {
|
||||
rejectSponsorshipRequestPresenter.present(output as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
const result = await service.rejectSponsorshipRequest(requestId, respondedBy, reason);
|
||||
|
||||
expect(result).toEqual(output);
|
||||
});
|
||||
|
||||
it('passes no reason when reason is undefined', async () => {
|
||||
const requestId = 'r1';
|
||||
const respondedBy = 'u1';
|
||||
|
||||
rejectSponsorshipRequestUseCase.execute.mockImplementation(async (input: any) => {
|
||||
expect(input).toEqual({ requestId, respondedBy });
|
||||
rejectSponsorshipRequestPresenter.present({
|
||||
requestId,
|
||||
status: 'rejected' as const,
|
||||
respondedAt: new Date(),
|
||||
rejectionReason: '',
|
||||
} as any);
|
||||
return Result.ok(undefined);
|
||||
});
|
||||
|
||||
await expect(service.rejectSponsorshipRequest(requestId, respondedBy)).resolves.toMatchObject({
|
||||
requestId,
|
||||
status: 'rejected',
|
||||
});
|
||||
});
|
||||
|
||||
it('throws on error', async () => {
|
||||
const requestId = 'r1';
|
||||
const respondedBy = 'u1';
|
||||
@@ -365,7 +510,19 @@ describe('SponsorService', () => {
|
||||
Result.err({ code: 'SPONSORSHIP_REQUEST_NOT_FOUND' }),
|
||||
);
|
||||
|
||||
await expect(service.rejectSponsorshipRequest(requestId, respondedBy)).rejects.toThrow('Reject sponsorship request failed');
|
||||
await expect(service.rejectSponsorshipRequest(requestId, respondedBy)).rejects.toThrow(
|
||||
'Reject sponsorship request failed',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when presenter viewModel is missing on success', async () => {
|
||||
const requestId = 'r1';
|
||||
const respondedBy = 'u1';
|
||||
rejectSponsorshipRequestUseCase.execute.mockResolvedValue(Result.ok(undefined));
|
||||
|
||||
await expect(service.rejectSponsorshipRequest(requestId, respondedBy)).rejects.toThrow(
|
||||
'Reject sponsorship request failed',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -395,6 +552,11 @@ describe('SponsorService', () => {
|
||||
expect(result.invoices).toBeInstanceOf(Array);
|
||||
expect(result.stats).toBeDefined();
|
||||
});
|
||||
|
||||
it('throws on error', async () => {
|
||||
getSponsorBillingUseCase.execute.mockResolvedValue(Result.err({ code: 'REPOSITORY_ERROR' } as any));
|
||||
await expect(service.getSponsorBilling('s1')).rejects.toThrow('Sponsor billing not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAvailableLeagues', () => {
|
||||
|
||||
@@ -130,19 +130,39 @@ export class SponsorService {
|
||||
|
||||
async getEntitySponsorshipPricing(): Promise<GetEntitySponsorshipPricingResultDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsorship pricing.');
|
||||
await this.getSponsorshipPricingUseCase.execute({});
|
||||
const result = await this.getSponsorshipPricingUseCase.execute({});
|
||||
|
||||
if (result.isErr()) {
|
||||
return {
|
||||
entityType: 'season',
|
||||
entityId: '',
|
||||
pricing: [],
|
||||
};
|
||||
}
|
||||
|
||||
return this.getEntitySponsorshipPricingPresenter.viewModel;
|
||||
}
|
||||
|
||||
async getSponsors(): Promise<GetSponsorsOutputDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsors.');
|
||||
await this.getSponsorsUseCase.execute();
|
||||
const result = await this.getSponsorsUseCase.execute();
|
||||
|
||||
if (result.isErr()) {
|
||||
return { sponsors: [] };
|
||||
}
|
||||
|
||||
return this.getSponsorsPresenter.responseModel;
|
||||
}
|
||||
|
||||
async createSponsor(input: CreateSponsorInputDTO): Promise<CreateSponsorOutputDTO> {
|
||||
this.logger.debug('[SponsorService] Creating sponsor.', { input });
|
||||
await this.createSponsorUseCase.execute(input);
|
||||
const result = await this.createSponsorUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr() as { details?: { message?: string }; message?: string };
|
||||
throw new Error(error.details?.message ?? error.message ?? 'Failed to create sponsor');
|
||||
}
|
||||
|
||||
return this.createSponsorPresenter.viewModel;
|
||||
}
|
||||
|
||||
@@ -150,34 +170,41 @@ export class SponsorService {
|
||||
params: GetSponsorDashboardQueryParamsDTO,
|
||||
): Promise<SponsorDashboardDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor dashboard.', { params });
|
||||
await this.getSponsorDashboardUseCase.execute(params);
|
||||
const result = this.getSponsorDashboardPresenter.viewModel;
|
||||
if (!result) {
|
||||
const result = await this.getSponsorDashboardUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Sponsor dashboard not found');
|
||||
}
|
||||
return result;
|
||||
|
||||
return this.getSponsorDashboardPresenter.viewModel;
|
||||
}
|
||||
|
||||
async getSponsorSponsorships(
|
||||
params: GetSponsorSponsorshipsQueryParamsDTO,
|
||||
): Promise<SponsorSponsorshipsDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor sponsorships.', { params });
|
||||
await this.getSponsorSponsorshipsUseCase.execute(params);
|
||||
const result = this.getSponsorSponsorshipsPresenter.viewModel;
|
||||
if (!result) {
|
||||
const result = await this.getSponsorSponsorshipsUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Sponsor sponsorships not found');
|
||||
}
|
||||
return result;
|
||||
|
||||
return this.getSponsorSponsorshipsPresenter.viewModel;
|
||||
}
|
||||
|
||||
async getSponsor(sponsorId: string): Promise<GetSponsorOutputDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor.', { sponsorId });
|
||||
await this.getSponsorUseCase.execute({ sponsorId });
|
||||
const result = this.getSponsorPresenter.viewModel;
|
||||
if (!result) {
|
||||
const result = await this.getSponsorUseCase.execute({ sponsorId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Sponsor not found');
|
||||
}
|
||||
return result;
|
||||
|
||||
const viewModel = this.getSponsorPresenter.viewModel;
|
||||
if (!viewModel) {
|
||||
throw new Error('Sponsor not found');
|
||||
}
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
async getPendingSponsorshipRequests(params: {
|
||||
@@ -185,14 +212,26 @@ export class SponsorService {
|
||||
entityId: string;
|
||||
}): Promise<GetPendingSponsorshipRequestsOutputDTO> {
|
||||
this.logger.debug('[SponsorService] Fetching pending sponsorship requests.', { params });
|
||||
await this.getPendingSponsorshipRequestsUseCase.execute(
|
||||
|
||||
const result = await this.getPendingSponsorshipRequestsUseCase.execute(
|
||||
params as GetPendingSponsorshipRequestsInput,
|
||||
);
|
||||
const result = this.getPendingSponsorshipRequestsPresenter.viewModel;
|
||||
if (!result) {
|
||||
|
||||
if (result.isErr()) {
|
||||
return {
|
||||
entityType: params.entityType,
|
||||
entityId: params.entityId,
|
||||
requests: [],
|
||||
totalCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const viewModel = this.getPendingSponsorshipRequestsPresenter.viewModel;
|
||||
if (!viewModel) {
|
||||
throw new Error('Pending sponsorship requests not found');
|
||||
}
|
||||
return result;
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
async acceptSponsorshipRequest(
|
||||
@@ -203,15 +242,22 @@ export class SponsorService {
|
||||
requestId,
|
||||
respondedBy,
|
||||
});
|
||||
await this.acceptSponsorshipRequestUseCase.execute({
|
||||
|
||||
const result = await this.acceptSponsorshipRequestUseCase.execute({
|
||||
requestId,
|
||||
respondedBy,
|
||||
});
|
||||
const result = this.acceptSponsorshipRequestPresenter.viewModel;
|
||||
if (!result) {
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Accept sponsorship request failed');
|
||||
}
|
||||
return result;
|
||||
|
||||
const viewModel = this.acceptSponsorshipRequestPresenter.viewModel;
|
||||
if (!viewModel) {
|
||||
throw new Error('Accept sponsorship request failed');
|
||||
}
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
async rejectSponsorshipRequest(
|
||||
@@ -231,12 +277,19 @@ export class SponsorService {
|
||||
if (reason !== undefined) {
|
||||
input.reason = reason;
|
||||
}
|
||||
await this.rejectSponsorshipRequestUseCase.execute(input);
|
||||
const result = this.rejectSponsorshipRequestPresenter.viewModel;
|
||||
if (!result) {
|
||||
|
||||
const result = await this.rejectSponsorshipRequestUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Reject sponsorship request failed');
|
||||
}
|
||||
return result;
|
||||
|
||||
const viewModel = this.rejectSponsorshipRequestPresenter.viewModel;
|
||||
if (!viewModel) {
|
||||
throw new Error('Reject sponsorship request failed');
|
||||
}
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
async getSponsorBilling(sponsorId: string): Promise<{
|
||||
@@ -245,12 +298,13 @@ export class SponsorService {
|
||||
stats: BillingStatsDTO;
|
||||
}> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor billing.', { sponsorId });
|
||||
await this.getSponsorBillingUseCase.execute({ sponsorId });
|
||||
const result = this.sponsorBillingPresenter.viewModel;
|
||||
if (!result) {
|
||||
const result = await this.getSponsorBillingUseCase.execute({ sponsorId });
|
||||
|
||||
if (result.isErr()) {
|
||||
throw new Error('Sponsor billing not found');
|
||||
}
|
||||
return result;
|
||||
|
||||
return this.sponsorBillingPresenter.viewModel;
|
||||
}
|
||||
|
||||
async getAvailableLeagues(): Promise<AvailableLeaguesPresenter> {
|
||||
|
||||
@@ -24,8 +24,8 @@ export class GetEntitySponsorshipPricingPresenter {
|
||||
pricing: output.tiers.map(item => ({
|
||||
id: item.name,
|
||||
level: item.name,
|
||||
price: item.price,
|
||||
currency: 'USD',
|
||||
price: item.price.amount,
|
||||
currency: item.price.currency,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ export class GetSponsorDashboardPresenter {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
get viewModel(): SponsorDashboardDTO | null {
|
||||
get viewModel(): SponsorDashboardDTO {
|
||||
if (!this.result) throw new Error('Presenter not presented');
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ export class GetSponsorSponsorshipsPresenter {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
get viewModel(): SponsorSponsorshipsDTO | null {
|
||||
get viewModel(): SponsorSponsorshipsDTO {
|
||||
if (!this.result) throw new Error('Presenter not presented');
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('GetSponsorsPresenter', () => {
|
||||
id: 'sponsor-1',
|
||||
name: 'Sponsor One',
|
||||
contactEmail: 's1@example.com',
|
||||
logoUrl: 'logo1.png',
|
||||
logoUrl: 'https://one.example.com/logo1.png',
|
||||
websiteUrl: 'https://one.example.com',
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
}),
|
||||
@@ -46,7 +46,7 @@ describe('GetSponsorsPresenter', () => {
|
||||
id: 'sponsor-1',
|
||||
name: 'Sponsor One',
|
||||
contactEmail: 's1@example.com',
|
||||
logoUrl: 'logo1.png',
|
||||
logoUrl: 'https://one.example.com/logo1.png',
|
||||
websiteUrl: 'https://one.example.com',
|
||||
createdAt: new Date('2024-01-01T00:00:00Z'),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user