test apps api
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Get, HttpCode, HttpStatus, InternalServerErrorException, Param, Post, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Get, HttpCode, HttpStatus, InternalServerErrorException, Param, Post, Query, Inject } from '@nestjs/common';
|
||||
import { ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { RaceService } from './RaceService';
|
||||
import { AllRacesPageDTO } from './dtos/AllRacesPageDTO';
|
||||
@@ -21,7 +21,7 @@ import { RequestProtestDefenseCommandDTO } from './dtos/RequestProtestDefenseCom
|
||||
@ApiTags('races')
|
||||
@Controller('races')
|
||||
export class RaceController {
|
||||
constructor(private readonly raceService: RaceService) {}
|
||||
constructor(@Inject(RaceService) private readonly raceService: RaceService) {}
|
||||
|
||||
@Get('all')
|
||||
@ApiOperation({ summary: 'Get all races' })
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RaceProviders } from './RaceProviders';
|
||||
|
||||
@Module({
|
||||
controllers: [RaceController],
|
||||
providers: RaceProviders,
|
||||
providers: [RaceService, ...RaceProviders],
|
||||
exports: [RaceService],
|
||||
})
|
||||
export class RaceModule {}
|
||||
|
||||
@@ -90,32 +90,33 @@ import { RaceResultsDetailPresenter } from './presenters/RaceResultsDetailPresen
|
||||
import { RacesPageDataPresenter } from './presenters/RacesPageDataPresenter';
|
||||
import { RaceWithSOFPresenter } from './presenters/RaceWithSOFPresenter';
|
||||
|
||||
// Define injection tokens
|
||||
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
|
||||
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
|
||||
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
|
||||
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
|
||||
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
|
||||
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
|
||||
export const PENALTY_REPOSITORY_TOKEN = 'IPenaltyRepository';
|
||||
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
|
||||
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
|
||||
export const DRIVER_RATING_PROVIDER_TOKEN = 'DriverRatingProvider';
|
||||
export const IMAGE_SERVICE_TOKEN = 'IImageServicePort';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
import {
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
LEAGUE_REPOSITORY_TOKEN,
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
PENALTY_REPOSITORY_TOKEN,
|
||||
PROTEST_REPOSITORY_TOKEN,
|
||||
STANDING_REPOSITORY_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
IMAGE_SERVICE_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
GET_ALL_RACES_PRESENTER_TOKEN,
|
||||
GET_TOTAL_RACES_PRESENTER_TOKEN,
|
||||
IMPORT_RACE_RESULTS_API_PRESENTER_TOKEN,
|
||||
RACE_DETAIL_PRESENTER_TOKEN,
|
||||
RACES_PAGE_DATA_PRESENTER_TOKEN,
|
||||
ALL_RACES_PAGE_DATA_PRESENTER_TOKEN,
|
||||
RACE_RESULTS_DETAIL_PRESENTER_TOKEN,
|
||||
RACE_WITH_SOF_PRESENTER_TOKEN,
|
||||
RACE_PROTESTS_PRESENTER_TOKEN,
|
||||
RACE_PENALTIES_PRESENTER_TOKEN,
|
||||
COMMAND_RESULT_PRESENTER_TOKEN,
|
||||
} from './RaceTokens';
|
||||
|
||||
// Presenter tokens
|
||||
export const GET_ALL_RACES_PRESENTER_TOKEN = 'GetAllRacesPresenter';
|
||||
export const GET_TOTAL_RACES_PRESENTER_TOKEN = 'GetTotalRacesPresenter';
|
||||
export const IMPORT_RACE_RESULTS_API_PRESENTER_TOKEN = 'ImportRaceResultsApiPresenter';
|
||||
export const RACE_DETAIL_PRESENTER_TOKEN = 'RaceDetailPresenter';
|
||||
export const RACES_PAGE_DATA_PRESENTER_TOKEN = 'RacesPageDataPresenter';
|
||||
export const ALL_RACES_PAGE_DATA_PRESENTER_TOKEN = 'AllRacesPageDataPresenter';
|
||||
export const RACE_RESULTS_DETAIL_PRESENTER_TOKEN = 'RaceResultsDetailPresenter';
|
||||
export const RACE_WITH_SOF_PRESENTER_TOKEN = 'RaceWithSOFPresenter';
|
||||
export const RACE_PROTESTS_PRESENTER_TOKEN = 'RaceProtestsPresenter';
|
||||
export const RACE_PENALTIES_PRESENTER_TOKEN = 'RacePenaltiesPresenter';
|
||||
export const COMMAND_RESULT_PRESENTER_TOKEN = 'CommandResultPresenter';
|
||||
export * from './RaceTokens';
|
||||
|
||||
// Adapter classes to bridge presenters with UseCaseOutputPort interface
|
||||
class GetAllRacesOutputAdapter implements UseCaseOutputPort<GetAllRacesResult> {
|
||||
@@ -295,7 +296,6 @@ class ReviewProtestOutputAdapter implements UseCaseOutputPort<ReviewProtestResul
|
||||
}
|
||||
|
||||
export const RaceProviders: Provider[] = [
|
||||
RaceService,
|
||||
{
|
||||
provide: RACE_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryRaceRepository(logger),
|
||||
@@ -471,16 +471,15 @@ export const RaceProviders: Provider[] = [
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
presenter: RaceDetailPresenter,
|
||||
) => {
|
||||
const useCase = new GetRaceDetailUseCase(
|
||||
return new GetRaceDetailUseCase(
|
||||
raceRepo,
|
||||
leagueRepo,
|
||||
driverRepo,
|
||||
raceRegRepo,
|
||||
resultRepo,
|
||||
leagueMembershipRepo,
|
||||
new RaceDetailOutputAdapter(presenter),
|
||||
);
|
||||
useCase.setOutput(new RaceDetailOutputAdapter(presenter));
|
||||
return useCase;
|
||||
},
|
||||
inject: [
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
|
||||
138
apps/api/src/domain/race/RaceService.test.ts
Normal file
138
apps/api/src/domain/race/RaceService.test.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { RaceService } from './RaceService';
|
||||
|
||||
describe('RaceService', () => {
|
||||
it('invokes each use case and returns the corresponding presenter', async () => {
|
||||
const mkUseCase = () => ({ execute: vi.fn(async () => {}) });
|
||||
|
||||
const getAllRacesUseCase = mkUseCase();
|
||||
const getTotalRacesUseCase = mkUseCase();
|
||||
const importRaceResultsApiUseCase = mkUseCase();
|
||||
const getRaceDetailUseCase = mkUseCase();
|
||||
const getRacesPageDataUseCase = mkUseCase();
|
||||
const getAllRacesPageDataUseCase = mkUseCase();
|
||||
const getRaceResultsDetailUseCase = mkUseCase();
|
||||
const getRaceWithSOFUseCase = mkUseCase();
|
||||
const getRaceProtestsUseCase = mkUseCase();
|
||||
const getRacePenaltiesUseCase = mkUseCase();
|
||||
const registerForRaceUseCase = mkUseCase();
|
||||
const withdrawFromRaceUseCase = mkUseCase();
|
||||
const cancelRaceUseCase = mkUseCase();
|
||||
const completeRaceUseCase = mkUseCase();
|
||||
const fileProtestUseCase = mkUseCase();
|
||||
const quickPenaltyUseCase = mkUseCase();
|
||||
const applyPenaltyUseCase = mkUseCase();
|
||||
const requestProtestDefenseUseCase = mkUseCase();
|
||||
const reviewProtestUseCase = mkUseCase();
|
||||
const reopenRaceUseCase = mkUseCase();
|
||||
|
||||
const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
||||
|
||||
const getAllRacesPresenter = {} as any;
|
||||
const getTotalRacesPresenter = {} as any;
|
||||
const importRaceResultsApiPresenter = {} as any;
|
||||
const raceDetailPresenter = {} as any;
|
||||
const racesPageDataPresenter = {} as any;
|
||||
const allRacesPageDataPresenter = {} as any;
|
||||
const raceResultsDetailPresenter = {} as any;
|
||||
const raceWithSOFPresenter = {} as any;
|
||||
const raceProtestsPresenter = {} as any;
|
||||
const racePenaltiesPresenter = {} as any;
|
||||
const commandResultPresenter = {} as any;
|
||||
|
||||
const service = new RaceService(
|
||||
getAllRacesUseCase as any,
|
||||
getTotalRacesUseCase as any,
|
||||
importRaceResultsApiUseCase as any,
|
||||
getRaceDetailUseCase as any,
|
||||
getRacesPageDataUseCase as any,
|
||||
getAllRacesPageDataUseCase as any,
|
||||
getRaceResultsDetailUseCase as any,
|
||||
getRaceWithSOFUseCase as any,
|
||||
getRaceProtestsUseCase as any,
|
||||
getRacePenaltiesUseCase as any,
|
||||
registerForRaceUseCase as any,
|
||||
withdrawFromRaceUseCase as any,
|
||||
cancelRaceUseCase as any,
|
||||
completeRaceUseCase as any,
|
||||
fileProtestUseCase as any,
|
||||
quickPenaltyUseCase as any,
|
||||
applyPenaltyUseCase as any,
|
||||
requestProtestDefenseUseCase as any,
|
||||
reviewProtestUseCase as any,
|
||||
reopenRaceUseCase as any,
|
||||
logger as any,
|
||||
getAllRacesPresenter,
|
||||
getTotalRacesPresenter,
|
||||
importRaceResultsApiPresenter,
|
||||
raceDetailPresenter,
|
||||
racesPageDataPresenter,
|
||||
allRacesPageDataPresenter,
|
||||
raceResultsDetailPresenter,
|
||||
raceWithSOFPresenter,
|
||||
raceProtestsPresenter,
|
||||
racePenaltiesPresenter,
|
||||
commandResultPresenter,
|
||||
);
|
||||
|
||||
expect(await service.getAllRaces()).toBe(getAllRacesPresenter);
|
||||
expect(getAllRacesUseCase.execute).toHaveBeenCalledWith({});
|
||||
|
||||
expect(await service.getTotalRaces()).toBe(getTotalRacesPresenter);
|
||||
expect(getTotalRacesUseCase.execute).toHaveBeenCalledWith({});
|
||||
|
||||
expect(await service.importRaceResults({ raceId: 'r1', resultsFileContent: 'x' } as any)).toBe(importRaceResultsApiPresenter);
|
||||
expect(importRaceResultsApiUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', resultsFileContent: 'x' });
|
||||
|
||||
expect(await service.getRaceDetail({ raceId: 'r1' } as any)).toBe(raceDetailPresenter);
|
||||
expect(getRaceDetailUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.getRacesPageData('l1')).toBe(racesPageDataPresenter);
|
||||
expect(getRacesPageDataUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
||||
|
||||
expect(await service.getAllRacesPageData()).toBe(allRacesPageDataPresenter);
|
||||
expect(getAllRacesPageDataUseCase.execute).toHaveBeenCalledWith({});
|
||||
|
||||
expect(await service.getRaceResultsDetail('r1')).toBe(raceResultsDetailPresenter);
|
||||
expect(getRaceResultsDetailUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
|
||||
expect(await service.getRaceWithSOF('r1')).toBe(raceWithSOFPresenter);
|
||||
expect(getRaceWithSOFUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
|
||||
expect(await service.getRaceProtests('r1')).toBe(raceProtestsPresenter);
|
||||
expect(getRaceProtestsUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
|
||||
expect(await service.getRacePenalties('r1')).toBe(racePenaltiesPresenter);
|
||||
expect(getRacePenaltiesUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
|
||||
expect(await service.registerForRace({ raceId: 'r1', driverId: 'd1' } as any)).toBe(commandResultPresenter);
|
||||
expect(registerForRaceUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.withdrawFromRace({ raceId: 'r1', driverId: 'd1' } as any)).toBe(commandResultPresenter);
|
||||
expect(withdrawFromRaceUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.cancelRace({ raceId: 'r1' } as any, 'admin')).toBe(commandResultPresenter);
|
||||
expect(cancelRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', cancelledById: 'admin' });
|
||||
|
||||
expect(await service.completeRace({ raceId: 'r1' } as any)).toBe(commandResultPresenter);
|
||||
expect(completeRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
|
||||
expect(await service.reopenRace({ raceId: 'r1' } as any, 'admin')).toBe(commandResultPresenter);
|
||||
expect(reopenRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', reopenedById: 'admin' });
|
||||
|
||||
expect(await service.fileProtest({} as any)).toBe(commandResultPresenter);
|
||||
expect(fileProtestUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.applyQuickPenalty({} as any)).toBe(commandResultPresenter);
|
||||
expect(quickPenaltyUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.applyPenalty({} as any)).toBe(commandResultPresenter);
|
||||
expect(applyPenaltyUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.requestProtestDefense({} as any)).toBe(commandResultPresenter);
|
||||
expect(requestProtestDefenseUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.reviewProtest({} as any)).toBe(commandResultPresenter);
|
||||
expect(reviewProtestUseCase.execute).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -66,7 +66,7 @@ import {
|
||||
RACE_RESULTS_DETAIL_PRESENTER_TOKEN,
|
||||
RACE_WITH_SOF_PRESENTER_TOKEN,
|
||||
RACES_PAGE_DATA_PRESENTER_TOKEN
|
||||
} from './RaceProviders';
|
||||
} from './RaceTokens';
|
||||
|
||||
@Injectable()
|
||||
export class RaceService {
|
||||
|
||||
24
apps/api/src/domain/race/RaceTokens.ts
Normal file
24
apps/api/src/domain/race/RaceTokens.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
|
||||
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
|
||||
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
|
||||
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
|
||||
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
|
||||
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
|
||||
export const PENALTY_REPOSITORY_TOKEN = 'IPenaltyRepository';
|
||||
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
|
||||
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
|
||||
export const DRIVER_RATING_PROVIDER_TOKEN = 'DriverRatingProvider';
|
||||
export const IMAGE_SERVICE_TOKEN = 'IImageServicePort';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
|
||||
export const GET_ALL_RACES_PRESENTER_TOKEN = 'GetAllRacesPresenter';
|
||||
export const GET_TOTAL_RACES_PRESENTER_TOKEN = 'GetTotalRacesPresenter';
|
||||
export const IMPORT_RACE_RESULTS_API_PRESENTER_TOKEN = 'ImportRaceResultsApiPresenter';
|
||||
export const RACE_DETAIL_PRESENTER_TOKEN = 'RaceDetailPresenter';
|
||||
export const RACES_PAGE_DATA_PRESENTER_TOKEN = 'RacesPageDataPresenter';
|
||||
export const ALL_RACES_PAGE_DATA_PRESENTER_TOKEN = 'AllRacesPageDataPresenter';
|
||||
export const RACE_RESULTS_DETAIL_PRESENTER_TOKEN = 'RaceResultsDetailPresenter';
|
||||
export const RACE_WITH_SOF_PRESENTER_TOKEN = 'RaceWithSOFPresenter';
|
||||
export const RACE_PROTESTS_PRESENTER_TOKEN = 'RaceProtestsPresenter';
|
||||
export const RACE_PENALTIES_PRESENTER_TOKEN = 'RacePenaltiesPresenter';
|
||||
export const COMMAND_RESULT_PRESENTER_TOKEN = 'CommandResultPresenter';
|
||||
Reference in New Issue
Block a user