website refactor
This commit is contained in:
@@ -1,14 +1,9 @@
|
||||
import type { NotificationService } from '@core/notifications/application/ports/NotificationService';
|
||||
import type { WalletRepository } from '@core/payments/domain/repositories/WalletRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
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 { LeagueWalletRepository } from '../../domain/repositories/LeagueWalletRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { SeasonSponsorshipRepository } from '../../domain/repositories/SeasonSponsorshipRepository';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
import { Money } from '../../domain/value-objects/Money';
|
||||
import { AcceptSponsorshipRequestUseCase } from './AcceptSponsorshipRequestUseCase';
|
||||
|
||||
|
||||
@@ -6,15 +6,9 @@
|
||||
*/
|
||||
|
||||
import type { NotificationService } from '@core/notifications/application/ports/NotificationService';
|
||||
import type { WalletRepository } from '@core/payments/domain/repositories/WalletRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { SeasonSponsorship } from '../../domain/entities/season/SeasonSponsorship';
|
||||
import type { LeagueWalletRepository } from '../../domain/repositories/LeagueWalletRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { SeasonSponsorshipRepository } from '../../domain/repositories/SeasonSponsorshipRepository';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
|
||||
export interface AcceptSponsorshipRequestInput {
|
||||
requestId: string;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { ApplyForSponsorshipUseCase } from './ApplyForSponsorshipUseCase';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
import type { SponsorshipPricingRepository } from '../../domain/repositories/SponsorshipPricingRepository';
|
||||
import type { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Money } from '../../domain/value-objects/Money';
|
||||
import { ApplyForSponsorshipUseCase } from './ApplyForSponsorshipUseCase';
|
||||
|
||||
describe('ApplyForSponsorshipUseCase', () => {
|
||||
let mockSponsorshipRequestRepo: {
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
* (driver, team, race, or season/league).
|
||||
*/
|
||||
|
||||
import { SponsorshipRequest } from '../../domain/entities/SponsorshipRequest';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
import type { SponsorshipPricingRepository } from '../../domain/repositories/SponsorshipPricingRepository';
|
||||
import type { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import { Money, isCurrency } from '../../domain/value-objects/Money';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { Result } from '@/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { SponsorshipRequest } from '../../domain/entities/SponsorshipRequest';
|
||||
import { Money, isCurrency } from '../../domain/value-objects/Money';
|
||||
|
||||
export interface ApplyForSponsorshipInput {
|
||||
sponsorId: string;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { ApplyPenaltyUseCase, type ApplyPenaltyResult } from './ApplyPenaltyUseCase';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { ProtestRepository } from '../../domain/repositories/ProtestRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { ApplyPenaltyUseCase } from './ApplyPenaltyUseCase';
|
||||
|
||||
describe('ApplyPenaltyUseCase', () => {
|
||||
let mockPenaltyRepo: {
|
||||
create: Mock;
|
||||
@@ -46,15 +43,11 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
it('should return error when race does not exist', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue(null);
|
||||
|
||||
@@ -68,19 +61,15 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(false);
|
||||
expect(result.error!.code).toBe('RACE_NOT_FOUND');
|
||||
expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND');
|
||||
});
|
||||
|
||||
it('should return error when steward does not have authority', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -102,19 +91,15 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(false);
|
||||
expect(result.error!.code).toBe('INSUFFICIENT_AUTHORITY');
|
||||
expect(result.unwrapErr().code).toBe('INSUFFICIENT_AUTHORITY');
|
||||
});
|
||||
|
||||
it('should return error when protest does not exist', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -138,19 +123,15 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(false);
|
||||
expect(result.error!.code).toBe('PROTEST_NOT_FOUND');
|
||||
expect(result.unwrapErr().code).toBe('PROTEST_NOT_FOUND');
|
||||
});
|
||||
|
||||
it('should return error when protest is not upheld', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -174,19 +155,15 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(false);
|
||||
expect(result.error!.code).toBe('PROTEST_NOT_UPHELD');
|
||||
expect(result.unwrapErr().code).toBe('PROTEST_NOT_UPHELD');
|
||||
});
|
||||
|
||||
it('should return error when protest is not for this race', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -210,19 +187,15 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(false);
|
||||
expect(result.error!.code).toBe('PROTEST_NOT_FOR_RACE');
|
||||
expect(result.unwrapErr().code).toBe('PROTEST_NOT_FOR_RACE');
|
||||
});
|
||||
|
||||
it('should create penalty and return result on success', async () => {
|
||||
const output: { present: Mock } = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as unknown as IPenaltyRepository,
|
||||
mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockLogger as unknown as Logger);
|
||||
const useCase = new ApplyPenaltyUseCase(mockPenaltyRepo as any,
|
||||
mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any,
|
||||
mockLogger as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -246,22 +219,11 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
});
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presented = (expect(presented).toEqual({ penaltyId: expect.any(String) });
|
||||
const presented = result.unwrap();
|
||||
expect(presented.penaltyId).toBeDefined();
|
||||
|
||||
expect(mockPenaltyRepo.create).toHaveBeenCalledTimes(1);
|
||||
const createdPenalty = (mockPenaltyRepo.create as Mock).mock.calls[0]?.[0] as unknown as {
|
||||
leagueId: unknown;
|
||||
raceId: unknown;
|
||||
driverId: unknown;
|
||||
type: string;
|
||||
value?: number;
|
||||
reason: string;
|
||||
issuedBy: unknown;
|
||||
status: unknown;
|
||||
notes?: string;
|
||||
};
|
||||
const createdPenalty = (mockPenaltyRepo.create as Mock).mock.calls[0]?.[0] as any;
|
||||
|
||||
type ToStringable = { toString(): string };
|
||||
const asString = (value: unknown): string => {
|
||||
@@ -287,4 +249,4 @@ describe('ApplyPenaltyUseCase', () => {
|
||||
expect(asString(createdPenalty.status)).toBe('pending');
|
||||
expect(createdPenalty.notes).toBe('Test notes');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,15 +5,11 @@
|
||||
* The penalty can be standalone or linked to an upheld protest.
|
||||
*/
|
||||
|
||||
import { Penalty } from '../../domain/entities/penalty/Penalty';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { ProtestRepository } from '../../domain/repositories/ProtestRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import { randomUUID } from 'crypto';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { Result } from '@/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { Penalty } from '../../domain/entities/penalty/Penalty';
|
||||
|
||||
export interface ApplyPenaltyInput {
|
||||
raceId: string;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { CancelRaceUseCase, type CancelRaceResult } from './CancelRaceUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import { SessionType } from '../../domain/value-objects/SessionType';
|
||||
import { CancelRaceUseCase } from './CancelRaceUseCase';
|
||||
|
||||
describe('CancelRaceUseCase', () => {
|
||||
let useCase: CancelRaceUseCase;
|
||||
let raceRepository: {
|
||||
@@ -16,6 +15,7 @@ describe('CancelRaceUseCase', () => {
|
||||
info: Mock;
|
||||
error: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
raceRepository = {
|
||||
findById: vi.fn(),
|
||||
@@ -27,8 +27,8 @@ describe('CancelRaceUseCase', () => {
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
useCase = new CancelRaceUseCase(raceRepository as unknown as IRaceRepository,
|
||||
logger as unknown as Logger);
|
||||
useCase = new CancelRaceUseCase(raceRepository as any,
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('should cancel race successfully', async () => {
|
||||
@@ -48,14 +48,14 @@ describe('CancelRaceUseCase', () => {
|
||||
const result = await useCase.execute({ raceId, cancelledById: 'admin-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
expect(raceRepository.findById).toHaveBeenCalledWith(raceId);
|
||||
expect(raceRepository.update).toHaveBeenCalledTimes(1);
|
||||
const updatedRace = (raceRepository.update as Mock).mock.calls[0]?.[0] as Race;
|
||||
expect(updatedRace.id).toBe(raceId);
|
||||
expect(updatedRace.status.toString()).toBe('cancelled');
|
||||
|
||||
const presented = (expect(presented.race.id).toBe(raceId);
|
||||
expect(presented.race.id).toBe(raceId);
|
||||
expect(presented.race.status.toString()).toBe('cancelled');
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('CancelRaceUseCase', () => {
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return domain error if race is already cancelled', async () => {
|
||||
const raceId = 'race-1';
|
||||
@@ -91,7 +91,7 @@ describe('CancelRaceUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toContain('already cancelled');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return domain error if race is completed', async () => {
|
||||
const raceId = 'race-1';
|
||||
@@ -115,5 +115,5 @@ describe('CancelRaceUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toContain('completed race');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { CloseRaceEventStewardingUseCase, type CloseRaceEventStewardingResult } from './CloseRaceEventStewardingUseCase';
|
||||
import type { RaceEventRepository } from '../../domain/repositories/RaceEventRepository';
|
||||
import type { RaceRegistrationRepository } from '../../domain/repositories/RaceRegistrationRepository';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { DomainEventPublisher } from '@core/shared/domain/DomainEvent';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { RaceEvent } from '../../domain/entities/RaceEvent';
|
||||
import { Session } from '../../domain/entities/Session';
|
||||
import { SessionType } from '../../domain/value-objects/SessionType';
|
||||
import { CloseRaceEventStewardingUseCase } from './CloseRaceEventStewardingUseCase';
|
||||
|
||||
describe('CloseRaceEventStewardingUseCase', () => {
|
||||
let useCase: CloseRaceEventStewardingUseCase;
|
||||
let raceEventRepository: {
|
||||
@@ -27,6 +23,7 @@ describe('CloseRaceEventStewardingUseCase', () => {
|
||||
let logger: {
|
||||
error: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
raceEventRepository = {
|
||||
findAwaitingStewardingClose: vi.fn(),
|
||||
@@ -45,11 +42,11 @@ describe('CloseRaceEventStewardingUseCase', () => {
|
||||
logger = {
|
||||
error: vi.fn(),
|
||||
};
|
||||
useCase = new CloseRaceEventStewardingUseCase(logger as unknown as Logger,
|
||||
raceEventRepository as unknown as IRaceEventRepository,
|
||||
raceRegistrationRepository as unknown as IRaceRegistrationRepository,
|
||||
penaltyRepository as unknown as IPenaltyRepository,
|
||||
domainEventPublisher as unknown as DomainEventPublisher);
|
||||
useCase = new CloseRaceEventStewardingUseCase(logger as any,
|
||||
raceEventRepository as any,
|
||||
raceRegistrationRepository as any,
|
||||
penaltyRepository as any,
|
||||
domainEventPublisher as any);
|
||||
});
|
||||
|
||||
it('should close stewarding for expired events successfully', async () => {
|
||||
@@ -82,33 +79,27 @@ describe('CloseRaceEventStewardingUseCase', () => {
|
||||
const result = await useCase.execute({ raceId: 'event-1', closedById: 'admin-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
expect(raceEventRepository.findAwaitingStewardingClose).toHaveBeenCalled();
|
||||
expect(raceEventRepository.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ status: 'closed' })
|
||||
);
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled();
|
||||
const presentedRace = (status?: unknown;
|
||||
};
|
||||
const presentedId =
|
||||
presentedRace?.id && typeof presentedRace.id === 'object' && typeof presentedRace.id.toString === 'function'
|
||||
? presentedRace.id.toString()
|
||||
: presentedRace?.id;
|
||||
|
||||
expect(presentedId).toBe('event-1');
|
||||
expect(presentedRace?.status).toBe('closed');
|
||||
expect(presented.race.id).toBe('event-1');
|
||||
expect(presented.race.status).toBe('closed');
|
||||
});
|
||||
|
||||
it('should handle no expired events', async () => {
|
||||
it('should return error when no expired events', async () => {
|
||||
raceEventRepository.findAwaitingStewardingClose.mockResolvedValue([]);
|
||||
|
||||
const result = await useCase.execute({ raceId: 'event-1', closedById: 'admin-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND');
|
||||
expect(raceEventRepository.update).not.toHaveBeenCalled();
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
raceEventRepository.findAwaitingStewardingClose.mockRejectedValue(new Error('DB error'));
|
||||
@@ -121,5 +112,5 @@ describe('CloseRaceEventStewardingUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toContain('DB error');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { RaceEventRepository } from '../../domain/repositories/RaceEventRepository';
|
||||
import type { RaceRegistrationRepository } from '../../domain/repositories/RaceRegistrationRepository';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { DomainEventPublisher } from '@core/shared/domain/DomainEvent';
|
||||
import { RaceEventStewardingClosedEvent } from '../../domain/events/RaceEventStewardingClosed';
|
||||
import { DomainEventPublisher } from '@/shared/domain/DomainEvent';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { RaceEvent } from '../../domain/entities/RaceEvent';
|
||||
import { RaceEventStewardingClosedEvent } from '../../domain/events/RaceEventStewardingClosed';
|
||||
|
||||
export type CloseRaceEventStewardingInput = {
|
||||
raceId: string;
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { RaceRegistrationRepository } from '../../domain/repositories/RaceRegistrationRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
|
||||
describe('CompleteRaceUseCase', () => {
|
||||
let useCase: CompleteRaceUseCase;
|
||||
let raceRepository: {
|
||||
@@ -21,7 +22,6 @@ describe('CompleteRaceUseCase', () => {
|
||||
save: Mock;
|
||||
};
|
||||
let getDriverRating: Mock;
|
||||
let output: { present: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
raceRepository = {
|
||||
@@ -39,11 +39,10 @@ describe('CompleteRaceUseCase', () => {
|
||||
save: vi.fn(),
|
||||
};
|
||||
getDriverRating = vi.fn();
|
||||
output = { present: vi.fn() };
|
||||
useCase = new CompleteRaceUseCase(raceRepository as unknown as IRaceRepository,
|
||||
raceRegistrationRepository as unknown as IRaceRegistrationRepository,
|
||||
resultRepository as unknown as IResultRepository,
|
||||
standingRepository as unknown as IStandingRepository,
|
||||
useCase = new CompleteRaceUseCase(raceRepository as any,
|
||||
raceRegistrationRepository as any,
|
||||
resultRepository as any,
|
||||
standingRepository as any,
|
||||
getDriverRating);
|
||||
});
|
||||
|
||||
@@ -73,7 +72,8 @@ describe('CompleteRaceUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
expect(presented.raceId).toBe('race-1');
|
||||
expect(raceRepository.findById).toHaveBeenCalledWith('race-1');
|
||||
expect(raceRegistrationRepository.getRegisteredDrivers).toHaveBeenCalledWith('race-1');
|
||||
expect(getDriverRating).toHaveBeenCalledTimes(2);
|
||||
@@ -81,7 +81,7 @@ describe('CompleteRaceUseCase', () => {
|
||||
expect(standingRepository.save).toHaveBeenCalledTimes(2);
|
||||
expect(mockRace.complete).toHaveBeenCalled();
|
||||
expect(raceRepository.update).toHaveBeenCalledWith({ id: 'race-1', status: 'completed' });
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when race does not exist', async () => {
|
||||
const command: CompleteRaceInput = {
|
||||
@@ -94,7 +94,7 @@ describe('CompleteRaceUseCase', () => {
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('RACE_NOT_FOUND');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when no registered drivers', async () => {
|
||||
const command: CompleteRaceInput = {
|
||||
@@ -114,7 +114,7 @@ describe('CompleteRaceUseCase', () => {
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('NO_REGISTERED_DRIVERS');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const command: CompleteRaceInput = {
|
||||
@@ -138,5 +138,5 @@ describe('CompleteRaceUseCase', () => {
|
||||
const error = result.unwrapErr();
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details?.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import type { Season } from '../../domain/entities/season/Season';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
|
||||
export type CreateLeagueSeasonScheduleRaceInput = {
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
track: string;
|
||||
car: string;
|
||||
scheduledAt: Date;
|
||||
};
|
||||
|
||||
export type CreateLeagueSeasonScheduleRaceResult = {
|
||||
raceId: string;
|
||||
@@ -96,9 +87,7 @@ export class CreateLeagueSeasonScheduleRaceUseCase {
|
||||
}
|
||||
}
|
||||
|
||||
private isWithinSeasonWindow(_season: Season, _scheduledAt: Date): boolean {
|
||||
// Implementation would check if scheduledAt is within season's schedule window
|
||||
// For now, return true as a placeholder
|
||||
return true;
|
||||
private isWithinSeasonWindow(season: Season, scheduledAt: Date): boolean {
|
||||
return scheduledAt >= season.startDate && scheduledAt <= season.endDate;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
CreateLeagueWithSeasonAndScoringUseCase,
|
||||
type CreateLeagueWithSeasonAndScoringCommand,
|
||||
type CreateLeagueWithSeasonAndScoringResult,
|
||||
CreateLeagueWithSeasonAndScoringUseCase,
|
||||
type CreateLeagueWithSeasonAndScoringCommand
|
||||
} from './CreateLeagueWithSeasonAndScoringUseCase';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { LeagueScoringConfigRepository } from '../../domain/repositories/LeagueScoringConfigRepository';
|
||||
|
||||
describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
let useCase: CreateLeagueWithSeasonAndScoringUseCase;
|
||||
@@ -26,7 +22,6 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
warn: Mock;
|
||||
error: Mock;
|
||||
};
|
||||
let output: { present: Mock } ;
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = {
|
||||
@@ -45,12 +40,11 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = { present: vi.fn() } as unknown as typeof output;
|
||||
useCase = new CreateLeagueWithSeasonAndScoringUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
seasonRepository as unknown as ISeasonRepository,
|
||||
leagueScoringConfigRepository as unknown as ILeagueScoringConfigRepository,
|
||||
useCase = new CreateLeagueWithSeasonAndScoringUseCase(leagueRepository as any,
|
||||
seasonRepository as any,
|
||||
leagueScoringConfigRepository as any,
|
||||
getLeagueScoringPresetById,
|
||||
logger as unknown as Logger);
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('should create league, season, and scoring successfully', async () => {
|
||||
@@ -82,11 +76,11 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = (expect(presented?.league.id.toString()).toBeDefined();
|
||||
expect(presented?.season.id).toBeDefined();
|
||||
expect(presented?.scoringConfig.seasonId.toString()).toBe(presented?.season.id);
|
||||
expect(presented.league.id).toBeDefined();
|
||||
expect(presented.season.id).toBeDefined();
|
||||
expect(presented.scoringConfig.seasonId.toString()).toBe(presented.season.id);
|
||||
expect(leagueRepository.create).toHaveBeenCalledTimes(1);
|
||||
expect(seasonRepository.create).toHaveBeenCalledTimes(1);
|
||||
expect(leagueScoringConfigRepository.save).toHaveBeenCalledTimes(1);
|
||||
@@ -113,7 +107,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('League name is required');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when ownerId is empty', async () => {
|
||||
const command = {
|
||||
@@ -136,7 +130,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('League ownerId is required');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when gameId is empty', async () => {
|
||||
const command = {
|
||||
@@ -159,7 +153,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('gameId is required');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when visibility is missing', async () => {
|
||||
const command: Partial<CreateLeagueWithSeasonAndScoringCommand> = {
|
||||
@@ -180,7 +174,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('visibility is required');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when maxDrivers is invalid', async () => {
|
||||
const command = {
|
||||
@@ -204,7 +198,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('maxDrivers must be greater than 0 when provided');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when ranked league has insufficient drivers', async () => {
|
||||
const command = {
|
||||
@@ -228,7 +222,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toContain('Ranked leagues require at least 10 drivers');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when scoring preset is unknown', async () => {
|
||||
const command = {
|
||||
@@ -254,7 +248,7 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('Unknown scoring preset: unknown-preset');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const command = {
|
||||
@@ -285,5 +279,5 @@ describe('CreateLeagueWithSeasonAndScoringUseCase', () => {
|
||||
if ('details' in err && err.details && typeof err.details === 'object' && 'message' in err.details) {
|
||||
expect(err.details.message).toBe('DB error');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { League } from '../../domain/entities/League';
|
||||
import { Season } from '../../domain/entities/season/Season';
|
||||
import { LeagueScoringConfig } from '../../domain/entities/LeagueScoringConfig';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { LeagueScoringConfigRepository } from '../../domain/repositories/LeagueScoringConfigRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ChampionshipConfig } from '../../domain/types/ChampionshipConfig';
|
||||
import type { SessionType } from '../../domain/types/SessionType';
|
||||
import type { BonusRule } from '../../domain/types/BonusRule';
|
||||
import { PointsTable } from '../../domain/value-objects/PointsTable';
|
||||
import {
|
||||
LeagueVisibility,
|
||||
MIN_RANKED_LEAGUE_DRIVERS,
|
||||
} from '../../domain/value-objects/LeagueVisibility';
|
||||
import { League } from '@/racing/domain/entities/League';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { LeagueScoringConfig } from '../../domain/entities/LeagueScoringConfig';
|
||||
import { Season } from '../../domain/entities/season/Season';
|
||||
import type { BonusRule } from '../../domain/types/BonusRule';
|
||||
import type { ChampionshipConfig } from '../../domain/types/ChampionshipConfig';
|
||||
import type { SessionType } from '../../domain/types/SessionType';
|
||||
import {
|
||||
LeagueVisibility,
|
||||
MIN_RANKED_LEAGUE_DRIVERS,
|
||||
} from '../../domain/value-objects/LeagueVisibility';
|
||||
import { PointsTable } from '../../domain/value-objects/PointsTable';
|
||||
|
||||
export type CreateLeagueWithSeasonAndScoringCommand = {
|
||||
name: string;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { describe, it, expect, vi, Mock } from 'vitest';
|
||||
|
||||
import { describe, it, expect, vi, Mock, beforeEach } from 'vitest';
|
||||
import { Season } from '@core/racing/domain/entities/season/Season';
|
||||
import type { SeasonRepository } from '@core/racing/domain/repositories/SeasonRepository';
|
||||
import type { LeagueRepository } from '@core/racing/domain/repositories/LeagueRepository';
|
||||
@@ -75,7 +74,7 @@ type CreateSeasonErrorCode = ApplicationErrorCode<'LEAGUE_NOT_FOUND' | 'VALIDATI
|
||||
|
||||
describe('CreateSeasonForLeagueUseCase', () => {
|
||||
const mockLeagueFindById = vi.fn();
|
||||
const mockLeagueRepo: ILeagueRepository = {
|
||||
const mockLeagueRepo: any = {
|
||||
findById: mockLeagueFindById,
|
||||
findAll: vi.fn(),
|
||||
findByOwnerId: vi.fn(),
|
||||
@@ -88,7 +87,7 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
|
||||
const mockSeasonFindById = vi.fn();
|
||||
const mockSeasonAdd = vi.fn();
|
||||
const mockSeasonRepo: ISeasonRepository = {
|
||||
const mockSeasonRepo: any = {
|
||||
findById: mockSeasonFindById,
|
||||
findByLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
@@ -98,11 +97,8 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
listActiveByLeague: vi.fn(),
|
||||
};
|
||||
|
||||
let output: { present: Mock } ;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
output = { present: vi.fn() } as unknown as typeof output;
|
||||
});
|
||||
|
||||
it('creates a planned Season for an existing league with config-derived props', async () => {
|
||||
@@ -125,8 +121,6 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
strategy: 'dropWorstN',
|
||||
n: 2,
|
||||
},
|
||||
// Intentionally omit seasonStartDate / raceStartTime to avoid schedule derivation,
|
||||
// focusing this test on scoring/drop/stewarding/maxDrivers mapping.
|
||||
timings: {
|
||||
qualifyingMinutes: 10,
|
||||
mainRaceMinutes: 30,
|
||||
@@ -141,13 +135,13 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
config,
|
||||
};
|
||||
|
||||
const result: Result<void, CreateSeasonErrorCode> = await useCase.execute(command);
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = (expect(presented?.season).toBeInstanceOf(Season);
|
||||
expect(presented?.league.id).toBe('league-1');
|
||||
expect(presented.season).toBeInstanceOf(Season);
|
||||
expect(presented.league.id).toBe('league-1');
|
||||
});
|
||||
|
||||
it('clones configuration from a source season when sourceSeasonId is provided', async () => {
|
||||
@@ -172,15 +166,15 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
sourceSeasonId: 'source-season',
|
||||
};
|
||||
|
||||
const result: Result<void, CreateSeasonErrorCode> = await useCase.execute(command);
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = (expect(presented?.season.maxDrivers).toBe(40);
|
||||
expect(presented.season.maxDrivers).toBe(40);
|
||||
});
|
||||
|
||||
it('returns error when league not found and does not call output', async () => {
|
||||
it('returns error when league not found', async () => {
|
||||
mockLeagueFindById.mockResolvedValue(null);
|
||||
|
||||
const useCase = new CreateSeasonForLeagueUseCase(mockLeagueRepo, mockSeasonRepo);
|
||||
@@ -191,15 +185,15 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
gameId: 'iracing',
|
||||
};
|
||||
|
||||
const result: Result<void, CreateSeasonErrorCode> = await useCase.execute(command);
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
const error = result.unwrapErr();
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details?.message).toBe('League not found: missing-league');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns validation error when source season is missing and does not call output', async () => {
|
||||
it('returns validation error when source season is missing', async () => {
|
||||
mockLeagueFindById.mockResolvedValue({ id: 'league-1' });
|
||||
mockSeasonFindById.mockResolvedValue(undefined);
|
||||
|
||||
@@ -212,11 +206,11 @@ describe('CreateSeasonForLeagueUseCase', () => {
|
||||
sourceSeasonId: 'missing-source',
|
||||
};
|
||||
|
||||
const result: Result<void, CreateSeasonErrorCode> = await useCase.execute(command);
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
const error = result.unwrapErr();
|
||||
expect(error.code).toBe('VALIDATION_ERROR');
|
||||
expect(error.details?.message).toBe('Source Season not found: missing-source');
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { CreateSponsorUseCase, type CreateSponsorInput } from './CreateSponsorUseCase';
|
||||
import type { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
describe('CreateSponsorUseCase', () => {
|
||||
let useCase: CreateSponsorUseCase;
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
*
|
||||
* Creates a new sponsor.
|
||||
*/
|
||||
import { ApplicationErrorCode } from '@/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Sponsor } from '../../domain/entities/sponsor/Sponsor';
|
||||
import type { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
export interface CreateSponsorInput {
|
||||
name: string;
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
CreateTeamUseCase,
|
||||
type CreateTeamInput,
|
||||
type CreateTeamResult,
|
||||
CreateTeamUseCase,
|
||||
type CreateTeamInput
|
||||
} from './CreateTeamUseCase';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
describe('CreateTeamUseCase', () => {
|
||||
let useCase: CreateTeamUseCase;
|
||||
let teamRepository: {
|
||||
@@ -22,7 +19,6 @@ describe('CreateTeamUseCase', () => {
|
||||
warn: Mock;
|
||||
error: Mock;
|
||||
};
|
||||
let output: { present: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
teamRepository = {
|
||||
@@ -38,10 +34,9 @@ describe('CreateTeamUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = { present: vi.fn() };
|
||||
useCase = new CreateTeamUseCase(teamRepository as unknown as ITeamRepository,
|
||||
membershipRepository as unknown as ITeamMembershipRepository,
|
||||
logger as unknown as Logger);
|
||||
useCase = new CreateTeamUseCase(teamRepository as any,
|
||||
membershipRepository as any,
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('should create team successfully', async () => {
|
||||
@@ -69,10 +64,11 @@ describe('CreateTeamUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
expect(presented.team.id).toBe('team-uuid');
|
||||
expect(teamRepository.create).toHaveBeenCalledTimes(1);
|
||||
expect(membershipRepository.saveMembership).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when driver already belongs to a team', async () => {
|
||||
const command: CreateTeamInput = {
|
||||
@@ -100,7 +96,7 @@ describe('CreateTeamUseCase', () => {
|
||||
);
|
||||
expect(teamRepository.create).not.toHaveBeenCalled();
|
||||
expect(membershipRepository.saveMembership).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const command: CreateTeamInput = {
|
||||
@@ -119,5 +115,5 @@ describe('CreateTeamUseCase', () => {
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('REPOSITORY_ERROR');
|
||||
expect(result.unwrapErr().details?.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,18 +3,16 @@
|
||||
*
|
||||
* Creates a new team.
|
||||
*/
|
||||
import { Result } from '@/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import type {
|
||||
TeamMembership,
|
||||
TeamMembershipStatus,
|
||||
TeamRole,
|
||||
TeamMembership,
|
||||
TeamMembershipStatus,
|
||||
TeamRole,
|
||||
} from '../../domain/types/TeamMembership';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
export interface CreateTeamInput {
|
||||
name: string;
|
||||
tag: string;
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
|
||||
export type DeleteLeagueSeasonScheduleRaceInput = {
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
raceId: string;
|
||||
};
|
||||
|
||||
export type DeleteLeagueSeasonScheduleRaceResult = {
|
||||
success: true;
|
||||
|
||||
@@ -15,6 +15,7 @@ describe('FileProtestUseCase', () => {
|
||||
let mockLeagueMembershipRepo: {
|
||||
getLeagueMembers: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockProtestRepo = {
|
||||
create: vi.fn(),
|
||||
@@ -25,12 +26,12 @@ describe('FileProtestUseCase', () => {
|
||||
mockLeagueMembershipRepo = {
|
||||
getLeagueMembers: vi.fn(),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when race does not exist', async () => {
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository);
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue(null);
|
||||
|
||||
@@ -45,12 +46,12 @@ describe('FileProtestUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<FileProtestErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('RACE_NOT_FOUND');
|
||||
expect(err.details?.message).toBe('Race not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when protesting against self', async () => {
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository);
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
|
||||
@@ -65,12 +66,12 @@ describe('FileProtestUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<FileProtestErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('SELF_PROTEST');
|
||||
expect(err.details?.message).toBe('Cannot file a protest against yourself');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when protesting driver is not an active member', async () => {
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository);
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
mockLeagueMembershipRepo.getLeagueMembers.mockResolvedValue([
|
||||
@@ -88,12 +89,12 @@ describe('FileProtestUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<FileProtestErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('NOT_MEMBER');
|
||||
expect(err.details?.message).toBe('Protesting driver is not an active member of this league');
|
||||
});
|
||||
});
|
||||
|
||||
it('should create protest and return protestId on success', async () => {
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as unknown as IProtestRepository,
|
||||
mockRaceRepo as unknown as IRaceRepository,
|
||||
mockLeagueMembershipRepo as unknown as ILeagueMembershipRepository);
|
||||
const useCase = new FileProtestUseCase(mockProtestRepo as any,
|
||||
mockRaceRepo as any,
|
||||
mockLeagueMembershipRepo as any);
|
||||
|
||||
mockRaceRepo.findById.mockResolvedValue({ id: 'race1', leagueId: 'league1' });
|
||||
mockLeagueMembershipRepo.getLeagueMembers.mockResolvedValue([
|
||||
@@ -111,21 +112,9 @@ describe('FileProtestUseCase', () => {
|
||||
} as FileProtestInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
expect(mockProtestRepo.create).toHaveBeenCalledTimes(1);
|
||||
const created = (mockProtestRepo.create as unknown as Mock).mock.calls[0]?.[0] as unknown as {
|
||||
raceId: { toString(): string };
|
||||
protestingDriverId: { toString(): string };
|
||||
accusedDriverId: { toString(): string };
|
||||
comment?: string;
|
||||
proofVideoUrl: { toString(): string };
|
||||
status: { toString(): string };
|
||||
incident: {
|
||||
lap: { toNumber(): number };
|
||||
description: { toString(): string };
|
||||
timeInRace?: unknown;
|
||||
};
|
||||
};
|
||||
const created = (mockProtestRepo.create as unknown as Mock).mock.calls[0]?.[0] as any;
|
||||
|
||||
expect(created.raceId.toString()).toBe('race1');
|
||||
expect(created.protestingDriverId.toString()).toBe('driver1');
|
||||
@@ -136,16 +125,14 @@ describe('FileProtestUseCase', () => {
|
||||
|
||||
expect(created.incident.lap.toNumber()).toBe(5);
|
||||
expect(created.incident.description.toString()).toBe('Collision');
|
||||
expect(created.incident.timeInRace).toBeUndefined();
|
||||
|
||||
const presented = (expect(presented.protest.raceId.toString()).toBe('race1');
|
||||
expect(presented.protest.raceId.toString()).toBe('race1');
|
||||
expect(presented.protest.protestingDriverId.toString()).toBe('driver1');
|
||||
expect(presented.protest.accusedDriverId.toString()).toBe('driver2');
|
||||
expect(presented.protest.incident.lap.toNumber()).toBe(5);
|
||||
expect(presented.protest.incident.description.toString()).toBe('Collision');
|
||||
expect(presented.protest.incident.timeInRace).toBeUndefined();
|
||||
expect(presented.protest.comment).toBe('Test comment');
|
||||
expect(presented.protest.proofVideoUrl).toBeDefined();
|
||||
expect(presented.protest.proofVideoUrl!.toString()).toBe('http://example.com/video');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,23 +16,23 @@ describe('GetAllLeaguesWithCapacityAndScoringUseCase', () => {
|
||||
let mockSeasonRepo: { findByLeagueId: Mock };
|
||||
let mockScoringConfigRepo: { findBySeasonId: Mock };
|
||||
let mockGameRepo: { findById: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
mockLeagueRepo = { findAll: vi.fn() };
|
||||
mockMembershipRepo = { getLeagueMembers: vi.fn() };
|
||||
mockSeasonRepo = { findByLeagueId: vi.fn() };
|
||||
mockScoringConfigRepo = { findBySeasonId: vi.fn() };
|
||||
mockGameRepo = { findById: vi.fn() };
|
||||
output = { present: vi.fn() } as unknown as typeof output;
|
||||
});
|
||||
|
||||
it('should return enriched leagues with capacity and scoring', async () => {
|
||||
const useCase = new GetAllLeaguesWithCapacityAndScoringUseCase(mockLeagueRepo as unknown as ILeagueRepository,
|
||||
mockMembershipRepo as unknown as ILeagueMembershipRepository,
|
||||
mockSeasonRepo as unknown as ISeasonRepository,
|
||||
mockScoringConfigRepo as unknown as ILeagueScoringConfigRepository,
|
||||
mockGameRepo as unknown as IGameRepository,
|
||||
{ getPresetById: vi.fn().mockReturnValue({ id: 'preset1', name: 'Default' }) },
|
||||
output,
|
||||
const useCase = new GetAllLeaguesWithCapacityAndScoringUseCase(
|
||||
mockLeagueRepo as any,
|
||||
mockMembershipRepo as any,
|
||||
mockSeasonRepo as any,
|
||||
mockScoringConfigRepo as any,
|
||||
mockGameRepo as any,
|
||||
{ getPresetById: vi.fn().mockReturnValue({ id: 'preset1', name: 'Default' }) }
|
||||
);
|
||||
|
||||
const league = { id: 'league1', name: 'Test League', settings: { maxDrivers: 30 } };
|
||||
@@ -53,19 +53,18 @@ describe('GetAllLeaguesWithCapacityAndScoringUseCase', () => {
|
||||
const result = await useCase.execute({} as GetAllLeaguesWithCapacityAndScoringInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented =
|
||||
expect(presented?.leagues).toHaveLength(1);
|
||||
expect(presented.leagues).toHaveLength(1);
|
||||
|
||||
const [summary] = presented?.leagues ?? [];
|
||||
const summary = presented.leagues[0];
|
||||
|
||||
expect(summary?.league).toEqual(league);
|
||||
expect(summary?.currentDrivers).toBe(2);
|
||||
expect(summary?.maxDrivers).toBe(30);
|
||||
expect(summary?.season).toEqual(season);
|
||||
expect(summary?.scoringConfig).toEqual(scoringConfig);
|
||||
expect(summary?.game).toEqual(game);
|
||||
expect(summary?.preset).toEqual({ id: 'preset1', name: 'Default' });
|
||||
expect(summary.league).toEqual(league);
|
||||
expect(summary.currentDrivers).toBe(2);
|
||||
expect(summary.maxDrivers).toBe(30);
|
||||
expect(summary.season).toEqual(season);
|
||||
expect(summary.scoringConfig).toEqual(scoringConfig);
|
||||
expect(summary.game).toEqual(game);
|
||||
expect(summary.preset).toEqual({ id: 'preset1', name: 'Default' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import {
|
||||
GetAllRacesPageDataUseCase,
|
||||
type GetAllRacesPageDataResult,
|
||||
type GetAllRacesPageDataInput,
|
||||
} from './GetAllRacesPageDataUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { League } from '../../domain/entities/League';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import {
|
||||
GetAllRacesPageDataUseCase,
|
||||
type GetAllRacesPageDataInput
|
||||
} from './GetAllRacesPageDataUseCase';
|
||||
|
||||
describe('GetAllRacesPageDataUseCase', () => {
|
||||
const mockRaceFindAll = vi.fn();
|
||||
const mockRaceRepo: IRaceRepository = {
|
||||
const mockRaceRepo: any = {
|
||||
findById: vi.fn(),
|
||||
findAll: mockRaceFindAll,
|
||||
findByLeagueId: vi.fn(),
|
||||
@@ -27,7 +24,7 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
};
|
||||
|
||||
const mockLeagueFindAll = vi.fn();
|
||||
const mockLeagueRepo: ILeagueRepository = {
|
||||
const mockLeagueRepo: any = {
|
||||
findById: vi.fn(),
|
||||
findAll: mockLeagueFindAll,
|
||||
findByOwnerId: vi.fn(),
|
||||
@@ -47,9 +44,9 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
it('should present races and filters data', async () => {
|
||||
it('should return races and filters data', async () => {
|
||||
const useCase = new GetAllRacesPageDataUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
@@ -95,8 +92,8 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.races).toEqual([
|
||||
const presented = result.unwrap();
|
||||
expect(presented.races).toEqual([
|
||||
{
|
||||
id: 'race2',
|
||||
track: 'Track B',
|
||||
@@ -134,7 +131,7 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should present empty result when no races or leagues', async () => {
|
||||
it('should return empty result when no races or leagues', async () => {
|
||||
const useCase = new GetAllRacesPageDataUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
@@ -145,8 +142,8 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
const result = await useCase.execute({});
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.races).toEqual([]);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.races).toEqual([]);
|
||||
expect(presented.filters).toEqual({
|
||||
statuses: [
|
||||
{ value: 'all', label: 'All Statuses' },
|
||||
@@ -159,7 +156,7 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws and not present data', async () => {
|
||||
it('should return error when repository throws', async () => {
|
||||
const useCase = new GetAllRacesPageDataUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
@@ -173,5 +170,5 @@ describe('GetAllRacesPageDataUseCase', () => {
|
||||
const err = result.unwrapErr();
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { RaceStatusValue } from '../../domain/entities/Race';
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import {
|
||||
GetAllRacesUseCase,
|
||||
type GetAllRacesResult,
|
||||
type GetAllRacesInput,
|
||||
} from './GetAllRacesUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { League } from '../../domain/entities/League';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import {
|
||||
GetAllRacesUseCase,
|
||||
type GetAllRacesInput
|
||||
} from './GetAllRacesUseCase';
|
||||
|
||||
describe('GetAllRacesUseCase', () => {
|
||||
const mockRaceFindAll = vi.fn();
|
||||
const mockRaceRepo: IRaceRepository = {
|
||||
const mockRaceRepo: RaceRepository = {
|
||||
findById: vi.fn(),
|
||||
findAll: mockRaceFindAll,
|
||||
findByLeagueId: vi.fn(),
|
||||
@@ -27,7 +26,7 @@ describe('GetAllRacesUseCase', () => {
|
||||
};
|
||||
|
||||
const mockLeagueFindAll = vi.fn();
|
||||
const mockLeagueRepo: ILeagueRepository = {
|
||||
const mockLeagueRepo: LeagueRepository = {
|
||||
findById: vi.fn(),
|
||||
findAll: mockLeagueFindAll,
|
||||
findByOwnerId: vi.fn(),
|
||||
@@ -47,13 +46,12 @@ describe('GetAllRacesUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
it('should present domain races and leagues data', async () => {
|
||||
it('should return domain races and leagues data', async () => {
|
||||
const useCase = new GetAllRacesUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
useCase.setOutput(output);
|
||||
|
||||
const race1 = Race.create({
|
||||
id: 'race1',
|
||||
@@ -95,17 +93,16 @@ describe('GetAllRacesUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.totalCount).toBe(2);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.totalCount).toBe(2);
|
||||
expect(presented.races).toEqual([race1, race2]);
|
||||
expect(presented.leagues).toEqual([league1, league2]);
|
||||
});
|
||||
|
||||
it('should present empty result when no races or leagues', async () => {
|
||||
it('should return empty result when no races or leagues', async () => {
|
||||
const useCase = new GetAllRacesUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
useCase.setOutput(output);
|
||||
|
||||
mockRaceFindAll.mockResolvedValue([]);
|
||||
mockLeagueFindAll.mockResolvedValue([]);
|
||||
@@ -113,13 +110,13 @@ describe('GetAllRacesUseCase', () => {
|
||||
const result = await useCase.execute({});
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.totalCount).toBe(0);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.totalCount).toBe(0);
|
||||
expect(presented.races).toEqual([]);
|
||||
expect(presented.leagues).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return error when repository throws and not present data', async () => {
|
||||
it('should return error when repository throws', async () => {
|
||||
const useCase = new GetAllRacesUseCase(mockRaceRepo,
|
||||
mockLeagueRepo,
|
||||
mockLogger);
|
||||
@@ -133,5 +130,5 @@ describe('GetAllRacesUseCase', () => {
|
||||
const err = result.unwrapErr();
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
import type { League } from '../../domain/entities/League';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
|
||||
export type GetAllRacesInput = {};
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import { GetAllTeamsUseCase, type GetAllTeamsInput, type GetAllTeamsResult } from './GetAllTeamsUseCase';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamStatsRepository } from '../../domain/repositories/TeamStatsRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { GetAllTeamsUseCase, type GetAllTeamsInput } from './GetAllTeamsUseCase';
|
||||
|
||||
describe('GetAllTeamsUseCase', () => {
|
||||
const mockTeamFindAll = vi.fn();
|
||||
const mockTeamRepo: ITeamRepository = {
|
||||
const mockTeamRepo: TeamRepository = {
|
||||
findById: vi.fn(),
|
||||
findAll: mockTeamFindAll,
|
||||
findByLeagueId: vi.fn(),
|
||||
@@ -18,7 +18,7 @@ describe('GetAllTeamsUseCase', () => {
|
||||
};
|
||||
|
||||
const mockTeamMembershipCountByTeamId = vi.fn();
|
||||
const mockTeamMembershipRepo: ITeamMembershipRepository = {
|
||||
const mockTeamMembershipRepo: TeamMembershipRepository = {
|
||||
getMembership: vi.fn(),
|
||||
getActiveMembershipForDriver: vi.fn(),
|
||||
getTeamMembers: vi.fn(),
|
||||
@@ -30,28 +30,13 @@ describe('GetAllTeamsUseCase', () => {
|
||||
removeJoinRequest: vi.fn(),
|
||||
};
|
||||
|
||||
const mockTeamStatsRepo: ITeamStatsRepository = {
|
||||
const mockTeamStatsRepo: TeamStatsRepository = {
|
||||
getTeamStats: vi.fn(),
|
||||
saveTeamStats: vi.fn(),
|
||||
getAllStats: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
};
|
||||
|
||||
const mockResultRepo: IResultRepository = {
|
||||
findAll: vi.fn(),
|
||||
findById: vi.fn(),
|
||||
findByRaceId: vi.fn(),
|
||||
findByDriverId: vi.fn(),
|
||||
findByDriverIdAndLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
createMany: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
deleteByRaceId: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
existsByRaceId: vi.fn(),
|
||||
};
|
||||
|
||||
const mockLogger: Logger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
@@ -61,20 +46,19 @@ describe('GetAllTeamsUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return teams data', async () => {
|
||||
const useCase = new GetAllTeamsUseCase(mockTeamRepo,
|
||||
mockTeamMembershipRepo,
|
||||
mockTeamStatsRepo,
|
||||
mockResultRepo,
|
||||
mockLogger);
|
||||
|
||||
const team1 = {
|
||||
id: 'team1',
|
||||
name: { props: 'Team One' },
|
||||
tag: { props: 'TO' },
|
||||
description: { props: 'Description One' },
|
||||
id: { toString: () => 'team1' },
|
||||
name: { toString: () => 'Team One' },
|
||||
tag: { toString: () => 'TO' },
|
||||
description: { toString: () => 'Description One' },
|
||||
ownerId: { toString: () => 'owner1' },
|
||||
leagues: [{ toString: () => 'league1' }],
|
||||
createdAt: { toDate: () => new Date('2023-01-01T00:00:00Z') },
|
||||
@@ -83,10 +67,10 @@ describe('GetAllTeamsUseCase', () => {
|
||||
isRecruiting: false,
|
||||
};
|
||||
const team2 = {
|
||||
id: 'team2',
|
||||
name: { props: 'Team Two' },
|
||||
tag: { props: 'TT' },
|
||||
description: { props: 'Description Two' },
|
||||
id: { toString: () => 'team2' },
|
||||
name: { toString: () => 'Team Two' },
|
||||
tag: { toString: () => 'TT' },
|
||||
description: { toString: () => 'Description Two' },
|
||||
ownerId: { toString: () => 'owner2' },
|
||||
leagues: [{ toString: () => 'league2' }],
|
||||
createdAt: { toDate: () => new Date('2023-01-02T00:00:00Z') },
|
||||
@@ -98,7 +82,6 @@ describe('GetAllTeamsUseCase', () => {
|
||||
mockTeamFindAll.mockResolvedValue([team1, team2]);
|
||||
mockTeamMembershipCountByTeamId.mockImplementation((id: string) => Promise.resolve(id === 'team1' ? 5 : 3));
|
||||
|
||||
// Provide precomputed stats so the use case doesn't compute from results.
|
||||
(mockTeamStatsRepo.getTeamStats as unknown as Mock).mockImplementation((teamId: string) =>
|
||||
Promise.resolve(
|
||||
teamId === 'team1'
|
||||
@@ -126,62 +109,21 @@ describe('GetAllTeamsUseCase', () => {
|
||||
const result = await useCase.execute({} as GetAllTeamsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented).toEqual({
|
||||
teams: [
|
||||
{
|
||||
id: 'team1',
|
||||
name: 'Team One',
|
||||
tag: 'TO',
|
||||
description: 'Description One',
|
||||
ownerId: 'owner1',
|
||||
leagues: ['league1'],
|
||||
createdAt: new Date('2023-01-01T00:00:00Z'),
|
||||
memberCount: 5,
|
||||
totalWins: 2,
|
||||
totalRaces: 10,
|
||||
performanceLevel: 'intermediate',
|
||||
specialization: 'mixed',
|
||||
region: 'EU',
|
||||
languages: ['en'],
|
||||
logoRef: team1.logoRef,
|
||||
logoUrl: null,
|
||||
rating: 1200,
|
||||
category: undefined,
|
||||
isRecruiting: false,
|
||||
},
|
||||
{
|
||||
id: 'team2',
|
||||
name: 'Team Two',
|
||||
tag: 'TT',
|
||||
description: 'Description Two',
|
||||
ownerId: 'owner2',
|
||||
leagues: ['league2'],
|
||||
createdAt: new Date('2023-01-02T00:00:00Z'),
|
||||
memberCount: 3,
|
||||
totalWins: 5,
|
||||
totalRaces: 20,
|
||||
performanceLevel: 'advanced',
|
||||
specialization: 'mixed',
|
||||
region: 'US',
|
||||
languages: ['en', 'de'],
|
||||
logoRef: team2.logoRef,
|
||||
logoUrl: null,
|
||||
rating: 1400,
|
||||
category: undefined,
|
||||
isRecruiting: true,
|
||||
},
|
||||
],
|
||||
totalCount: 2,
|
||||
});
|
||||
expect(presented.totalCount).toBe(2);
|
||||
expect(presented.teams[0].team).toBe(team1);
|
||||
expect(presented.teams[0].memberCount).toBe(5);
|
||||
expect(presented.teams[0].rating).toBe(1200);
|
||||
expect(presented.teams[1].team).toBe(team2);
|
||||
expect(presented.teams[1].memberCount).toBe(3);
|
||||
expect(presented.teams[1].rating).toBe(1400);
|
||||
});
|
||||
|
||||
it('should return empty result when no teams', async () => {
|
||||
const useCase = new GetAllTeamsUseCase(mockTeamRepo,
|
||||
mockTeamMembershipRepo,
|
||||
mockTeamStatsRepo,
|
||||
mockResultRepo,
|
||||
mockLogger);
|
||||
|
||||
mockTeamFindAll.mockResolvedValue([]);
|
||||
@@ -189,19 +131,16 @@ describe('GetAllTeamsUseCase', () => {
|
||||
const result = await useCase.execute({} as GetAllTeamsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented).toEqual({
|
||||
teams: [],
|
||||
totalCount: 0,
|
||||
});
|
||||
expect(presented.teams).toEqual([]);
|
||||
expect(presented.totalCount).toBe(0);
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const useCase = new GetAllTeamsUseCase(mockTeamRepo,
|
||||
mockTeamMembershipRepo,
|
||||
mockTeamStatsRepo,
|
||||
mockResultRepo,
|
||||
mockLogger);
|
||||
|
||||
const error = new Error('Repository error');
|
||||
@@ -214,6 +153,5 @@ describe('GetAllTeamsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { Team } from '@/racing/domain/entities/Team';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamStatsRepository } from '../../domain/repositories/TeamStatsRepository';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
|
||||
export interface GetAllTeamsInput {}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { GetDriverLiveriesUseCase, type GetDriverLiveriesInput } from './GetDriverLiveriesUseCase';
|
||||
import type { LiveryRepository } from '../../domain/repositories/LiveryRepository';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import type { DriverLivery } from '../../domain/entities/DriverLivery';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { GetDriverLiveriesUseCase, type GetDriverLiveriesInput } from './GetDriverLiveriesUseCase';
|
||||
|
||||
describe('GetDriverLiveriesUseCase', () => {
|
||||
const mockLiveryRepository: ILiveryRepository = {
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
* Retrieves all liveries for a specific driver.
|
||||
*/
|
||||
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { DriverLivery } from '@/racing/domain/entities/DriverLivery';
|
||||
import { UseCase } from '@core/shared/application/UseCase';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { LiveryRepository } from '../../domain/repositories/LiveryRepository';
|
||||
import type { DriverLivery } from '../../domain/entities/DriverLivery';
|
||||
|
||||
export interface GetDriverLiveriesInput {
|
||||
driverId: string;
|
||||
|
||||
@@ -1,43 +1,42 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import { GetDriverTeamUseCase, type GetDriverTeamInput, type GetDriverTeamResult } from './GetDriverTeamUseCase';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { GetDriverTeamUseCase, type GetDriverTeamInput } from './GetDriverTeamUseCase';
|
||||
|
||||
describe('GetDriverTeamUseCase', () => {
|
||||
const mockFindById = vi.fn();
|
||||
const mockGetActiveMembershipForDriver = vi.fn();
|
||||
const mockTeamRepo: ITeamRepository = {
|
||||
findById: mockFindById,
|
||||
findAll: vi.fn(),
|
||||
findByLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
};
|
||||
|
||||
const mockMembershipRepo: ITeamMembershipRepository = {
|
||||
getActiveMembershipForDriver: mockGetActiveMembershipForDriver,
|
||||
getMembership: vi.fn(),
|
||||
getTeamMembers: vi.fn(),
|
||||
saveMembership: vi.fn(),
|
||||
removeMembership: vi.fn(),
|
||||
getJoinRequests: vi.fn(),
|
||||
countByTeamId: vi.fn(),
|
||||
saveJoinRequest: vi.fn(),
|
||||
removeJoinRequest: vi.fn(),
|
||||
};
|
||||
|
||||
const mockLogger: Logger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
let mockTeamRepo: any;
|
||||
let mockMembershipRepo: any;
|
||||
let mockLogger: Logger;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
mockTeamRepo = {
|
||||
findById: vi.fn(),
|
||||
findAll: vi.fn(),
|
||||
findByLeagueId: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
};
|
||||
|
||||
mockMembershipRepo = {
|
||||
getActiveMembershipForDriver: vi.fn(),
|
||||
getMembership: vi.fn(),
|
||||
getTeamMembers: vi.fn(),
|
||||
saveMembership: vi.fn(),
|
||||
removeMembership: vi.fn(),
|
||||
getJoinRequests: vi.fn(),
|
||||
countByTeamId: vi.fn(),
|
||||
saveJoinRequest: vi.fn(),
|
||||
removeJoinRequest: vi.fn(),
|
||||
};
|
||||
|
||||
mockLogger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
it('should return driver team data when membership and team exist', async () => {
|
||||
const useCase = new GetDriverTeamUseCase(mockTeamRepo,
|
||||
@@ -48,15 +47,15 @@ describe('GetDriverTeamUseCase', () => {
|
||||
const membership = { id: 'membership1', driverId, teamId: 'team1' };
|
||||
const team = { id: 'team1', name: 'Team One' };
|
||||
|
||||
mockGetActiveMembershipForDriver.mockResolvedValue(membership);
|
||||
mockFindById.mockResolvedValue(team);
|
||||
mockMembershipRepo.getActiveMembershipForDriver.mockResolvedValue(membership);
|
||||
mockTeamRepo.findById.mockResolvedValue(team);
|
||||
|
||||
const input: GetDriverTeamInput = { driverId };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = (expect(presented.driverId).toBe(driverId);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.driverId).toBe(driverId);
|
||||
expect(presented.team).toBe(team);
|
||||
expect(presented.membership).toBe(membership);
|
||||
});
|
||||
@@ -68,7 +67,7 @@ describe('GetDriverTeamUseCase', () => {
|
||||
|
||||
const driverId = 'driver1';
|
||||
|
||||
mockGetActiveMembershipForDriver.mockResolvedValue(null);
|
||||
mockMembershipRepo.getActiveMembershipForDriver.mockResolvedValue(null);
|
||||
|
||||
const input: GetDriverTeamInput = { driverId };
|
||||
const result = await useCase.execute(input);
|
||||
@@ -76,7 +75,7 @@ describe('GetDriverTeamUseCase', () => {
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('MEMBERSHIP_NOT_FOUND');
|
||||
expect(result.unwrapErr().details.message).toBe('No active membership found for driver driver1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when team not found', async () => {
|
||||
const useCase = new GetDriverTeamUseCase(mockTeamRepo,
|
||||
@@ -86,8 +85,8 @@ describe('GetDriverTeamUseCase', () => {
|
||||
const driverId = 'driver1';
|
||||
const membership = { id: 'membership1', driverId, teamId: 'team1' };
|
||||
|
||||
mockGetActiveMembershipForDriver.mockResolvedValue(membership);
|
||||
mockFindById.mockResolvedValue(null);
|
||||
mockMembershipRepo.getActiveMembershipForDriver.mockResolvedValue(membership);
|
||||
mockTeamRepo.findById.mockResolvedValue(null);
|
||||
|
||||
const input: GetDriverTeamInput = { driverId };
|
||||
const result = await useCase.execute(input);
|
||||
@@ -95,7 +94,7 @@ describe('GetDriverTeamUseCase', () => {
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('TEAM_NOT_FOUND');
|
||||
expect(result.unwrapErr().details.message).toBe('Team not found for teamId team1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const useCase = new GetDriverTeamUseCase(mockTeamRepo,
|
||||
@@ -105,7 +104,7 @@ describe('GetDriverTeamUseCase', () => {
|
||||
const driverId = 'driver1';
|
||||
const error = new Error('Repository error');
|
||||
|
||||
mockGetActiveMembershipForDriver.mockRejectedValue(error);
|
||||
mockMembershipRepo.getActiveMembershipForDriver.mockRejectedValue(error);
|
||||
|
||||
const input: GetDriverTeamInput = { driverId };
|
||||
const result = await useCase.execute(input);
|
||||
@@ -113,5 +112,5 @@ describe('GetDriverTeamUseCase', () => {
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr().code).toBe('REPOSITORY_ERROR');
|
||||
expect(result.unwrapErr().details.message).toBe('Repository error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { TeamMembership } from '@/racing/domain/types/TeamMembership';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
|
||||
export interface GetDriverTeamInput {
|
||||
driverId: string;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
GetDriversLeaderboardUseCase,
|
||||
type GetDriversLeaderboardInput,
|
||||
type GetDriversLeaderboardResult
|
||||
GetDriversLeaderboardUseCase,
|
||||
type GetDriversLeaderboardInput
|
||||
} from './GetDriversLeaderboardUseCase';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { RankingUseCase } from './RankingUseCase';
|
||||
import type { DriverStatsUseCase } from './DriverStatsUseCase';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
describe('GetDriversLeaderboardUseCase', () => {
|
||||
const mockDriverFindAll = vi.fn();
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
GetEntitySponsorshipPricingUseCase,
|
||||
type GetEntitySponsorshipPricingInput,
|
||||
type GetEntitySponsorshipPricingResult,
|
||||
} from './GetEntitySponsorshipPricingUseCase';
|
||||
import type { SponsorshipPricingRepository } from '../../domain/repositories/SponsorshipPricingRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
GetEntitySponsorshipPricingUseCase,
|
||||
type GetEntitySponsorshipPricingInput
|
||||
} from './GetEntitySponsorshipPricingUseCase';
|
||||
|
||||
describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
let mockSponsorshipPricingRepo: ISponsorshipPricingRepository;
|
||||
let mockSponsorshipPricingRepo: any;
|
||||
let mockLogger: Logger;
|
||||
let mockFindByEntity: Mock;
|
||||
let mockFindPendingByEntity: Mock;
|
||||
let mockFindBySeasonId: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockFindByEntity = vi.fn();
|
||||
mockFindPendingByEntity = vi.fn();
|
||||
mockFindBySeasonId = vi.fn();
|
||||
mockSponsorshipPricingRepo = {
|
||||
findByEntity: mockFindByEntity,
|
||||
findAll: vi.fn(),
|
||||
@@ -29,18 +22,17 @@ describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
save: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
findAcceptingApplications: vi.fn(),
|
||||
} as ISponsorshipPricingRepository;
|
||||
};
|
||||
mockLogger = {
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = { present: vi.fn() } as unknown as typeof output;
|
||||
});
|
||||
|
||||
it('should return PRICING_NOT_CONFIGURED when no pricing found', async () => {
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as unknown as ISponsorshipPricingRepository,
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as any,
|
||||
mockLogger);
|
||||
|
||||
const dto: GetEntitySponsorshipPricingInput = {
|
||||
@@ -59,10 +51,10 @@ describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('PRICING_NOT_CONFIGURED');
|
||||
expect(err.details.message).toContain('No sponsorship pricing configured');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return pricing data when found', async () => {
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as unknown as ISponsorshipPricingRepository,
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as any,
|
||||
mockLogger);
|
||||
|
||||
const dto: GetEntitySponsorshipPricingInput = {
|
||||
@@ -88,14 +80,12 @@ describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
};
|
||||
|
||||
mockFindByEntity.mockResolvedValue(pricing);
|
||||
mockFindPendingByEntity.mockResolvedValue([]);
|
||||
mockFindBySeasonId.mockResolvedValue([]);
|
||||
|
||||
const result = await useCase.execute(dto);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = (expect(presented.entityType).toBe('season');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.entityType).toBe('season');
|
||||
expect(presented.entityId).toBe('season1');
|
||||
expect(presented.acceptingApplications).toBe(true);
|
||||
expect(presented.customRequirements).toBe('Some requirements');
|
||||
@@ -116,7 +106,7 @@ describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as unknown as ISponsorshipPricingRepository,
|
||||
const useCase = new GetEntitySponsorshipPricingUseCase(mockSponsorshipPricingRepo as any,
|
||||
mockLogger);
|
||||
|
||||
const dto: GetEntitySponsorshipPricingInput = {
|
||||
@@ -137,5 +127,5 @@ describe('GetEntitySponsorshipPricingUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* Used by sponsors to see available slots and prices.
|
||||
*/
|
||||
|
||||
import type { SponsorshipPricingRepository } from '../../domain/repositories/SponsorshipPricingRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { SponsorableEntityType } from '../../domain/entities/SponsorshipRequest';
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetLeagueAdminPermissionsUseCase,
|
||||
type GetLeagueAdminPermissionsInput,
|
||||
type GetLeagueAdminPermissionsResult,
|
||||
type GetLeagueAdminPermissionsErrorCode,
|
||||
} from './GetLeagueAdminPermissionsUseCase';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetLeagueAdminPermissionsUseCase,
|
||||
type GetLeagueAdminPermissionsErrorCode,
|
||||
type GetLeagueAdminPermissionsInput
|
||||
} from './GetLeagueAdminPermissionsUseCase';
|
||||
|
||||
describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
let mockLeagueRepo: ILeagueRepository;
|
||||
let mockMembershipRepo: ILeagueMembershipRepository;
|
||||
let mockLeagueRepo: any;
|
||||
let mockMembershipRepo: any;
|
||||
let mockFindById: Mock;
|
||||
let mockGetMembership: Mock;
|
||||
const logger: Logger = {
|
||||
@@ -34,7 +31,7 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
exists: vi.fn(),
|
||||
findByOwnerId: vi.fn(),
|
||||
searchByName: vi.fn(),
|
||||
} as ILeagueRepository;
|
||||
};
|
||||
|
||||
mockMembershipRepo = {
|
||||
getMembership: mockGetMembership,
|
||||
@@ -46,9 +43,8 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
removeJoinRequest: vi.fn(),
|
||||
countByLeagueId: vi.fn(),
|
||||
getLeagueMembers: vi.fn(),
|
||||
} as ILeagueMembershipRepository;
|
||||
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
const createUseCase = () => new GetLeagueAdminPermissionsUseCase(mockLeagueRepo,
|
||||
mockMembershipRepo,
|
||||
@@ -59,7 +55,7 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
performerDriverId: 'driver1',
|
||||
};
|
||||
|
||||
it('returns LEAGUE_NOT_FOUND when league does not exist and does not call output', async () => {
|
||||
it('returns LEAGUE_NOT_FOUND when league does not exist', async () => {
|
||||
mockFindById.mockResolvedValue(null);
|
||||
|
||||
const useCase = createUseCase();
|
||||
@@ -69,9 +65,9 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminPermissionsErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns USER_NOT_MEMBER when membership is missing and does not call output', async () => {
|
||||
it('returns USER_NOT_MEMBER when membership is missing', async () => {
|
||||
mockFindById.mockResolvedValue({ id: 'league1' });
|
||||
mockGetMembership.mockResolvedValue(null);
|
||||
|
||||
@@ -82,9 +78,9 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminPermissionsErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('USER_NOT_MEMBER');
|
||||
expect(err.details.message).toBe('User is not a member of this league');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns USER_NOT_MEMBER when membership is not active and does not call output', async () => {
|
||||
it('returns USER_NOT_MEMBER when membership is not active', async () => {
|
||||
mockFindById.mockResolvedValue({ id: 'league1' });
|
||||
mockGetMembership.mockResolvedValue({ status: 'inactive', role: 'admin' });
|
||||
|
||||
@@ -95,9 +91,9 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminPermissionsErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('USER_NOT_MEMBER');
|
||||
expect(err.details.message).toBe('User is not a member of this league');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns USER_NOT_MEMBER when role is member and does not call output', async () => {
|
||||
it('returns USER_NOT_MEMBER when role is member', async () => {
|
||||
mockFindById.mockResolvedValue({ id: 'league1' });
|
||||
mockGetMembership.mockResolvedValue({ status: 'active', role: 'member' });
|
||||
|
||||
@@ -108,10 +104,10 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminPermissionsErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('USER_NOT_MEMBER');
|
||||
expect(err.details.message).toBe('User is not a member of this league');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns admin permissions for admin role and calls output once', async () => {
|
||||
const league = { id: 'league1' } as unknown as { id: string };
|
||||
it('returns admin permissions for admin role', async () => {
|
||||
const league = { id: 'league1' } as any;
|
||||
mockFindById.mockResolvedValue(league);
|
||||
mockGetMembership.mockResolvedValue({ status: 'active', role: 'admin' });
|
||||
|
||||
@@ -119,9 +115,9 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.league).toBe(league);
|
||||
expect(presented.league).toBe(league);
|
||||
expect(presented.permissions).toEqual({
|
||||
canManageSchedule: true,
|
||||
canManageMembers: true,
|
||||
@@ -130,8 +126,8 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns admin permissions for owner role and calls output once', async () => {
|
||||
const league = { id: 'league1' } as unknown as { id: string };
|
||||
it('returns admin permissions for owner role', async () => {
|
||||
const league = { id: 'league1' } as any;
|
||||
mockFindById.mockResolvedValue(league);
|
||||
mockGetMembership.mockResolvedValue({ status: 'active', role: 'owner' });
|
||||
|
||||
@@ -139,9 +135,9 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.league).toBe(league);
|
||||
expect(presented.league).toBe(league);
|
||||
expect(presented.permissions).toEqual({
|
||||
canManageSchedule: true,
|
||||
canManageMembers: true,
|
||||
@@ -150,7 +146,7 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('wraps repository errors in REPOSITORY_ERROR and does not call output', async () => {
|
||||
it('wraps repository errors in REPOSITORY_ERROR', async () => {
|
||||
const error = new Error('repo failed');
|
||||
mockFindById.mockRejectedValue(error);
|
||||
|
||||
@@ -161,5 +157,5 @@ describe('GetLeagueAdminPermissionsUseCase', () => {
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminPermissionsErrorCode, { message: string }>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('repo failed');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { League } from '../../domain/entities/League';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
|
||||
export type GetLeagueAdminPermissionsInput = {
|
||||
leagueId: string;
|
||||
performerDriverId: string;
|
||||
};
|
||||
|
||||
export type LeagueAdminPermissions = {
|
||||
canManageSchedule: boolean;
|
||||
|
||||
@@ -9,8 +9,9 @@ import type { LeagueRepository } from '../../domain/repositories/LeagueRepositor
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
describe('GetLeagueAdminUseCase', () => {
|
||||
let mockLeagueRepo: ILeagueRepository;
|
||||
let mockLeagueRepo: any;
|
||||
let mockFindById: Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
mockFindById = vi.fn();
|
||||
mockLeagueRepo = {
|
||||
@@ -22,9 +23,8 @@ describe('GetLeagueAdminUseCase', () => {
|
||||
exists: vi.fn(),
|
||||
findByOwnerId: vi.fn(),
|
||||
searchByName: vi.fn(),
|
||||
} as ILeagueRepository;
|
||||
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
const createUseCase = () => new GetLeagueAdminUseCase(mockLeagueRepo);
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('GetLeagueAdminUseCase', () => {
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminErrorCode, { message: string }>;
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return league data when league found', async () => {
|
||||
const league = { id: 'league1', ownerId: 'owner1' };
|
||||
@@ -52,8 +52,8 @@ describe('GetLeagueAdminUseCase', () => {
|
||||
const result = await useCase.execute(params);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.league.id).toBe('league1');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.league.id).toBe('league1');
|
||||
expect(presented.league.ownerId).toBe('owner1');
|
||||
});
|
||||
|
||||
@@ -68,5 +68,5 @@ describe('GetLeagueAdminUseCase', () => {
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<GetLeagueAdminErrorCode, { message: string }>;
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('Repository failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import type { DriverRatingPort } from '../ports/DriverRatingPort';
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
GetLeagueDriverSeasonStatsUseCase,
|
||||
type GetLeagueDriverSeasonStatsErrorCode,
|
||||
type GetLeagueDriverSeasonStatsInput,
|
||||
type GetLeagueDriverSeasonStatsResult,
|
||||
} from './GetLeagueDriverSeasonStatsUseCase';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { DriverRatingPort } from '../ports/DriverRatingPort';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
const mockStandingFindByLeagueId = vi.fn();
|
||||
@@ -20,15 +20,15 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
const mockRaceFindByLeagueId = vi.fn();
|
||||
const mockDriverRatingGetRating = vi.fn();
|
||||
const mockDriverFindById = vi.fn();
|
||||
const mockTeamFindById = vi.fn();
|
||||
|
||||
let useCase: GetLeagueDriverSeasonStatsUseCase;
|
||||
let standingRepository: IStandingRepository;
|
||||
let resultRepository: IResultRepository;
|
||||
let penaltyRepository: IPenaltyRepository;
|
||||
let raceRepository: IRaceRepository;
|
||||
let driverRepository: IDriverRepository;
|
||||
let driverRatingPort: DriverRatingPort;
|
||||
let standingRepository: any;
|
||||
let resultRepository: any;
|
||||
let penaltyRepository: any;
|
||||
let raceRepository: any;
|
||||
let driverRepository: any;
|
||||
let driverRatingPort: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockStandingFindByLeagueId.mockReset();
|
||||
mockResultFindByDriverIdAndLeagueId.mockReset();
|
||||
@@ -36,7 +36,6 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
mockRaceFindByLeagueId.mockReset();
|
||||
mockDriverRatingGetRating.mockReset();
|
||||
mockDriverFindById.mockReset();
|
||||
mockTeamFindById.mockReset();
|
||||
|
||||
standingRepository = {
|
||||
findByLeagueId: mockStandingFindByLeagueId,
|
||||
@@ -103,8 +102,6 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
updateDriverRating: vi.fn(),
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
useCase = new GetLeagueDriverSeasonStatsUseCase(standingRepository,
|
||||
resultRepository,
|
||||
penaltyRepository,
|
||||
@@ -182,8 +179,8 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.leagueId).toBe('league-1');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.leagueId).toBe('league-1');
|
||||
expect(presented.stats).toHaveLength(2);
|
||||
|
||||
expect(presented.stats[0]).toEqual({
|
||||
@@ -231,8 +228,8 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented?.stats[0]?.penaltyPoints).toBe(0);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.stats[0]?.penaltyPoints).toBe(0);
|
||||
});
|
||||
|
||||
it('should return LEAGUE_NOT_FOUND when no standings are found', async () => {
|
||||
@@ -250,7 +247,7 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return REPOSITORY_ERROR when an unexpected error occurs', async () => {
|
||||
const input: GetLeagueDriverSeasonStatsInput = { leagueId: 'league-1' };
|
||||
@@ -265,8 +262,7 @@ describe('GetLeagueDriverSeasonStatsUseCase', () => {
|
||||
GetLeagueDriverSeasonStatsErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('repository failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,30 +13,23 @@ import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorC
|
||||
|
||||
describe('GetLeagueFullConfigUseCase', () => {
|
||||
let useCase: GetLeagueFullConfigUseCase;
|
||||
let leagueRepository: ILeagueRepository & { findById: ReturnType<typeof vi.fn> };
|
||||
let seasonRepository: ISeasonRepository & { findByLeagueId: ReturnType<typeof vi.fn> };
|
||||
let leagueScoringConfigRepository: ILeagueScoringConfigRepository & {
|
||||
findBySeasonId: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
let gameRepository: IGameRepository & { findById: ReturnType<typeof vi.fn> };
|
||||
let leagueRepository: any;
|
||||
let seasonRepository: any;
|
||||
let leagueScoringConfigRepository: any;
|
||||
let gameRepository: any;
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any;
|
||||
};
|
||||
seasonRepository = {
|
||||
findByLeagueId: vi.fn(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any;
|
||||
};
|
||||
leagueScoringConfigRepository = {
|
||||
findBySeasonId: vi.fn(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any;
|
||||
};
|
||||
gameRepository = {
|
||||
findById: vi.fn(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any;
|
||||
|
||||
};
|
||||
|
||||
useCase = new GetLeagueFullConfigUseCase(leagueRepository,
|
||||
@@ -78,9 +71,7 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const firstCall = const presented = firstCall[0] as GetLeagueFullConfigResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.config.league).toEqual(mockLeague);
|
||||
expect(presented.config.activeSeason).toEqual(mockSeasons[0]);
|
||||
@@ -88,7 +79,7 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
expect(presented.config.game).toEqual(mockGame);
|
||||
});
|
||||
|
||||
it('should return error when league not found and not call presenter', async () => {
|
||||
it('should return error when league not found', async () => {
|
||||
const input: GetLeagueFullConfigInput = { leagueId: 'league-1' };
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(null);
|
||||
@@ -103,7 +94,7 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle no active season', async () => {
|
||||
const input: GetLeagueFullConfigInput = { leagueId: 'league-1' };
|
||||
@@ -121,8 +112,7 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const firstCall = const presented = firstCall[0] as GetLeagueFullConfigResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.config.league).toEqual(mockLeague);
|
||||
expect(presented.config.activeSeason).toBeUndefined();
|
||||
@@ -130,7 +120,7 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
expect(presented.config.game).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return repository error when repository throws and not call presenter', async () => {
|
||||
it('should return repository error when repository throws', async () => {
|
||||
const input: GetLeagueFullConfigInput = { leagueId: 'league-1' };
|
||||
|
||||
const thrownError = new Error('Repository failure');
|
||||
@@ -146,5 +136,5 @@ describe('GetLeagueFullConfigUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('Repository failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,9 +5,6 @@ import {
|
||||
type GetLeagueMembershipsResult,
|
||||
type GetLeagueMembershipsErrorCode,
|
||||
} from './GetLeagueMembershipsUseCase';
|
||||
import { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { LeagueMembership } from '../../domain/entities/LeagueMembership';
|
||||
import { Driver } from '../../domain/entities/Driver';
|
||||
import { League } from '../../domain/entities/League';
|
||||
@@ -24,6 +21,7 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
let leagueRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
leagueMembershipRepository = {
|
||||
getLeagueMembers: vi.fn(),
|
||||
@@ -34,12 +32,9 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
useCase = new GetLeagueMembershipsUseCase(leagueMembershipRepository as unknown as ILeagueMembershipRepository,
|
||||
driverRepository as unknown as IDriverRepository,
|
||||
leagueRepository as unknown as ILeagueRepository);
|
||||
useCase = new GetLeagueMembershipsUseCase(leagueMembershipRepository as any,
|
||||
driverRepository as any,
|
||||
leagueRepository as any);
|
||||
});
|
||||
|
||||
it('should return league memberships with drivers', async () => {
|
||||
@@ -90,14 +85,14 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId } as GetLeagueMembershipsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented?.league).toEqual(league);
|
||||
expect(presented?.memberships).toHaveLength(2);
|
||||
expect(presented?.memberships[0]?.membership).toEqual(memberships[0]);
|
||||
expect(presented?.memberships[0]?.driver).toEqual(driver1);
|
||||
expect(presented?.memberships[1]?.membership).toEqual(memberships[1]);
|
||||
expect(presented?.memberships[1]?.driver).toEqual(driver2);
|
||||
expect(presented.league).toEqual(league);
|
||||
expect(presented.memberships).toHaveLength(2);
|
||||
expect(presented.memberships[0]?.membership).toEqual(memberships[0]);
|
||||
expect(presented.memberships[0]?.driver).toEqual(driver1);
|
||||
expect(presented.memberships[1]?.membership).toEqual(memberships[1]);
|
||||
expect(presented.memberships[1]?.driver).toEqual(driver2);
|
||||
});
|
||||
|
||||
it('should handle drivers not found', async () => {
|
||||
@@ -125,12 +120,12 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId } as GetLeagueMembershipsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented?.league).toEqual(league);
|
||||
expect(presented?.memberships).toHaveLength(1);
|
||||
expect(presented?.memberships[0]?.membership).toEqual(memberships[0]);
|
||||
expect(presented?.memberships[0]?.driver).toBeNull();
|
||||
expect(presented.league).toEqual(league);
|
||||
expect(presented.memberships).toHaveLength(1);
|
||||
expect(presented.memberships[0]?.membership).toEqual(memberships[0]);
|
||||
expect(presented.memberships[0]?.driver).toBeNull();
|
||||
});
|
||||
|
||||
it('should return error when league not found', async () => {
|
||||
@@ -149,7 +144,7 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details?.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return repository error on unexpected failure', async () => {
|
||||
const leagueId = 'league-1';
|
||||
@@ -169,5 +164,5 @@ describe('GetLeagueMembershipsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details?.message).toBe('Database connection failed');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,11 +5,10 @@ import {
|
||||
type GetLeagueOwnerSummaryResult,
|
||||
type GetLeagueOwnerSummaryErrorCode,
|
||||
} from './GetLeagueOwnerSummaryUseCase';
|
||||
import { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { Driver } from '../../domain/entities/Driver';
|
||||
import { League } from '../../domain/entities/League';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
let useCase: GetLeagueOwnerSummaryUseCase;
|
||||
let leagueRepository: {
|
||||
@@ -18,6 +17,14 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
let driverRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
let leagueMembershipRepository: {
|
||||
getLeagueMembers: Mock;
|
||||
};
|
||||
let standingRepository: {
|
||||
findByDriverIdAndLeagueId: Mock;
|
||||
findByLeagueId: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
@@ -25,8 +32,19 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
driverRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
useCase = new GetLeagueOwnerSummaryUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
driverRepository as unknown as IDriverRepository);
|
||||
leagueMembershipRepository = {
|
||||
getLeagueMembers: vi.fn(),
|
||||
};
|
||||
standingRepository = {
|
||||
findByDriverIdAndLeagueId: vi.fn(),
|
||||
findByLeagueId: vi.fn(),
|
||||
};
|
||||
useCase = new GetLeagueOwnerSummaryUseCase(
|
||||
leagueRepository as any,
|
||||
driverRepository as any,
|
||||
leagueMembershipRepository as any,
|
||||
standingRepository as any
|
||||
);
|
||||
});
|
||||
|
||||
it('should return owner summary when league and owner exist', async () => {
|
||||
@@ -48,15 +66,17 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
driverRepository.findById.mockResolvedValue(driver);
|
||||
leagueMembershipRepository.getLeagueMembers.mockResolvedValue([]);
|
||||
standingRepository.findByDriverIdAndLeagueId.mockResolvedValue(null);
|
||||
|
||||
const result = await useCase.execute({ leagueId } as GetLeagueOwnerSummaryInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented?.league).toBe(league);
|
||||
expect(presented?.owner).toBe(driver);
|
||||
expect(presented?.rating).toBe(0);
|
||||
expect(presented?.rank).toBe(0);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.league).toBe(league);
|
||||
expect(presented.owner).toBe(driver);
|
||||
expect(presented.rating).toBeNull();
|
||||
expect(presented.rank).toBeNull();
|
||||
});
|
||||
|
||||
it('should return error when league does not exist', async () => {
|
||||
@@ -73,7 +93,7 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
>;
|
||||
expect(errorResult.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(errorResult.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when owner does not exist', async () => {
|
||||
const leagueId = 'league-1';
|
||||
@@ -98,7 +118,7 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
>;
|
||||
expect(errorResult.code).toBe('OWNER_NOT_FOUND');
|
||||
expect(errorResult.details.message).toBe('League owner not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return repository error when repository throws', async () => {
|
||||
const leagueId = 'league-1';
|
||||
@@ -115,5 +135,5 @@ describe('GetLeagueOwnerSummaryUseCase', () => {
|
||||
|
||||
expect(errorResult.code).toBe('REPOSITORY_ERROR');
|
||||
expect(errorResult.details.message).toBe('DB failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { SeasonScheduleGenerator } from '@/racing/domain/services/SeasonScheduleGenerator';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { League } from '../../domain/entities/League';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
import type { Season } from '../../domain/entities/season/Season';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import { SeasonScheduleGenerator } from '../../domain/services/SeasonScheduleGenerator';
|
||||
|
||||
export type GetLeagueScheduleErrorCode =
|
||||
| 'LEAGUE_NOT_FOUND'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { GetLeagueScoringConfigUseCase } from './GetLeagueScoringConfigUseCase';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
@@ -12,39 +13,39 @@ import type { LeagueScoringPreset } from '../../domain/types/LeagueScoringPreset
|
||||
|
||||
describe('GetLeagueScoringConfigUseCase', () => {
|
||||
let useCase: GetLeagueScoringConfigUseCase;
|
||||
let mockLeagueRepository: jest.Mocked<ILeagueRepository>;
|
||||
let mockSeasonRepository: jest.Mocked<ISeasonRepository>;
|
||||
let mockLeagueScoringConfigRepository: jest.Mocked<ILeagueScoringConfigRepository>;
|
||||
let mockGameRepository: jest.Mocked<IGameRepository>;
|
||||
let mockPresetProvider: { getPresetById: jest.Mock };
|
||||
let mockLeagueRepository: any;
|
||||
let mockSeasonRepository: any;
|
||||
let mockLeagueScoringConfigRepository: any;
|
||||
let mockGameRepository: any;
|
||||
let mockPresetProvider: { getPresetById: any };
|
||||
|
||||
beforeEach(() => {
|
||||
mockLeagueRepository = {
|
||||
findById: jest.fn(),
|
||||
exists: jest.fn(),
|
||||
save: jest.fn(),
|
||||
findAll: jest.fn(),
|
||||
} as any;
|
||||
findById: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
save: vi.fn(),
|
||||
findAll: vi.fn(),
|
||||
};
|
||||
|
||||
mockSeasonRepository = {
|
||||
findByLeagueId: jest.fn(),
|
||||
save: jest.fn(),
|
||||
findById: jest.fn(),
|
||||
} as any;
|
||||
findByLeagueId: vi.fn(),
|
||||
save: vi.fn(),
|
||||
findById: vi.fn(),
|
||||
};
|
||||
|
||||
mockLeagueScoringConfigRepository = {
|
||||
findBySeasonId: jest.fn(),
|
||||
save: jest.fn(),
|
||||
} as any;
|
||||
findBySeasonId: vi.fn(),
|
||||
save: vi.fn(),
|
||||
};
|
||||
|
||||
mockGameRepository = {
|
||||
findById: jest.fn(),
|
||||
save: jest.fn(),
|
||||
findAll: jest.fn(),
|
||||
} as any;
|
||||
findById: vi.fn(),
|
||||
save: vi.fn(),
|
||||
findAll: vi.fn(),
|
||||
};
|
||||
|
||||
mockPresetProvider = {
|
||||
getPresetById: jest.fn(),
|
||||
getPresetById: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetLeagueScoringConfigUseCase(
|
||||
@@ -80,7 +81,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const value = result.value as any;
|
||||
const value = result.unwrap() as any;
|
||||
expect(value.league).toBe(mockLeague);
|
||||
expect(value.season).toBe(mockSeason);
|
||||
expect(value.scoringConfig).toBe(mockScoringConfig);
|
||||
@@ -94,7 +95,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'non-existent' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'LEAGUE_NOT_FOUND',
|
||||
details: { message: 'League not found' },
|
||||
});
|
||||
@@ -109,7 +110,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'NO_SEASONS',
|
||||
details: { message: 'No seasons found for league' },
|
||||
});
|
||||
@@ -129,7 +130,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'NO_ACTIVE_SEASON',
|
||||
details: { message: 'No active season found for league' },
|
||||
});
|
||||
@@ -150,7 +151,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'NO_SCORING_CONFIG',
|
||||
details: { message: 'Scoring configuration not found' },
|
||||
});
|
||||
@@ -177,7 +178,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'GAME_NOT_FOUND',
|
||||
details: { message: 'Game not found for season' },
|
||||
});
|
||||
@@ -205,7 +206,7 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const value = result.value as any;
|
||||
const value = result.unwrap() as any;
|
||||
expect(value.preset).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -215,9 +216,9 @@ describe('GetLeagueScoringConfigUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId: 'league-1' });
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.value).toEqual({
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
details: { message: 'Database error' },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -74,7 +74,7 @@ export class GetLeagueScoringConfigUseCase {
|
||||
return (seasonStatus as { toString: () => string }).toString() === 'active';
|
||||
}
|
||||
return false;
|
||||
}) ?? seasons[0];
|
||||
});
|
||||
|
||||
if (!activeSeason) {
|
||||
return Result.err({
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { Season } from '../../domain/entities/season';
|
||||
import { Season } from '../../domain/entities/season/Season';
|
||||
import { League } from '../../domain/entities/League';
|
||||
|
||||
describe('GetLeagueSeasonsUseCase', () => {
|
||||
@@ -18,7 +18,7 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
};
|
||||
let leagueRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
exists: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -28,15 +28,14 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
useCase = new GetLeagueSeasonsUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
leagueRepository as unknown as ILeagueRepository);
|
||||
useCase = new GetLeagueSeasonsUseCase(leagueRepository as any,
|
||||
seasonRepository as any);
|
||||
});
|
||||
|
||||
it('should present seasons with correct isParallelActive flags on success', async () => {
|
||||
it('should return seasons with correct isParallelActive flags on success', async () => {
|
||||
const leagueId = 'league-1';
|
||||
const league = League.create({
|
||||
id: leagueId,
|
||||
@@ -64,24 +63,24 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
}),
|
||||
];
|
||||
|
||||
leagueRepository.exists.mockResolvedValue(true);
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findByLeagueId.mockResolvedValue(seasons);
|
||||
|
||||
const result = await useCase.execute({ leagueId } satisfies GetLeagueSeasonsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented?.league).toBe(league);
|
||||
expect(presented?.seasons).toHaveLength(2);
|
||||
expect(presented.seasons).toHaveLength(2);
|
||||
|
||||
expect(presented?.seasons[0]?.season).toBe(seasons[0]);
|
||||
expect(presented?.seasons[0]?.isPrimary).toBe(false);
|
||||
expect(presented?.seasons[0]?.isParallelActive).toBe(false);
|
||||
expect(presented.seasons[0]?.season).toBe(seasons[0]);
|
||||
expect(presented.seasons[0]?.isPrimary).toBe(true);
|
||||
expect(presented.seasons[0]?.isParallelActive).toBe(false);
|
||||
|
||||
expect(presented?.seasons[1]?.season).toBe(seasons[1]);
|
||||
expect(presented?.seasons[1]?.isPrimary).toBe(false);
|
||||
expect(presented?.seasons[1]?.isParallelActive).toBe(false);
|
||||
expect(presented.seasons[1]?.season).toBe(seasons[1]);
|
||||
expect(presented.seasons[1]?.isPrimary).toBe(false);
|
||||
expect(presented.seasons[1]?.isParallelActive).toBe(false);
|
||||
});
|
||||
|
||||
it('should set isParallelActive true for active seasons when multiple active', async () => {
|
||||
@@ -110,23 +109,24 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
}),
|
||||
];
|
||||
|
||||
leagueRepository.exists.mockResolvedValue(true);
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findByLeagueId.mockResolvedValue(seasons);
|
||||
|
||||
const result = await useCase.execute({ leagueId } satisfies GetLeagueSeasonsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented?.seasons).toHaveLength(2);
|
||||
expect(presented?.seasons[0]?.isParallelActive).toBe(true);
|
||||
expect(presented?.seasons[1]?.isParallelActive).toBe(true);
|
||||
expect(presented.seasons).toHaveLength(2);
|
||||
expect(presented.seasons[0]?.isParallelActive).toBe(true);
|
||||
expect(presented.seasons[1]?.isParallelActive).toBe(true);
|
||||
});
|
||||
|
||||
it('should return LEAGUE_NOT_FOUND error when league does not exist', async () => {
|
||||
const leagueId = 'missing-league';
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(null);
|
||||
leagueRepository.exists.mockResolvedValue(false);
|
||||
|
||||
const result = await useCase.execute({ leagueId } satisfies GetLeagueSeasonsInput);
|
||||
|
||||
@@ -138,13 +138,13 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return REPOSITORY_ERROR when repository throws', async () => {
|
||||
const leagueId = 'league-1';
|
||||
const errorMessage = 'DB error';
|
||||
|
||||
leagueRepository.findById.mockRejectedValue(new Error(errorMessage));
|
||||
leagueRepository.exists.mockRejectedValue(new Error(errorMessage));
|
||||
|
||||
const result = await useCase.execute({ leagueId } satisfies GetLeagueSeasonsInput);
|
||||
|
||||
@@ -156,5 +156,5 @@ describe('GetLeagueSeasonsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe(errorMessage);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,8 +6,6 @@ import {
|
||||
type GetLeagueStandingsResult,
|
||||
type GetLeagueStandingsErrorCode,
|
||||
} from './GetLeagueStandingsUseCase';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { Standing } from '../../domain/entities/Standing';
|
||||
import { Driver } from '../../domain/entities/Driver';
|
||||
|
||||
@@ -19,6 +17,7 @@ describe('GetLeagueStandingsUseCase', () => {
|
||||
let driverRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
standingRepository = {
|
||||
findByLeagueId: vi.fn(),
|
||||
@@ -26,15 +25,12 @@ describe('GetLeagueStandingsUseCase', () => {
|
||||
driverRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetLeagueStandingsUseCase(standingRepository as unknown as IStandingRepository,
|
||||
driverRepository as unknown as IDriverRepository);
|
||||
useCase = new GetLeagueStandingsUseCase(standingRepository as any,
|
||||
driverRepository as any);
|
||||
});
|
||||
|
||||
it('should present standings with drivers mapped and return ok result', async () => {
|
||||
it('should return standings with drivers mapped', async () => {
|
||||
const leagueId = 'league-1';
|
||||
const standings = [
|
||||
Standing.create({
|
||||
@@ -75,9 +71,9 @@ describe('GetLeagueStandingsUseCase', () => {
|
||||
const result = await useCase.execute({ leagueId } satisfies GetLeagueStandingsInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.standings).toHaveLength(2);
|
||||
expect(presented.standings).toHaveLength(2);
|
||||
expect(presented.standings[0]).toEqual({
|
||||
driverId: 'driver-1',
|
||||
driver: driver1,
|
||||
@@ -92,7 +88,7 @@ describe('GetLeagueStandingsUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return repository error and not call output when repository fails', async () => {
|
||||
it('should return repository error when repository fails', async () => {
|
||||
const leagueId = 'league-1';
|
||||
standingRepository.findByLeagueId.mockRejectedValue(new Error('DB error'));
|
||||
|
||||
@@ -106,5 +102,5 @@ describe('GetLeagueStandingsUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
type GetLeagueStatsResult,
|
||||
type GetLeagueStatsErrorCode,
|
||||
} from './GetLeagueStatsUseCase';
|
||||
import { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
describe('GetLeagueStatsUseCase', () => {
|
||||
@@ -18,6 +18,7 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
findByLeagueId: Mock;
|
||||
};
|
||||
let getDriverRating: Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
leagueMembershipRepository = {
|
||||
getLeagueMembers: vi.fn(),
|
||||
@@ -26,8 +27,8 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
findByLeagueId: vi.fn(),
|
||||
};
|
||||
getDriverRating = vi.fn();
|
||||
useCase = new GetLeagueStatsUseCase(leagueMembershipRepository as unknown as ILeagueMembershipRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
useCase = new GetLeagueStatsUseCase(leagueMembershipRepository as any,
|
||||
raceRepository as any,
|
||||
getDriverRating);
|
||||
});
|
||||
|
||||
@@ -52,8 +53,8 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = (expect(presented.leagueId).toBe(input.leagueId);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.leagueId).toBe(input.leagueId);
|
||||
expect(presented.driverCount).toBe(3);
|
||||
expect(presented.raceCount).toBe(2);
|
||||
expect(presented.averageRating).toBe(1550); // (1500 + 1600) / 2
|
||||
@@ -71,8 +72,8 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = (expect(presented.leagueId).toBe(input.leagueId);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.leagueId).toBe(input.leagueId);
|
||||
expect(presented.driverCount).toBe(1);
|
||||
expect(presented.raceCount).toBe(1);
|
||||
expect(presented.averageRating).toBe(0);
|
||||
@@ -92,7 +93,7 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error when repository fails', async () => {
|
||||
const input: GetLeagueStatsInput = { leagueId: 'league-1' };
|
||||
@@ -107,5 +108,5 @@ describe('GetLeagueStatsUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,9 +40,9 @@ describe('GetLeagueWalletUseCase', () => {
|
||||
findByWalletId: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetLeagueWalletUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
leagueWalletRepository as unknown as ILeagueWalletRepository,
|
||||
transactionRepository as unknown as ITransactionRepository);
|
||||
useCase = new GetLeagueWalletUseCase(leagueRepository as any,
|
||||
leagueWalletRepository as any,
|
||||
transactionRepository as any);
|
||||
});
|
||||
|
||||
it('returns mapped wallet data when wallet exists', async () => {
|
||||
@@ -123,8 +123,8 @@ describe('GetLeagueWalletUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = (expect(presented.wallet).toBe(wallet);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.wallet).toBe(wallet);
|
||||
expect(presented.transactions).toHaveLength(transactions.length);
|
||||
expect(presented.transactions[0]!.id).toEqual(
|
||||
transactions.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0]!
|
||||
@@ -171,7 +171,7 @@ describe('GetLeagueWalletUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('WALLET_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League wallet not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns league not found when league does not exist', async () => {
|
||||
const leagueId = 'league-missing';
|
||||
@@ -190,7 +190,7 @@ describe('GetLeagueWalletUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns repository error when repository throws', async () => {
|
||||
const leagueId = 'league-1';
|
||||
@@ -209,5 +209,5 @@ describe('GetLeagueWalletUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,6 @@ import {
|
||||
type GetRaceProtestsResult,
|
||||
type GetRaceProtestsErrorCode,
|
||||
} from './GetRaceProtestsUseCase';
|
||||
import type { ProtestRepository } from '../../domain/repositories/ProtestRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { Protest } from '../../domain/entities/Protest';
|
||||
import { Driver } from '../../domain/entities/Driver';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
@@ -15,11 +13,12 @@ describe('GetRaceProtestsUseCase', () => {
|
||||
let useCase: GetRaceProtestsUseCase;
|
||||
let protestRepository: { findByRaceId: Mock };
|
||||
let driverRepository: { findById: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
protestRepository = { findByRaceId: vi.fn() };
|
||||
driverRepository = { findById: vi.fn() };
|
||||
useCase = new GetRaceProtestsUseCase(protestRepository as unknown as IProtestRepository,
|
||||
driverRepository as unknown as IDriverRepository);
|
||||
useCase = new GetRaceProtestsUseCase(protestRepository as any,
|
||||
driverRepository as any);
|
||||
});
|
||||
|
||||
it('should return protests with drivers', async () => {
|
||||
@@ -66,10 +65,7 @@ describe('GetRaceProtestsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetRaceProtestsResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.protests).toHaveLength(1);
|
||||
expect(presented.protests[0]).toEqual(protest);
|
||||
@@ -85,10 +81,7 @@ describe('GetRaceProtestsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetRaceProtestsResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.protests).toEqual([]);
|
||||
expect(presented.drivers).toEqual([]);
|
||||
@@ -109,5 +102,5 @@ describe('GetRaceProtestsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,25 +5,23 @@ import {
|
||||
type GetRaceRegistrationsResult,
|
||||
type GetRaceRegistrationsErrorCode,
|
||||
} from './GetRaceRegistrationsUseCase';
|
||||
import type { RaceRepository } from '@core/racing/domain/repositories/RaceRepository';
|
||||
import type { RaceRegistrationRepository } from '@core/racing/domain/repositories/RaceRegistrationRepository';
|
||||
import { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration';
|
||||
import { Race } from '@core/racing/domain/entities/Race';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
|
||||
describe('GetRaceRegistrationsUseCase', () => {
|
||||
let useCase: GetRaceRegistrationsUseCase;
|
||||
let raceRepository: { findById: Mock };
|
||||
let registrationRepository: { findByRaceId: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
raceRepository = { findById: vi.fn() };
|
||||
registrationRepository = { findByRaceId: vi.fn() };
|
||||
useCase = new GetRaceRegistrationsUseCase(raceRepository as unknown as IRaceRepository,
|
||||
registrationRepository as unknown as IRaceRegistrationRepository);
|
||||
useCase = new GetRaceRegistrationsUseCase(raceRepository as any,
|
||||
registrationRepository as any);
|
||||
});
|
||||
|
||||
it('should present race and registrations on success', async () => {
|
||||
it('should return race and registrations on success', async () => {
|
||||
const input: GetRaceRegistrationsInput = { raceId: 'race-1' };
|
||||
|
||||
const race = Race.create({
|
||||
@@ -42,14 +40,10 @@ describe('GetRaceRegistrationsUseCase', () => {
|
||||
raceRepository.findById.mockResolvedValue(race);
|
||||
registrationRepository.findByRaceId.mockResolvedValue(registrations);
|
||||
|
||||
const result: Result<void, ApplicationErrorCode<GetRaceRegistrationsErrorCode, { message: string }>> =
|
||||
await useCase.execute(input);
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetRaceRegistrationsResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.race).toEqual(race);
|
||||
expect(presented.registrations).toHaveLength(2);
|
||||
@@ -62,8 +56,7 @@ describe('GetRaceRegistrationsUseCase', () => {
|
||||
|
||||
raceRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const result: Result<void, ApplicationErrorCode<GetRaceRegistrationsErrorCode, { message: string }>> =
|
||||
await useCase.execute(input);
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<
|
||||
@@ -73,15 +66,14 @@ describe('GetRaceRegistrationsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('RACE_NOT_FOUND');
|
||||
expect(err.details?.message).toBe('Race not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return REPOSITORY_ERROR when repository throws', async () => {
|
||||
const input: GetRaceRegistrationsInput = { raceId: 'race-1' };
|
||||
|
||||
raceRepository.findById.mockRejectedValue(new Error('DB failure'));
|
||||
|
||||
const result: Result<void, ApplicationErrorCode<GetRaceRegistrationsErrorCode, { message: string }>> =
|
||||
await useCase.execute(input);
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
const err = result.unwrapErr() as ApplicationErrorCode<
|
||||
@@ -91,5 +83,5 @@ describe('GetRaceRegistrationsUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details?.message).toBe('DB failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,19 +19,19 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
let resultRepository: { findByRaceId: Mock };
|
||||
let driverRepository: { findAll: Mock };
|
||||
let penaltyRepository: { findByRaceId: Mock };
|
||||
|
||||
beforeEach(() => {
|
||||
raceRepository = { findById: vi.fn() };
|
||||
leagueRepository = { findById: vi.fn() };
|
||||
resultRepository = { findByRaceId: vi.fn() };
|
||||
driverRepository = { findAll: vi.fn() };
|
||||
penaltyRepository = { findByRaceId: vi.fn() };
|
||||
};
|
||||
|
||||
useCase = new GetRaceResultsDetailUseCase(raceRepository as unknown as IRaceRepository,
|
||||
leagueRepository as unknown as ILeagueRepository,
|
||||
resultRepository as unknown as IResultRepository,
|
||||
driverRepository as unknown as IDriverRepository,
|
||||
penaltyRepository as unknown as IPenaltyRepository);
|
||||
useCase = new GetRaceResultsDetailUseCase(raceRepository as any,
|
||||
leagueRepository as any,
|
||||
resultRepository as any,
|
||||
driverRepository as any,
|
||||
penaltyRepository as any);
|
||||
});
|
||||
|
||||
it('presents race results detail when race exists', async () => {
|
||||
@@ -104,19 +104,18 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = (expect(presented.race).toEqual(race);
|
||||
expect(presented.race).toEqual(race);
|
||||
expect(presented.league).toEqual(league);
|
||||
expect(presented.results).toEqual(results);
|
||||
expect(presented.drivers).toEqual(drivers);
|
||||
expect(presented.penalties).toEqual(penalties);
|
||||
expect(presented.pointsSystem).toBeDefined();
|
||||
expect(presented.fastestLapTime).toBe(120);
|
||||
expect(presented.currentDriverId).toBe('driver-1');
|
||||
});
|
||||
|
||||
it('returns error when race not found and does not present data', async () => {
|
||||
it('returns error when race not found', async () => {
|
||||
const input: GetRaceResultsDetailInput = { raceId: 'race-1' };
|
||||
|
||||
raceRepository.findById.mockResolvedValue(null);
|
||||
@@ -131,7 +130,7 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('RACE_NOT_FOUND');
|
||||
expect(error.details.message).toBe('Race not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns repository error when an unexpected error occurs', async () => {
|
||||
const input: GetRaceResultsDetailInput = { raceId: 'race-1' };
|
||||
@@ -148,5 +147,5 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('Database failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,9 +5,6 @@ import {
|
||||
type GetRaceWithSOFResult,
|
||||
type GetRaceWithSOFErrorCode,
|
||||
} from './GetRaceWithSOFUseCase';
|
||||
import { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import { RaceRegistrationRepository } from '../../domain/repositories/RaceRegistrationRepository';
|
||||
import { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import { SessionType } from '../../domain/value-objects/SessionType';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
@@ -24,6 +21,7 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
findByRaceId: Mock;
|
||||
};
|
||||
let getDriverRating: Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
raceRepository = {
|
||||
findById: vi.fn(),
|
||||
@@ -35,13 +33,12 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
findByRaceId: vi.fn(),
|
||||
};
|
||||
getDriverRating = vi.fn();
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
useCase = new GetRaceWithSOFUseCase(raceRepository as unknown as IRaceRepository,
|
||||
registrationRepository as unknown as IRaceRegistrationRepository,
|
||||
resultRepository as unknown as IResultRepository,
|
||||
getDriverRating);
|
||||
useCase = new GetRaceWithSOFUseCase(
|
||||
raceRepository as any,
|
||||
registrationRepository as any,
|
||||
resultRepository as any,
|
||||
getDriverRating
|
||||
);
|
||||
});
|
||||
|
||||
it('should return error when race not found', async () => {
|
||||
@@ -56,7 +53,7 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('RACE_NOT_FOUND');
|
||||
expect(err.details?.message).toBe('Race with id race-1 not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return race with stored SOF when available', async () => {
|
||||
const race = Race.create({
|
||||
@@ -74,23 +71,15 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
|
||||
raceRepository.findById.mockResolvedValue(race);
|
||||
registrationRepository.getRegisteredDrivers.mockResolvedValue([
|
||||
'driver-1',
|
||||
'driver-2',
|
||||
'driver-3',
|
||||
'driver-4',
|
||||
'driver-5',
|
||||
'driver-6',
|
||||
'driver-7',
|
||||
'driver-8',
|
||||
'driver-9',
|
||||
'driver-10',
|
||||
'driver-1', 'driver-2', 'driver-3', 'driver-4', 'driver-5',
|
||||
'driver-6', 'driver-7', 'driver-8', 'driver-9', 'driver-10',
|
||||
]);
|
||||
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = expect(presented.race.id).toBe('race-1');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.race.id).toBe('race-1');
|
||||
expect(presented.race.leagueId).toBe('league-1');
|
||||
expect(presented.strengthOfField).toBe(1500);
|
||||
expect(presented.registeredCount).toBe(10);
|
||||
@@ -124,8 +113,8 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = expect(presented.strengthOfField).toBe(1500); // average
|
||||
const presented = result.unwrap();
|
||||
expect(presented.strengthOfField).toBe(1500); // average
|
||||
expect(presented.participantCount).toBe(2);
|
||||
expect(registrationRepository.getRegisteredDrivers).toHaveBeenCalledWith('race-1');
|
||||
expect(resultRepository.findByRaceId).not.toHaveBeenCalled();
|
||||
@@ -160,8 +149,8 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = expect(presented.strengthOfField).toBe(1500);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.strengthOfField).toBe(1500);
|
||||
expect(presented.participantCount).toBe(2);
|
||||
expect(resultRepository.findByRaceId).toHaveBeenCalledWith('race-1');
|
||||
expect(registrationRepository.getRegisteredDrivers).not.toHaveBeenCalled();
|
||||
@@ -191,8 +180,8 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = expect(presented.strengthOfField).toBe(1400); // only one rating
|
||||
const presented = result.unwrap();
|
||||
expect(presented.strengthOfField).toBe(1400); // only one rating
|
||||
expect(presented.participantCount).toBe(2);
|
||||
});
|
||||
|
||||
@@ -213,12 +202,12 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const [[presented]] = expect(presented.strengthOfField).toBe(null);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.strengthOfField).toBe(null);
|
||||
expect(presented.participantCount).toBe(0);
|
||||
});
|
||||
|
||||
it('should wrap repository errors in REPOSITORY_ERROR and not call output', async () => {
|
||||
it('should wrap repository errors in REPOSITORY_ERROR', async () => {
|
||||
raceRepository.findById.mockRejectedValue(new Error('boom'));
|
||||
|
||||
const result = await useCase.execute({ raceId: 'race-1' } as GetRaceWithSOFInput);
|
||||
@@ -230,5 +219,5 @@ describe('GetRaceWithSOFUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details?.message).toBe('boom');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetRacesPageDataUseCase,
|
||||
type GetRacesPageDataResult,
|
||||
type GetRacesPageDataInput,
|
||||
type GetRacesPageDataErrorCode,
|
||||
} from './GetRacesPageDataUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { Result } from '@core/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetRacesPageDataUseCase,
|
||||
type GetRacesPageDataErrorCode,
|
||||
type GetRacesPageDataInput,
|
||||
type GetRacesPageDataResult,
|
||||
} from './GetRacesPageDataUseCase';
|
||||
|
||||
describe('GetRacesPageDataUseCase', () => {
|
||||
let useCase: GetRacesPageDataUseCase;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
|
||||
export type GetRacesPageDataInput = {
|
||||
leagueId: string;
|
||||
};
|
||||
|
||||
export type GetRacesPageRaceItem = {
|
||||
race: Race;
|
||||
|
||||
@@ -5,38 +5,24 @@ import {
|
||||
type GetSeasonDetailsResult,
|
||||
type GetSeasonDetailsErrorCode,
|
||||
} from './GetSeasonDetailsUseCase';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { Season } from '../../domain/entities/season/Season';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
describe('GetSeasonDetailsUseCase', () => {
|
||||
let useCase: GetSeasonDetailsUseCase;
|
||||
let leagueRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
let seasonRepository: {
|
||||
findById: Mock;
|
||||
};
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
seasonRepository = {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetSeasonDetailsUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
seasonRepository as unknown as ISeasonRepository);
|
||||
useCase = new GetSeasonDetailsUseCase(seasonRepository as any);
|
||||
});
|
||||
|
||||
it('returns full details for a season belonging to the league', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
it('returns full details for a season', async () => {
|
||||
const season = Season.create({
|
||||
id: 'season-1',
|
||||
leagueId: 'league-1',
|
||||
@@ -45,58 +31,30 @@ describe('GetSeasonDetailsUseCase', () => {
|
||||
status: 'planned',
|
||||
}).withMaxDrivers(24);
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const input: GetSeasonDetailsInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
};
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented =
|
||||
(expect(presented).toBeDefined();
|
||||
expect(presented?.leagueId).toBe('league-1');
|
||||
expect(presented?.season.id).toBe('season-1');
|
||||
expect(presented?.season.leagueId).toBe('league-1');
|
||||
expect(presented?.season.gameId).toBe('iracing');
|
||||
expect(presented?.season.name).toBe('Detailed Season');
|
||||
expect(presented?.season.status.toString()).toBe('planned');
|
||||
expect(presented?.season.maxDrivers).toBe(24);
|
||||
expect(presented).toBeDefined();
|
||||
expect(presented.season.id).toBe('season-1');
|
||||
expect(presented.season.leagueId).toBe('league-1');
|
||||
expect(presented.season.gameId).toBe('iracing');
|
||||
expect(presented.season.name).toBe('Detailed Season');
|
||||
expect(presented.season.status.toString()).toBe('planned');
|
||||
expect(presented.season.maxDrivers).toBe(24);
|
||||
});
|
||||
|
||||
it('returns error when league not found', async () => {
|
||||
leagueRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const input: GetSeasonDetailsInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
};
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<
|
||||
GetSeasonDetailsErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details.message).toBe('League not found: league-1');
|
||||
});
|
||||
|
||||
it('returns error when season not found', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const input: GetSeasonDetailsInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
};
|
||||
|
||||
@@ -110,51 +68,15 @@ describe('GetSeasonDetailsUseCase', () => {
|
||||
>;
|
||||
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(error.details.message).toBe(
|
||||
'Season season-1 does not belong to league league-1',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error when season belongs to different league', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
const season = Season.create({
|
||||
id: 'season-1',
|
||||
leagueId: 'league-2',
|
||||
gameId: 'iracing',
|
||||
name: 'Season',
|
||||
status: 'active',
|
||||
});
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const input: GetSeasonDetailsInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
};
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<
|
||||
GetSeasonDetailsErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(error.details.message).toBe(
|
||||
'Season season-1 does not belong to league league-1',
|
||||
);
|
||||
});
|
||||
expect(error.details.message).toBe('Season not found');
|
||||
});
|
||||
|
||||
it('returns repository error when an unexpected exception occurs', async () => {
|
||||
leagueRepository.findById.mockRejectedValue(
|
||||
seasonRepository.findById.mockRejectedValue(
|
||||
new Error('Unexpected repository failure'),
|
||||
);
|
||||
|
||||
const input: GetSeasonDetailsInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
};
|
||||
|
||||
@@ -169,5 +91,5 @@ describe('GetSeasonDetailsUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toBe('Unexpected repository failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,11 +52,11 @@ describe('GetSeasonSponsorshipsUseCase', () => {
|
||||
findByLeagueId: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetSeasonSponsorshipsUseCase(seasonSponsorshipRepository as unknown as ISeasonSponsorshipRepository,
|
||||
seasonRepository as unknown as ISeasonRepository,
|
||||
leagueRepository as unknown as ILeagueRepository,
|
||||
leagueMembershipRepository as unknown as ILeagueMembershipRepository,
|
||||
raceRepository as unknown as IRaceRepository);
|
||||
useCase = new GetSeasonSponsorshipsUseCase(seasonSponsorshipRepository as any,
|
||||
seasonRepository as any,
|
||||
leagueRepository as any,
|
||||
leagueMembershipRepository as any,
|
||||
raceRepository as any);
|
||||
});
|
||||
|
||||
it('returns SEASON_NOT_FOUND when season does not exist', async () => {
|
||||
@@ -73,7 +73,7 @@ describe('GetSeasonSponsorshipsUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(err.details.message).toBe('Season not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns LEAGUE_NOT_FOUND when league for season does not exist', async () => {
|
||||
const input: GetSeasonSponsorshipsInput = { seasonId: 'season-1' };
|
||||
@@ -98,7 +98,7 @@ describe('GetSeasonSponsorshipsUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(err.details.message).toBe('League not found for season');
|
||||
});
|
||||
});
|
||||
|
||||
it('presents sponsorship details with computed metrics', async () => {
|
||||
const input: GetSeasonSponsorshipsInput = { seasonId: 'season-1' };
|
||||
@@ -149,8 +149,9 @@ describe('GetSeasonSponsorshipsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = (expect(presented.seasonId).toBe('season-1');
|
||||
expect(presented.seasonId).toBe('season-1');
|
||||
expect(presented.sponsorships).toHaveLength(1);
|
||||
|
||||
const detail = presented.sponsorships[0]!;
|
||||
@@ -187,5 +188,5 @@ describe('GetSeasonSponsorshipsUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { GetSponsorsUseCase } from './GetSponsorsUseCase';
|
||||
import { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import { Sponsor } from '../../domain/entities/sponsor/Sponsor';
|
||||
|
||||
describe('GetSponsorsUseCase', () => {
|
||||
let useCase: GetSponsorsUseCase;
|
||||
let sponsorRepository: {
|
||||
findAll: Mock;
|
||||
};
|
||||
let output: {
|
||||
present: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
sponsorRepository = {
|
||||
findAll: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
useCase = new GetSponsorsUseCase(sponsorRepository as unknown as ISponsorRepository);
|
||||
useCase = new GetSponsorsUseCase(sponsorRepository as any);
|
||||
});
|
||||
|
||||
it('should return all sponsors', async () => {
|
||||
@@ -41,8 +35,9 @@ describe('GetSponsorsUseCase', () => {
|
||||
const result = await useCase.execute();
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
});
|
||||
const presented = result.unwrap();
|
||||
expect(presented.sponsors).toEqual(sponsors);
|
||||
});
|
||||
|
||||
it('should return error on repository failure', async () => {
|
||||
sponsorRepository.findAll.mockRejectedValue(new Error('DB error'));
|
||||
@@ -52,7 +47,7 @@ describe('GetSponsorsUseCase', () => {
|
||||
expect(result.isErr()).toBe(true);
|
||||
expect(result.unwrapErr()).toEqual({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
message: 'Failed to fetch sponsors',
|
||||
details: { message: 'DB error' },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Sponsor } from '../../domain/entities/sponsor/Sponsor';
|
||||
import type { SponsorRepository } from '../../domain/repositories/SponsorRepository';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
export interface GetSponsorsInput {}
|
||||
|
||||
@@ -8,11 +9,20 @@ export interface GetSponsorsResult {
|
||||
sponsors: Sponsor[];
|
||||
}
|
||||
|
||||
export class GetSponsorsUseCase {
|
||||
constructor(private readonly sponsorRepository: ISponsorRepository) {}
|
||||
export type GetSponsorsErrorCode = 'REPOSITORY_ERROR';
|
||||
|
||||
async execute(_input: GetSponsorsInput): Promise<Result<GetSponsorsResult, never>> {
|
||||
const sponsors = await this.sponsorRepository.findAll();
|
||||
return Result.ok({ sponsors });
|
||||
export class GetSponsorsUseCase {
|
||||
constructor(private readonly sponsorRepository: SponsorRepository) {}
|
||||
|
||||
async execute(_input: GetSponsorsInput): Promise<Result<GetSponsorsResult, ApplicationErrorCode<GetSponsorsErrorCode, { message: string }>>> {
|
||||
try {
|
||||
const sponsors = await this.sponsorRepository.findAll();
|
||||
return Result.ok({ sponsors });
|
||||
} catch (error) {
|
||||
return Result.err({
|
||||
code: 'REPOSITORY_ERROR',
|
||||
details: { message: error instanceof Error ? error.message : 'Unknown error' },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import {
|
||||
type GetTeamDetailsResult,
|
||||
type GetTeamDetailsErrorCode,
|
||||
} from './GetTeamDetailsUseCase';
|
||||
import { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
@@ -19,6 +17,7 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
let membershipRepository: {
|
||||
getMembership: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
teamRepository = {
|
||||
findById: vi.fn(),
|
||||
@@ -26,8 +25,8 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
membershipRepository = {
|
||||
getMembership: vi.fn(),
|
||||
};
|
||||
useCase = new GetTeamDetailsUseCase(teamRepository as unknown as ITeamRepository,
|
||||
membershipRepository as unknown as ITeamMembershipRepository);
|
||||
useCase = new GetTeamDetailsUseCase(teamRepository as any,
|
||||
membershipRepository as any);
|
||||
});
|
||||
|
||||
it('should return team details with membership', async () => {
|
||||
@@ -57,9 +56,7 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetTeamDetailsResult;
|
||||
const presented = result.unwrap();
|
||||
expect(presented.team).toBe(team);
|
||||
expect(presented.membership).toEqual(membership);
|
||||
expect(presented.canManage).toBe(false);
|
||||
@@ -92,9 +89,7 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetTeamDetailsResult;
|
||||
const presented = result.unwrap();
|
||||
expect(presented.canManage).toBe(true);
|
||||
});
|
||||
|
||||
@@ -114,7 +109,7 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
>;
|
||||
expect(errorResult.code).toBe('TEAM_NOT_FOUND');
|
||||
expect(errorResult.details?.message).toBe('Team not found');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return error on repository failure', async () => {
|
||||
const teamId = 'team-1';
|
||||
@@ -132,5 +127,5 @@ describe('GetTeamDetailsUseCase', () => {
|
||||
>;
|
||||
expect(errorResult.code).toBe('REPOSITORY_ERROR');
|
||||
expect(errorResult.details?.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,9 +34,9 @@ describe('GetTeamJoinRequestsUseCase', () => {
|
||||
findById: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetTeamJoinRequestsUseCase(membershipRepository as unknown as ITeamMembershipRepository,
|
||||
driverRepository as unknown as IDriverRepository,
|
||||
teamRepository as unknown as ITeamRepository);
|
||||
useCase = new GetTeamJoinRequestsUseCase(membershipRepository as any,
|
||||
driverRepository as any,
|
||||
teamRepository as any);
|
||||
});
|
||||
|
||||
it('should return join requests with drivers when team exists', async () => {
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetTeamMembersUseCase,
|
||||
type GetTeamMembersInput,
|
||||
type GetTeamMembersResult,
|
||||
type GetTeamMembersErrorCode,
|
||||
} from './GetTeamMembersUseCase';
|
||||
import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { Driver } from '../../domain/entities/Driver';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import {
|
||||
GetTeamMembersUseCase,
|
||||
type GetTeamMembersErrorCode,
|
||||
type GetTeamMembersInput
|
||||
} from './GetTeamMembersUseCase';
|
||||
|
||||
describe('GetTeamMembersUseCase', () => {
|
||||
let useCase: GetTeamMembersUseCase;
|
||||
@@ -46,10 +41,10 @@ describe('GetTeamMembersUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
useCase = new GetTeamMembersUseCase(membershipRepository as unknown as ITeamMembershipRepository,
|
||||
driverRepository as unknown as IDriverRepository,
|
||||
teamRepository as unknown as ITeamRepository,
|
||||
logger as unknown as Logger);
|
||||
useCase = new GetTeamMembersUseCase(membershipRepository as any,
|
||||
driverRepository as any,
|
||||
teamRepository as any,
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('should return team members with driver entities', async () => {
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
import type { Driver } from '../../domain/entities/Driver';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
|
||||
export type GetTeamMembersInput = {
|
||||
teamId: string;
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import {
|
||||
GetTeamMembershipUseCase,
|
||||
type GetTeamMembershipInput,
|
||||
type GetTeamMembershipResult,
|
||||
type GetTeamMembershipErrorCode,
|
||||
} from './GetTeamMembershipUseCase';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
GetTeamMembershipUseCase,
|
||||
type GetTeamMembershipErrorCode,
|
||||
type GetTeamMembershipInput
|
||||
} from './GetTeamMembershipUseCase';
|
||||
|
||||
describe('GetTeamMembershipUseCase', () => {
|
||||
const mockGetMembership = vi.fn();
|
||||
const mockMembershipRepo: ITeamMembershipRepository = {
|
||||
const mockMembershipRepo: any = {
|
||||
getMembership: mockGetMembership,
|
||||
getActiveMembershipForDriver: vi.fn(),
|
||||
getTeamMembers: vi.fn(),
|
||||
@@ -34,13 +32,10 @@ describe('GetTeamMembershipUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
};
|
||||
|
||||
useCase = new GetTeamMembershipUseCase(mockMembershipRepo, mockLogger);
|
||||
});
|
||||
|
||||
it('should present membership data when membership exists', async () => {
|
||||
it('should return membership data when membership exists', async () => {
|
||||
const teamId = 'team1';
|
||||
const driverId = 'driver1';
|
||||
const membership = {
|
||||
@@ -58,16 +53,16 @@ describe('GetTeamMembershipUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.membership).toEqual({
|
||||
expect(presented.membership).toEqual({
|
||||
role: 'manager',
|
||||
joinedAt: '2023-01-01T00:00:00.000Z',
|
||||
isActive: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should present null membership when no membership exists', async () => {
|
||||
it('should return null membership when no membership exists', async () => {
|
||||
const teamId = 'team1';
|
||||
const driverId = 'driver1';
|
||||
|
||||
@@ -78,9 +73,9 @@ describe('GetTeamMembershipUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.membership).toBeNull();
|
||||
expect(presented.membership).toBeNull();
|
||||
});
|
||||
|
||||
it('should map driver role to member', async () => {
|
||||
@@ -101,9 +96,9 @@ describe('GetTeamMembershipUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.membership?.role).toBe('member');
|
||||
expect(presented.membership?.role).toBe('member');
|
||||
});
|
||||
|
||||
it('should return error when repository throws', async () => {
|
||||
@@ -126,6 +121,5 @@ describe('GetTeamMembershipUseCase', () => {
|
||||
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
export type GetTeamMembershipInput = {
|
||||
teamId: string;
|
||||
driverId: string;
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
GetTeamsLeaderboardUseCase,
|
||||
type GetTeamsLeaderboardResult,
|
||||
type GetTeamsLeaderboardInput,
|
||||
type GetTeamsLeaderboardErrorCode,
|
||||
} from './GetTeamsLeaderboardUseCase';
|
||||
import { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import {
|
||||
GetTeamsLeaderboardUseCase,
|
||||
type GetTeamsLeaderboardErrorCode,
|
||||
type GetTeamsLeaderboardInput
|
||||
} from './GetTeamsLeaderboardUseCase';
|
||||
|
||||
describe('GetTeamsLeaderboardUseCase', () => {
|
||||
let useCase: GetTeamsLeaderboardUseCase;
|
||||
@@ -26,6 +22,7 @@ describe('GetTeamsLeaderboardUseCase', () => {
|
||||
warn: Mock;
|
||||
error: Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
teamRepository = {
|
||||
findAll: vi.fn(),
|
||||
@@ -40,11 +37,10 @@ describe('GetTeamsLeaderboardUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
useCase = new GetTeamsLeaderboardUseCase(teamRepository as unknown as ITeamRepository,
|
||||
teamMembershipRepository as unknown as ITeamMembershipRepository,
|
||||
getDriverStats as unknown as (driverId: string) => { rating: number | null; wins: number; totalRaces: number } | null,
|
||||
logger as unknown as Logger,
|
||||
output,
|
||||
useCase = new GetTeamsLeaderboardUseCase(teamRepository as any,
|
||||
teamMembershipRepository as any,
|
||||
getDriverStats as any,
|
||||
logger as any
|
||||
);
|
||||
});
|
||||
|
||||
@@ -91,10 +87,7 @@ describe('GetTeamsLeaderboardUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = (expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as GetTeamsLeaderboardResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.recruitingCount).toBe(2); // both teams are recruiting
|
||||
expect(presented.items).toHaveLength(2);
|
||||
@@ -134,5 +127,5 @@ describe('GetTeamsLeaderboardUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('Repository error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { TeamRepository } from '@core/racing/domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '@core/racing/domain/repositories/TeamMembershipRepository';
|
||||
import { Team } from '@/racing/domain/entities/Team';
|
||||
import { SkillLevelService, type SkillLevel } from '@core/racing/domain/services/SkillLevelService';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Team } from '@core/racing/domain/entities/Team';
|
||||
|
||||
interface DriverStatsAdapter {
|
||||
rating: number | null;
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('GetTotalLeaguesUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
expect(result.unwrap()).toEqual({ totalLeagues: 3 });
|
||||
});
|
||||
|
||||
it('should return error on repository failure', async () => {
|
||||
|
||||
@@ -46,9 +46,7 @@ describe('GetTotalRacesUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const payloadRaw = expect(payloadRaw).toBeDefined();
|
||||
const payload = payloadRaw as GetTotalRacesResult;
|
||||
const payload = result.unwrap();
|
||||
expect(payload.totalRaces).toBe(2);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
ImportRaceResultsApiUseCase,
|
||||
type ImportRaceResultsApiInput,
|
||||
type ImportRaceResultsApiResult,
|
||||
type ImportRaceResultsApiErrorCode,
|
||||
} from './ImportRaceResultsApiUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
ImportRaceResultsApiUseCase,
|
||||
type ImportRaceResultsApiErrorCode,
|
||||
type ImportRaceResultsApiInput,
|
||||
type ImportRaceResultsApiResult,
|
||||
} from './ImportRaceResultsApiUseCase';
|
||||
|
||||
describe('ImportRaceResultsApiUseCase', () => {
|
||||
let useCase: ImportRaceResultsApiUseCase;
|
||||
@@ -165,15 +160,12 @@ describe('ImportRaceResultsApiUseCase', () => {
|
||||
standingRepository.recalculate.mockResolvedValue(undefined);
|
||||
|
||||
const result: Result<
|
||||
void,
|
||||
ImportRaceResultsApiResult,
|
||||
ApplicationErrorCode<ImportRaceResultsApiErrorCode, { message: string }>
|
||||
> = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as ImportRaceResultsApiResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented.success).toBe(true);
|
||||
expect(presented.raceId).toBe('race-1');
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import { Result as RaceResult } from '../../domain/entities/result/Result';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { Result as RaceResult } from '../../domain/entities/result/Result';
|
||||
|
||||
export type ImportRaceResultDTO = {
|
||||
id: string;
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
ImportRaceResultsUseCase,
|
||||
type ImportRaceResultsInput,
|
||||
type ImportRaceResultsResult,
|
||||
type ImportRaceResultsErrorCode,
|
||||
} from './ImportRaceResultsUseCase';
|
||||
import { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
ImportRaceResultsUseCase,
|
||||
type ImportRaceResultsErrorCode,
|
||||
type ImportRaceResultsInput
|
||||
} from './ImportRaceResultsUseCase';
|
||||
|
||||
describe('ImportRaceResultsUseCase', () => {
|
||||
let useCase: ImportRaceResultsUseCase;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
|
||||
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
|
||||
import { Result as RaceResult } from '../../domain/entities/result/Result';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { Result as RaceResult } from '../../domain/entities/result/Result';
|
||||
|
||||
export type ImportRaceResultRow = {
|
||||
id: string;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
IsDriverRegisteredForRaceUseCase,
|
||||
type IsDriverRegisteredForRaceInput,
|
||||
type IsDriverRegisteredForRaceErrorCode,
|
||||
type IsDriverRegisteredForRaceResult,
|
||||
} from './IsDriverRegisteredForRaceUseCase';
|
||||
import { RaceRegistrationRepository } from '../../domain/repositories/RaceRegistrationRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
IsDriverRegisteredForRaceUseCase,
|
||||
type IsDriverRegisteredForRaceErrorCode,
|
||||
type IsDriverRegisteredForRaceInput
|
||||
} from './IsDriverRegisteredForRaceUseCase';
|
||||
describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
let useCase: IsDriverRegisteredForRaceUseCase;
|
||||
let registrationRepository: {
|
||||
@@ -29,11 +26,8 @@ describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
useCase = new IsDriverRegisteredForRaceUseCase(registrationRepository as unknown as IRaceRegistrationRepository,
|
||||
logger as unknown as Logger);
|
||||
useCase = new IsDriverRegisteredForRaceUseCase(registrationRepository as any,
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('should return true when driver is registered', async () => {
|
||||
|
||||
@@ -49,9 +49,9 @@ describe('JoinLeagueUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.membership.id).toBe('membership-1');
|
||||
expect(presented.membership.id).toBe('membership-1');
|
||||
expect(presented.membership.leagueId.toString()).toBe('league-1');
|
||||
expect(presented.membership.driverId.toString()).toBe('driver-1');
|
||||
expect(presented.membership.role.toString()).toBe('member');
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { LeagueMembershipRepository } from '@core/racing/domain/repositories/LeagueMembershipRepository';
|
||||
import { LeagueMembership } from '../../domain/entities/LeagueMembership';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { Result } from '@/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { LeagueMembership } from '../../domain/entities/LeagueMembership';
|
||||
|
||||
export type JoinLeagueErrorCode = 'ALREADY_MEMBER' | 'REPOSITORY_ERROR';
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
JoinTeamUseCase,
|
||||
type JoinTeamInput,
|
||||
type JoinTeamResult,
|
||||
type JoinTeamErrorCode,
|
||||
} from './JoinTeamUseCase';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import { Team } from '../../domain/entities/Team';
|
||||
import {
|
||||
JoinTeamUseCase,
|
||||
type JoinTeamErrorCode,
|
||||
type JoinTeamInput
|
||||
} from './JoinTeamUseCase';
|
||||
|
||||
describe('JoinTeamUseCase', () => {
|
||||
let useCase: JoinTeamUseCase;
|
||||
@@ -46,7 +43,14 @@ describe('JoinTeamUseCase', () => {
|
||||
|
||||
it('should successfully join a team', async () => {
|
||||
const input: JoinTeamInput = { teamId: 'team-1', driverId: 'driver-1' };
|
||||
const team = Team.create({ id: 'team-1', name: 'Test Team', ownerId: 'owner-1' });
|
||||
const team = Team.create({
|
||||
id: 'team-1',
|
||||
name: 'Test Team',
|
||||
tag: 'TT',
|
||||
description: 'Test Description',
|
||||
ownerId: 'owner-1',
|
||||
leagues: [],
|
||||
});
|
||||
const membership = {
|
||||
teamId: 'team-1',
|
||||
driverId: 'driver-1',
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { TeamMembership } from '@/racing/domain/types/TeamMembership';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
|
||||
export type JoinTeamErrorCode =
|
||||
| 'ALREADY_IN_TEAM'
|
||||
|
||||
@@ -1,37 +1,31 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import { Season } from '../../domain/entities/season/Season';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
|
||||
import {
|
||||
CreateLeagueSeasonScheduleRaceUseCase,
|
||||
type CreateLeagueSeasonScheduleRaceErrorCode,
|
||||
type CreateLeagueSeasonScheduleRaceResult,
|
||||
CreateLeagueSeasonScheduleRaceUseCase,
|
||||
type CreateLeagueSeasonScheduleRaceErrorCode
|
||||
} from './CreateLeagueSeasonScheduleRaceUseCase';
|
||||
import {
|
||||
UpdateLeagueSeasonScheduleRaceUseCase,
|
||||
type UpdateLeagueSeasonScheduleRaceErrorCode,
|
||||
type UpdateLeagueSeasonScheduleRaceResult,
|
||||
} from './UpdateLeagueSeasonScheduleRaceUseCase';
|
||||
import {
|
||||
DeleteLeagueSeasonScheduleRaceUseCase,
|
||||
type DeleteLeagueSeasonScheduleRaceErrorCode,
|
||||
type DeleteLeagueSeasonScheduleRaceResult,
|
||||
DeleteLeagueSeasonScheduleRaceUseCase,
|
||||
type DeleteLeagueSeasonScheduleRaceErrorCode
|
||||
} from './DeleteLeagueSeasonScheduleRaceUseCase';
|
||||
import {
|
||||
PublishLeagueSeasonScheduleUseCase,
|
||||
type PublishLeagueSeasonScheduleErrorCode,
|
||||
type PublishLeagueSeasonScheduleResult,
|
||||
PublishLeagueSeasonScheduleUseCase,
|
||||
type PublishLeagueSeasonScheduleErrorCode
|
||||
} from './PublishLeagueSeasonScheduleUseCase';
|
||||
import {
|
||||
UnpublishLeagueSeasonScheduleUseCase,
|
||||
type UnpublishLeagueSeasonScheduleErrorCode,
|
||||
type UnpublishLeagueSeasonScheduleResult,
|
||||
UnpublishLeagueSeasonScheduleUseCase,
|
||||
type UnpublishLeagueSeasonScheduleErrorCode
|
||||
} from './UnpublishLeagueSeasonScheduleUseCase';
|
||||
import {
|
||||
UpdateLeagueSeasonScheduleRaceUseCase,
|
||||
type UpdateLeagueSeasonScheduleRaceErrorCode
|
||||
} from './UpdateLeagueSeasonScheduleRaceUseCase';
|
||||
|
||||
function createLogger(): Logger {
|
||||
return {
|
||||
@@ -62,7 +56,6 @@ describe('CreateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
beforeEach(() => {
|
||||
seasonRepository = { findById: vi.fn() };
|
||||
raceRepository = { create: vi.fn() };
|
||||
output = { present: vi.fn() };
|
||||
logger = createLogger();
|
||||
});
|
||||
|
||||
@@ -71,8 +64,8 @@ describe('CreateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
raceRepository.create.mockImplementation(async (race: Race) => race);
|
||||
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger,
|
||||
{ generateRaceId: () => 'race-123' },
|
||||
);
|
||||
@@ -100,8 +93,8 @@ describe('CreateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
const season = createSeasonWithinWindow({ leagueId: 'other-league' });
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger,
|
||||
{ generateRaceId: () => 'race-123' },
|
||||
);
|
||||
@@ -127,8 +120,8 @@ describe('CreateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
const season = createSeasonWithinWindow();
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new CreateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger,
|
||||
{ generateRaceId: () => 'race-123' },
|
||||
);
|
||||
@@ -159,7 +152,6 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
beforeEach(() => {
|
||||
seasonRepository = { findById: vi.fn() };
|
||||
raceRepository = { findById: vi.fn(), update: vi.fn() };
|
||||
output = { present: vi.fn() };
|
||||
logger = createLogger();
|
||||
});
|
||||
|
||||
@@ -177,8 +169,8 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
raceRepository.findById.mockResolvedValue(existing);
|
||||
raceRepository.update.mockImplementation(async (race: Race) => race);
|
||||
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const newScheduledAt = new Date('2025-01-20T20:00:00Z');
|
||||
@@ -193,20 +185,16 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(raceRepository.update).toHaveBeenCalledTimes(1);
|
||||
const updated = raceRepository.update.mock.calls[0]?.[0] as Race;
|
||||
expect(updated.id).toBe('race-1');
|
||||
expect(updated.leagueId).toBe('league-1');
|
||||
expect(updated.track).toBe('New Track');
|
||||
expect(updated.car).toBe('New Car');
|
||||
expect(updated.scheduledAt.getTime()).toBe(newScheduledAt.getTime());
|
||||
const presented = result.unwrap();
|
||||
expect(presented.success).toBe(true);
|
||||
});
|
||||
|
||||
it('returns SEASON_NOT_FOUND when season does not belong to league and does not read/update race', async () => {
|
||||
const season = createSeasonWithinWindow({ leagueId: 'other-league' });
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -224,7 +212,7 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(raceRepository.findById).not.toHaveBeenCalled();
|
||||
expect(raceRepository.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns RACE_OUTSIDE_SEASON_WINDOW when updated scheduledAt is outside window and does not update', async () => {
|
||||
const season = createSeasonWithinWindow();
|
||||
@@ -239,8 +227,8 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
});
|
||||
raceRepository.findById.mockResolvedValue(existing);
|
||||
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -257,15 +245,15 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('RACE_OUTSIDE_SEASON_WINDOW');
|
||||
expect(raceRepository.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns RACE_NOT_FOUND when race does not exist for league and does not update', async () => {
|
||||
const season = createSeasonWithinWindow();
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
raceRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -282,7 +270,7 @@ describe('UpdateLeagueSeasonScheduleRaceUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('RACE_NOT_FOUND');
|
||||
expect(raceRepository.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
@@ -293,7 +281,6 @@ describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
beforeEach(() => {
|
||||
seasonRepository = { findById: vi.fn() };
|
||||
raceRepository = { findById: vi.fn(), delete: vi.fn() };
|
||||
output = { present: vi.fn() };
|
||||
logger = createLogger();
|
||||
});
|
||||
|
||||
@@ -311,8 +298,8 @@ describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
raceRepository.findById.mockResolvedValue(existing);
|
||||
raceRepository.delete.mockResolvedValue(undefined);
|
||||
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -330,8 +317,8 @@ describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
const season = createSeasonWithinWindow({ leagueId: 'other-league' });
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -348,15 +335,15 @@ describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(raceRepository.findById).not.toHaveBeenCalled();
|
||||
expect(raceRepository.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns RACE_NOT_FOUND when race does not exist for league and does not delete', async () => {
|
||||
const season = createSeasonWithinWindow();
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
raceRepository.findById.mockResolvedValue(null);
|
||||
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
const useCase = new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepository as any,
|
||||
raceRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({
|
||||
@@ -372,7 +359,7 @@ describe('DeleteLeagueSeasonScheduleRaceUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('RACE_NOT_FOUND');
|
||||
expect(raceRepository.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PublishLeagueSeasonScheduleUseCase', () => {
|
||||
@@ -381,7 +368,6 @@ describe('PublishLeagueSeasonScheduleUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
seasonRepository = { findById: vi.fn(), update: vi.fn() };
|
||||
output = { present: vi.fn() };
|
||||
logger = createLogger();
|
||||
});
|
||||
|
||||
@@ -390,24 +376,23 @@ describe('PublishLeagueSeasonScheduleUseCase', () => {
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
seasonRepository.update.mockResolvedValue(undefined);
|
||||
|
||||
const useCase = new PublishLeagueSeasonScheduleUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
const useCase = new PublishLeagueSeasonScheduleUseCase(seasonRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({ leagueId: 'league-1', seasonId: 'season-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(seasonRepository.update).toHaveBeenCalledTimes(1);
|
||||
const updatedSeason = seasonRepository.update.mock.calls[0]?.[0] as Season;
|
||||
expect(updatedSeason.id).toBe('season-1');
|
||||
expect(updatedSeason.leagueId).toBe('league-1');
|
||||
expect(updatedSeason.schedulePublished).toBe(true);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.seasonId).toBe('season-1');
|
||||
expect(presented.published).toBe(true);
|
||||
});
|
||||
|
||||
it('returns SEASON_NOT_FOUND when season does not belong to league and does not update', async () => {
|
||||
const season = createSeasonWithinWindow({ leagueId: 'other-league' });
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new PublishLeagueSeasonScheduleUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
const useCase = new PublishLeagueSeasonScheduleUseCase(seasonRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({ leagueId: 'league-1', seasonId: 'season-1' });
|
||||
@@ -419,7 +404,7 @@ describe('PublishLeagueSeasonScheduleUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(seasonRepository.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('UnpublishLeagueSeasonScheduleUseCase', () => {
|
||||
@@ -428,7 +413,6 @@ describe('UnpublishLeagueSeasonScheduleUseCase', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
seasonRepository = { findById: vi.fn(), update: vi.fn() };
|
||||
output = { present: vi.fn() };
|
||||
logger = createLogger();
|
||||
});
|
||||
|
||||
@@ -437,24 +421,23 @@ describe('UnpublishLeagueSeasonScheduleUseCase', () => {
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
seasonRepository.update.mockResolvedValue(undefined);
|
||||
|
||||
const useCase = new UnpublishLeagueSeasonScheduleUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
const useCase = new UnpublishLeagueSeasonScheduleUseCase(seasonRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({ leagueId: 'league-1', seasonId: 'season-1' });
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(seasonRepository.update).toHaveBeenCalledTimes(1);
|
||||
const updatedSeason = seasonRepository.update.mock.calls[0]?.[0] as Season;
|
||||
expect(updatedSeason.id).toBe('season-1');
|
||||
expect(updatedSeason.leagueId).toBe('league-1');
|
||||
expect(updatedSeason.schedulePublished).toBe(false);
|
||||
const presented = result.unwrap();
|
||||
expect(presented.seasonId).toBe('season-1');
|
||||
expect(presented.published).toBe(false);
|
||||
});
|
||||
|
||||
it('returns SEASON_NOT_FOUND when season does not belong to league and does not update', async () => {
|
||||
const season = createSeasonWithinWindow({ leagueId: 'other-league' });
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
const useCase = new UnpublishLeagueSeasonScheduleUseCase(seasonRepository as unknown as ISeasonRepository,
|
||||
const useCase = new UnpublishLeagueSeasonScheduleUseCase(seasonRepository as any,
|
||||
logger);
|
||||
|
||||
const result = await useCase.execute({ leagueId: 'league-1', seasonId: 'season-1' });
|
||||
@@ -466,5 +449,5 @@ describe('UnpublishLeagueSeasonScheduleUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
expect(seasonRepository.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,9 +53,9 @@ describe('LeaveTeamUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
const presented = expect(presented.team.id).toBe('team-1');
|
||||
expect(presented.team.id).toBe('team-1');
|
||||
expect(presented.previousMembership).toEqual(membership);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { TeamMembership } from '@/racing/domain/types/TeamMembership';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
import type { TeamMembership } from '../../domain/types/TeamMembership';
|
||||
|
||||
export type LeaveTeamErrorCode =
|
||||
| 'TEAM_NOT_FOUND'
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from './ListLeagueScoringPresetsUseCase';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Result } from '@core/shared/domain/Result';
|
||||
|
||||
|
||||
describe('ListLeagueScoringPresetsUseCase', () => {
|
||||
let useCase: ListLeagueScoringPresetsUseCase;
|
||||
beforeEach(() => {
|
||||
@@ -47,21 +47,17 @@ describe('ListLeagueScoringPresetsUseCase', () => {
|
||||
createConfig: vi.fn(),
|
||||
},
|
||||
];
|
||||
|
||||
useCase = new ListLeagueScoringPresetsUseCase(mockPresets);
|
||||
|
||||
useCase = new ListLeagueScoringPresetsUseCase(mockPresets as any);
|
||||
});
|
||||
|
||||
|
||||
it('should list presets successfully', async () => {
|
||||
const input: ListLeagueScoringPresetsInput = {};
|
||||
|
||||
const result: Result<
|
||||
void,
|
||||
ApplicationErrorCode<ListLeagueScoringPresetsErrorCode, { message: string }>
|
||||
> = await useCase.execute(input);
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const firstCall = const presented = firstCall[0] as ListLeagueScoringPresetsResult;
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented).toEqual({
|
||||
presets: [
|
||||
@@ -101,21 +97,18 @@ describe('ListLeagueScoringPresetsUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap repository errors in ApplicationErrorCode and not call output', async () => {
|
||||
it('should return repository error when mapping fails', async () => {
|
||||
const failingPresets = {
|
||||
map: () => {
|
||||
throw new Error('Repository failure');
|
||||
},
|
||||
} as unknown as never[];
|
||||
} as any;
|
||||
|
||||
useCase = new ListLeagueScoringPresetsUseCase(failingPresets);
|
||||
|
||||
const input: ListLeagueScoringPresetsInput = {};
|
||||
|
||||
const result: Result<
|
||||
void,
|
||||
ApplicationErrorCode<ListLeagueScoringPresetsErrorCode, { message: string }>
|
||||
> = await useCase.execute(input);
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
|
||||
@@ -126,5 +119,5 @@ describe('ListLeagueScoringPresetsUseCase', () => {
|
||||
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details?.message).toBe('Repository failure');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,8 +19,7 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
findById: Mock;
|
||||
update: Mock;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = {
|
||||
findById: vi.fn(),
|
||||
@@ -29,11 +28,10 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
findById: vi.fn(),
|
||||
update: vi.fn(),
|
||||
};
|
||||
};
|
||||
useCase = new ManageSeasonLifecycleUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
seasonRepository as unknown as ISeasonRepository);
|
||||
useCase = new ManageSeasonLifecycleUseCase(leagueRepository as any,
|
||||
seasonRepository as any);
|
||||
});
|
||||
|
||||
|
||||
it('applies activate → complete → archive transitions and persists state', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
let currentSeason = Season.create({
|
||||
@@ -43,57 +41,48 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
name: 'Lifecycle Season',
|
||||
status: 'planned',
|
||||
});
|
||||
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockImplementation(() => Promise.resolve(currentSeason));
|
||||
seasonRepository.update.mockImplementation((s) => {
|
||||
currentSeason = s;
|
||||
return Promise.resolve(s);
|
||||
});
|
||||
|
||||
|
||||
const activateInput: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: currentSeason.id,
|
||||
transition: 'activate',
|
||||
};
|
||||
|
||||
|
||||
const activated = await useCase.execute(activateInput);
|
||||
expect(activated.isOk()).toBe(true);
|
||||
expect(activated.unwrap()).toBeUndefined();
|
||||
const [firstCall] = const [firstArg] = firstCall as [ManageSeasonLifecycleResult];
|
||||
let presented = firstArg;
|
||||
let presented = activated.unwrap();
|
||||
expect(presented.season.status.toString()).toBe('active');
|
||||
|
||||
(const completeInput: ManageSeasonLifecycleInput = {
|
||||
|
||||
const completeInput: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: currentSeason.id,
|
||||
transition: 'complete',
|
||||
};
|
||||
|
||||
|
||||
const completed = await useCase.execute(completeInput);
|
||||
expect(completed.isOk()).toBe(true);
|
||||
expect(completed.unwrap()).toBeUndefined();
|
||||
{
|
||||
const [[arg]] = presented = arg;
|
||||
}
|
||||
presented = completed.unwrap();
|
||||
expect(presented.season.status.toString()).toBe('completed');
|
||||
|
||||
(const archiveInput: ManageSeasonLifecycleInput = {
|
||||
|
||||
const archiveInput: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: currentSeason.id,
|
||||
transition: 'archive',
|
||||
};
|
||||
|
||||
|
||||
const archived = await useCase.execute(archiveInput);
|
||||
expect(archived.isOk()).toBe(true);
|
||||
expect(archived.unwrap()).toBeUndefined();
|
||||
{
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
presented = presentedRaw as ManageSeasonLifecycleResult;
|
||||
}
|
||||
presented = archived.unwrap();
|
||||
expect(presented.season.status.toString()).toBe('archived');
|
||||
});
|
||||
|
||||
|
||||
it('propagates domain invariant errors for invalid transitions', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
const season = Season.create({
|
||||
@@ -103,16 +92,16 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
name: 'Lifecycle Season',
|
||||
status: 'planned',
|
||||
});
|
||||
|
||||
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockResolvedValue(season);
|
||||
|
||||
|
||||
const completeInput: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: season.id,
|
||||
transition: 'complete',
|
||||
};
|
||||
|
||||
|
||||
const result = await useCase.execute(completeInput);
|
||||
expect(result.isErr()).toBe(true);
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<
|
||||
@@ -120,17 +109,17 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
{ message: string }
|
||||
>;
|
||||
expect(error.code).toEqual('INVALID_TRANSITION');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('returns error when league not found', async () => {
|
||||
leagueRepository.findById.mockResolvedValue(null);
|
||||
|
||||
|
||||
const input: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
transition: 'activate',
|
||||
};
|
||||
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
expect(result.isErr()).toBe(true);
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<
|
||||
@@ -139,19 +128,19 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toEqual('LEAGUE_NOT_FOUND');
|
||||
expect(error.details).toEqual({ message: 'League not found: league-1' });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('returns error when season not found', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
leagueRepository.findById.mockResolvedValue(league);
|
||||
seasonRepository.findById.mockResolvedValue(null);
|
||||
|
||||
|
||||
const input: ManageSeasonLifecycleInput = {
|
||||
leagueId: 'league-1',
|
||||
seasonId: 'season-1',
|
||||
transition: 'activate',
|
||||
};
|
||||
|
||||
|
||||
const result = await useCase.execute(input);
|
||||
expect(result.isErr()).toBe(true);
|
||||
const error = result.unwrapErr() as ApplicationErrorCode<
|
||||
@@ -162,5 +151,5 @@ describe('ManageSeasonLifecycleUseCase', () => {
|
||||
expect(error.details).toEqual({
|
||||
message: 'Season season-1 does not belong to league league-1',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import {
|
||||
PreviewLeagueScheduleUseCase,
|
||||
type PreviewLeagueScheduleResult,
|
||||
type PreviewLeagueScheduleInput,
|
||||
type PreviewLeagueScheduleErrorCode,
|
||||
} from './PreviewLeagueScheduleUseCase';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
PreviewLeagueScheduleUseCase,
|
||||
type PreviewLeagueScheduleErrorCode,
|
||||
type PreviewLeagueScheduleInput
|
||||
} from './PreviewLeagueScheduleUseCase';
|
||||
|
||||
describe('PreviewLeagueScheduleUseCase', () => {
|
||||
let useCase: PreviewLeagueScheduleUseCase;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { SeasonScheduleGenerator } from '../../domain/services/SeasonScheduleGenerator';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { SeasonSchedule } from '../../domain/value-objects/SeasonSchedule';
|
||||
import { RaceTimeOfDay } from '../../domain/value-objects/RaceTimeOfDay';
|
||||
import { LeagueTimezone } from '../../domain/value-objects/LeagueTimezone';
|
||||
import { RecurrenceStrategyFactory } from '../../domain/value-objects/RecurrenceStrategy';
|
||||
import { WeekdaySet } from '../../domain/value-objects/WeekdaySet';
|
||||
import { MonthlyRecurrencePattern } from '../../domain/value-objects/MonthlyRecurrencePattern';
|
||||
import { SeasonScheduleGenerator } from '../../domain/services/SeasonScheduleGenerator';
|
||||
import { ALL_WEEKDAYS, type Weekday } from '../../domain/types/Weekday';
|
||||
import { LeagueTimezone } from '../../domain/value-objects/LeagueTimezone';
|
||||
import { MonthlyRecurrencePattern } from '../../domain/value-objects/MonthlyRecurrencePattern';
|
||||
import { RaceTimeOfDay } from '../../domain/value-objects/RaceTimeOfDay';
|
||||
import { RecurrenceStrategyFactory } from '../../domain/value-objects/RecurrenceStrategy';
|
||||
import { SeasonSchedule } from '../../domain/value-objects/SeasonSchedule';
|
||||
import { WeekdaySet } from '../../domain/value-objects/WeekdaySet';
|
||||
export type SeasonScheduleConfig = {
|
||||
seasonStartDate: string;
|
||||
recurrenceStrategy: 'weekly' | 'everyNWeeks' | 'monthlyNthWeekday';
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
|
||||
export type PublishLeagueSeasonScheduleInput = {
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
};
|
||||
|
||||
export type PublishLeagueSeasonScheduleResult = {
|
||||
success: true;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { QuickPenaltyUseCase, type QuickPenaltyInput, type QuickPenaltyResult, type QuickPenaltyErrorCode } from './QuickPenaltyUseCase';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import { QuickPenaltyUseCase, type QuickPenaltyErrorCode, type QuickPenaltyInput } from './QuickPenaltyUseCase';
|
||||
|
||||
describe('QuickPenaltyUseCase', () => {
|
||||
let useCase: QuickPenaltyUseCase;
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
* Designed for fast, common penalty scenarios like track limits, warnings, etc.
|
||||
*/
|
||||
|
||||
import { Penalty } from '../../domain/entities/penalty/Penalty';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import { randomUUID } from 'crypto';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import { Result } from '@/shared/domain/Result';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { Penalty } from '../../domain/entities/penalty/Penalty';
|
||||
|
||||
export type QuickPenaltyErrorCode = 'RACE_NOT_FOUND' | 'UNAUTHORIZED' | 'UNKNOWN_INFRACTION' | 'REPOSITORY_ERROR';
|
||||
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
RecalculateChampionshipStandingsUseCase,
|
||||
type RecalculateChampionshipStandingsInput,
|
||||
type RecalculateChampionshipStandingsResult,
|
||||
type RecalculateChampionshipStandingsErrorCode,
|
||||
} from './RecalculateChampionshipStandingsUseCase';
|
||||
import type { SeasonRepository } from '../../domain/repositories/SeasonRepository';
|
||||
import type { LeagueScoringConfigRepository } from '../../domain/repositories/LeagueScoringConfigRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
|
||||
import type { PenaltyRepository } from '../../domain/repositories/PenaltyRepository';
|
||||
import type { ChampionshipStandingRepository } from '../../domain/repositories/ChampionshipStandingRepository';
|
||||
import type { Penalty } from '../../domain/entities/Penalty';
|
||||
import { EventScoringService } from '../../domain/services/EventScoringService';
|
||||
import type { LeagueRepository } from '../../domain/repositories/LeagueRepository';
|
||||
import { ChampionshipAggregator } from '../../domain/services/ChampionshipAggregator';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import type { Penalty } from '../../domain/entities/Penalty';
|
||||
import {
|
||||
RecalculateChampionshipStandingsUseCase,
|
||||
type RecalculateChampionshipStandingsErrorCode,
|
||||
type RecalculateChampionshipStandingsInput
|
||||
} from './RecalculateChampionshipStandingsUseCase';
|
||||
|
||||
describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
let useCase: RecalculateChampionshipStandingsUseCase;
|
||||
@@ -30,7 +20,6 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
let eventScoringService: { scoreSession: Mock };
|
||||
let championshipAggregator: { aggregate: Mock };
|
||||
let logger: Logger;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
leagueRepository = { findById: vi.fn() };
|
||||
@@ -47,18 +36,17 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = { present: vi.fn() } as unknown as typeof output;
|
||||
} as any;
|
||||
|
||||
useCase = new RecalculateChampionshipStandingsUseCase(leagueRepository as unknown as ILeagueRepository,
|
||||
seasonRepository as unknown as ISeasonRepository,
|
||||
leagueScoringConfigRepository as unknown as ILeagueScoringConfigRepository,
|
||||
raceRepository as unknown as IRaceRepository,
|
||||
resultRepository as unknown as IResultRepository,
|
||||
penaltyRepository as unknown as IPenaltyRepository,
|
||||
championshipStandingRepository as unknown as IChampionshipStandingRepository,
|
||||
eventScoringService as unknown as EventScoringService,
|
||||
championshipAggregator as unknown as ChampionshipAggregator,
|
||||
useCase = new RecalculateChampionshipStandingsUseCase(leagueRepository as any,
|
||||
seasonRepository as any,
|
||||
leagueScoringConfigRepository as any,
|
||||
raceRepository as any,
|
||||
resultRepository as any,
|
||||
penaltyRepository as any,
|
||||
championshipStandingRepository as any,
|
||||
eventScoringService as any,
|
||||
championshipAggregator as any,
|
||||
logger);
|
||||
});
|
||||
|
||||
@@ -79,7 +67,7 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('LEAGUE_NOT_FOUND');
|
||||
expect(error.details.message).toContain('league-1');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns season not found error when season does not exist', async () => {
|
||||
leagueRepository.findById.mockResolvedValue({ id: 'league-1' });
|
||||
@@ -98,7 +86,7 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
{ message: string }
|
||||
>;
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns season not found error when season belongs to different league', async () => {
|
||||
leagueRepository.findById.mockResolvedValue({ id: 'league-1' });
|
||||
@@ -117,9 +105,9 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
{ message: string }
|
||||
>;
|
||||
expect(error.code).toBe('SEASON_NOT_FOUND');
|
||||
});
|
||||
});
|
||||
|
||||
it('recalculates standings successfully and presents result', async () => {
|
||||
it('recalculates standings successfully and returns result', async () => {
|
||||
const league = { id: 'league-1' };
|
||||
const season = { id: 'season-1', leagueId: 'league-1' };
|
||||
const championship = {
|
||||
@@ -161,9 +149,7 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as RecalculateChampionshipStandingsResult;
|
||||
const presented = result.unwrap();
|
||||
expect(presented.leagueId).toBe('league-1');
|
||||
expect(presented.seasonId).toBe('season-1');
|
||||
expect(presented.entries).toHaveLength(1);
|
||||
@@ -175,7 +161,7 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('wraps repository failures in REPOSITORY_ERROR and does not call output', async () => {
|
||||
it('wraps repository failures in REPOSITORY_ERROR', async () => {
|
||||
leagueRepository.findById.mockResolvedValue({ id: 'league-1' });
|
||||
seasonRepository.findById.mockResolvedValue({ id: 'season-1', leagueId: 'league-1' });
|
||||
leagueScoringConfigRepository.findBySeasonId.mockImplementation(() => {
|
||||
@@ -196,5 +182,5 @@ describe('RecalculateChampionshipStandingsUseCase', () => {
|
||||
>;
|
||||
expect(error.code).toBe('REPOSITORY_ERROR');
|
||||
expect(error.details.message).toContain('boom');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import type { SeasonRepository } from '@core/racing/domain/repositories/SeasonRepository';
|
||||
import type { LeagueScoringConfigRepository } from '@core/racing/domain/repositories/LeagueScoringConfigRepository';
|
||||
import type { RaceRepository } from '@core/racing/domain/repositories/RaceRepository';
|
||||
import type { ResultRepository } from '@core/racing/domain/repositories/ResultRepository';
|
||||
import type { PenaltyRepository } from '@core/racing/domain/repositories/PenaltyRepository';
|
||||
import type { ChampionshipStandingRepository } from '@core/racing/domain/repositories/ChampionshipStandingRepository';
|
||||
import type { LeagueRepository } from '@core/racing/domain/repositories/LeagueRepository';
|
||||
|
||||
import { ChampionshipStanding } from '@/racing/domain/entities/championship/ChampionshipStanding';
|
||||
import { ChampionshipAggregator } from '@core/racing/domain/services/ChampionshipAggregator';
|
||||
import { EventScoringService } from '@core/racing/domain/services/EventScoringService';
|
||||
import type { ChampionshipConfig } from '@core/racing/domain/types/ChampionshipConfig';
|
||||
import type { SessionType } from '@core/racing/domain/types/SessionType';
|
||||
import type { ChampionshipStanding } from '@core/racing/domain/entities/championship/ChampionshipStanding';
|
||||
import { EventScoringService } from '@core/racing/domain/services/EventScoringService';
|
||||
import { ChampionshipAggregator } from '@core/racing/domain/services/ChampionshipAggregator';
|
||||
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
export type RecalculateChampionshipStandingsInput = {
|
||||
leagueId: string;
|
||||
@@ -132,7 +125,7 @@ export class RecalculateChampionshipStandingsUseCase {
|
||||
})),
|
||||
};
|
||||
|
||||
return Result.ok(undefined);
|
||||
return Result.ok(result);
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
this.logger.error('Failed to recalculate championship standings', err, {
|
||||
|
||||
@@ -86,15 +86,13 @@ describe('RegisterForRaceUseCase', () => {
|
||||
const result = await useCase.execute(buildInput());
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as RegisterForRaceResult;
|
||||
const presented = result.unwrap();
|
||||
expect(presented).toEqual<RegisterForRaceResult>({
|
||||
raceId: 'race-1',
|
||||
driverId: 'driver-1',
|
||||
status: 'registered',
|
||||
});
|
||||
expect(registrationRepository.register).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('wraps unexpected repository errors', async () => {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
RejectSponsorshipRequestUseCase,
|
||||
type RejectSponsorshipRequestInput,
|
||||
type RejectSponsorshipRequestResult,
|
||||
type RejectSponsorshipRequestErrorCode,
|
||||
RejectSponsorshipRequestUseCase,
|
||||
type RejectSponsorshipRequestErrorCode,
|
||||
type RejectSponsorshipRequestInput,
|
||||
type RejectSponsorshipRequestResult,
|
||||
} from './RejectSponsorshipRequestUseCase';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
|
||||
describe('RejectSponsorshipRequestUseCase', () => {
|
||||
let useCase: RejectSponsorshipRequestUseCase;
|
||||
|
||||
@@ -4,16 +4,10 @@
|
||||
* Allows an entity owner to reject a sponsorship request.
|
||||
*/
|
||||
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { SponsorshipRequestRepository } from '../../domain/repositories/SponsorshipRequestRepository';
|
||||
|
||||
export type RejectSponsorshipRequestInput = {
|
||||
requestId: string;
|
||||
respondedBy: string;
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
export type RejectSponsorshipRequestResult = {
|
||||
requestId: string;
|
||||
|
||||
@@ -78,8 +78,8 @@ describe('RejectTeamJoinRequestUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = expect(presented.teamId).toBe('team-1');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.teamId).toBe('team-1');
|
||||
expect(presented.requestId).toBe('req-1');
|
||||
expect(presented.status).toBe('rejected');
|
||||
expect(membershipRepository.removeJoinRequest).toHaveBeenCalledWith('req-1');
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { Logger } from '@core/shared/domain/Logger';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
|
||||
import type { TeamRepository } from '../../domain/repositories/TeamRepository';
|
||||
|
||||
export type RejectTeamJoinRequestInput = {
|
||||
teamId: string;
|
||||
managerId: string;
|
||||
requestId: string;
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
export type RejectTeamJoinRequestResult = {
|
||||
teamId: string;
|
||||
|
||||
@@ -40,8 +40,9 @@ describe('RemoveLeagueMemberUseCase', () => {
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const removeResult = result.unwrap();
|
||||
expect(removeResult.success).toBe(true);
|
||||
expect(removeResult.message).toBeDefined();
|
||||
expect(removeResult.leagueId).toBe(leagueId);
|
||||
expect(removeResult.memberId).toBe(targetDriverId);
|
||||
expect(removeResult.removedRole).toBe('member');
|
||||
|
||||
expect(leagueMembershipRepository.saveMembership).toHaveBeenCalledTimes(1);
|
||||
const savedMembership = leagueMembershipRepository.saveMembership.mock.calls[0]?.[0];
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
ReopenRaceUseCase,
|
||||
type ReopenRaceInput,
|
||||
type ReopenRaceResult,
|
||||
type ReopenRaceErrorCode,
|
||||
} from './ReopenRaceUseCase';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Race } from '../../domain/entities/Race';
|
||||
import { SessionType } from '../../domain/value-objects/SessionType';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import {
|
||||
ReopenRaceUseCase,
|
||||
type ReopenRaceErrorCode,
|
||||
type ReopenRaceInput
|
||||
} from './ReopenRaceUseCase';
|
||||
|
||||
describe('ReopenRaceUseCase', () => {
|
||||
let raceRepository: {
|
||||
@@ -37,8 +34,8 @@ describe('ReopenRaceUseCase', () => {
|
||||
error: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new ReopenRaceUseCase(raceRepository as unknown as IRaceRepository,
|
||||
logger as unknown as Logger);
|
||||
useCase = new ReopenRaceUseCase(raceRepository as any,
|
||||
logger as any);
|
||||
});
|
||||
|
||||
it('returns RACE_NOT_FOUND when race does not exist', async () => {
|
||||
@@ -55,9 +52,9 @@ describe('ReopenRaceUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('RACE_NOT_FOUND');
|
||||
expect(err.details.message).toContain('race-404');
|
||||
});
|
||||
});
|
||||
|
||||
it('reopens a completed race, persists, and presents the result', async () => {
|
||||
it('reopens a completed race, persists, and returns the result', async () => {
|
||||
const race = Race.create({
|
||||
id: 'race-1',
|
||||
leagueId: 'league-1',
|
||||
@@ -81,7 +78,8 @@ describe('ReopenRaceUseCase', () => {
|
||||
expect(updatedRace.id).toBe('race-1');
|
||||
expect(updatedRace.status.toString()).toBe('scheduled');
|
||||
|
||||
const presented = (expect(presented.race.id).toBe('race-1');
|
||||
const presented = result.unwrap();
|
||||
expect(presented.race.id).toBe('race-1');
|
||||
expect(presented.race.status.toString()).toBe('scheduled');
|
||||
|
||||
expect(logger.info).toHaveBeenCalled();
|
||||
@@ -110,7 +108,7 @@ describe('ReopenRaceUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('INVALID_RACE_STATE');
|
||||
expect(err.details.message).toContain('already scheduled');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns INVALID_RACE_STATE when race is running', async () => {
|
||||
const race = Race.create({
|
||||
@@ -135,7 +133,7 @@ describe('ReopenRaceUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('INVALID_RACE_STATE');
|
||||
expect(err.details.message).toContain('running race');
|
||||
});
|
||||
});
|
||||
|
||||
it('returns REPOSITORY_ERROR when repository throws unexpected error', async () => {
|
||||
raceRepository.findById.mockRejectedValue(new Error('DB error'));
|
||||
@@ -150,5 +148,5 @@ describe('ReopenRaceUseCase', () => {
|
||||
>;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('DB error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { Race } from '../../domain/entities/Race';
|
||||
|
||||
@@ -132,12 +132,10 @@ describe('RequestProtestDefenseUseCase', () => {
|
||||
const result = await useCase.execute(createInput());
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(protestRepository.update).toHaveBeenCalledWith(updatedProtest);
|
||||
|
||||
const presentedRaw = expect(presentedRaw).toBeDefined();
|
||||
const presented = presentedRaw as RequestProtestDefenseResult;
|
||||
expect(presented).toEqual({
|
||||
leagueId: 'league-1',
|
||||
protestId: 'protest-1',
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
* Allows a steward to review a protest and make a decision (uphold or dismiss).
|
||||
*/
|
||||
|
||||
import type { ProtestRepository } from '../../domain/repositories/ProtestRepository';
|
||||
import type { RaceRepository } from '../../domain/repositories/RaceRepository';
|
||||
import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import { Result } from '@core/shared/domain/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user