refactor use cases
This commit is contained in:
@@ -20,17 +20,13 @@ export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
|
||||
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
|
||||
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
export const REVIEW_PROTEST_PRESENTER_TOKEN = 'ReviewProtestPresenter';
|
||||
|
||||
export const ProtestsProviders: Provider[] = [
|
||||
{
|
||||
provide: LOGGER_TOKEN,
|
||||
useClass: ConsoleLogger,
|
||||
},
|
||||
{
|
||||
provide: REVIEW_PROTEST_PRESENTER_TOKEN,
|
||||
useClass: ReviewProtestPresenter,
|
||||
},
|
||||
ReviewProtestPresenter,
|
||||
// Use cases
|
||||
{
|
||||
provide: ReviewProtestUseCase,
|
||||
@@ -39,14 +35,12 @@ export const ProtestsProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
output: ReviewProtestPresenter,
|
||||
) => new ReviewProtestUseCase(protestRepo, raceRepo, leagueMembershipRepo, logger, output),
|
||||
) => new ReviewProtestUseCase(protestRepo, raceRepo, leagueMembershipRepo, logger),
|
||||
inject: [
|
||||
PROTEST_REPOSITORY_TOKEN,
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
REVIEW_PROTEST_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -40,13 +40,15 @@ describe('ProtestsService', () => {
|
||||
|
||||
it('returns DTO with success model on success', async () => {
|
||||
executeMock.mockImplementation(async (command) => {
|
||||
presenter.present({ protestId: command.protestId } as ReviewProtestResult);
|
||||
return Result.ok(undefined);
|
||||
return Result.ok({
|
||||
leagueId: 'league-1',
|
||||
protestId: command.protestId,
|
||||
status: 'upheld',
|
||||
});
|
||||
});
|
||||
|
||||
const dto = await service.reviewProtest(baseCommand);
|
||||
|
||||
expect(presenter.getResponseModel()).not.toBeNull();
|
||||
expect(executeMock).toHaveBeenCalledWith(baseCommand);
|
||||
expect(dto).toEqual<ReviewProtestResponseDTO>({
|
||||
success: true,
|
||||
@@ -63,8 +65,7 @@ describe('ProtestsService', () => {
|
||||
};
|
||||
|
||||
executeMock.mockImplementation(async () => {
|
||||
presenter.presentError(error);
|
||||
return Result.err<void, ReviewProtestApplicationError>(error);
|
||||
return Result.err<ReviewProtestResult, ReviewProtestApplicationError>(error);
|
||||
});
|
||||
|
||||
const dto = await service.reviewProtest(baseCommand);
|
||||
@@ -83,8 +84,7 @@ describe('ProtestsService', () => {
|
||||
};
|
||||
|
||||
executeMock.mockImplementation(async () => {
|
||||
presenter.presentError(error);
|
||||
return Result.err<void, ReviewProtestApplicationError>(error);
|
||||
return Result.err<ReviewProtestResult, ReviewProtestApplicationError>(error);
|
||||
});
|
||||
|
||||
const dto = await service.reviewProtest(baseCommand);
|
||||
@@ -103,8 +103,7 @@ describe('ProtestsService', () => {
|
||||
};
|
||||
|
||||
executeMock.mockImplementation(async () => {
|
||||
presenter.presentError(error);
|
||||
return Result.err<void, ReviewProtestApplicationError>(error);
|
||||
return Result.err<ReviewProtestResult, ReviewProtestApplicationError>(error);
|
||||
});
|
||||
|
||||
const dto = await service.reviewProtest(baseCommand);
|
||||
@@ -124,8 +123,7 @@ describe('ProtestsService', () => {
|
||||
};
|
||||
|
||||
executeMock.mockImplementation(async () => {
|
||||
presenter.presentError(error);
|
||||
return Result.err<void, ReviewProtestApplicationError>(error);
|
||||
return Result.err<ReviewProtestResult, ReviewProtestApplicationError>(error);
|
||||
});
|
||||
|
||||
const dto = await service.reviewProtest(baseCommand);
|
||||
|
||||
@@ -8,14 +8,14 @@ import { ReviewProtestUseCase } from '@core/racing/application/use-cases/ReviewP
|
||||
import { ReviewProtestPresenter, type ReviewProtestResponseDTO } from './presenters/ReviewProtestPresenter';
|
||||
|
||||
// Tokens
|
||||
import { LOGGER_TOKEN, REVIEW_PROTEST_PRESENTER_TOKEN } from './ProtestsProviders';
|
||||
import { LOGGER_TOKEN } from './ProtestsProviders';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ProtestsService {
|
||||
constructor(
|
||||
private readonly reviewProtestUseCase: ReviewProtestUseCase,
|
||||
@Inject(REVIEW_PROTEST_PRESENTER_TOKEN) private readonly reviewProtestPresenter: ReviewProtestPresenter,
|
||||
private readonly reviewProtestPresenter: ReviewProtestPresenter,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
) {}
|
||||
|
||||
@@ -27,14 +27,20 @@ export class ProtestsService {
|
||||
}): Promise<ReviewProtestResponseDTO> {
|
||||
this.logger.debug('[ProtestsService] Reviewing protest:', command);
|
||||
|
||||
// Set the command on the presenter so it can include stewardId and decision in the response
|
||||
this.reviewProtestPresenter.setCommand({
|
||||
const result = await this.reviewProtestUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
const err = result.unwrapErr();
|
||||
this.reviewProtestPresenter.presentError(err);
|
||||
return this.reviewProtestPresenter.responseModel;
|
||||
}
|
||||
|
||||
// Present the result with the additional context
|
||||
this.reviewProtestPresenter.present(result.unwrap(), {
|
||||
stewardId: command.stewardId,
|
||||
decision: command.decision,
|
||||
});
|
||||
|
||||
await this.reviewProtestUseCase.execute(command);
|
||||
|
||||
return this.reviewProtestPresenter.responseModel;
|
||||
}
|
||||
}
|
||||
@@ -12,27 +12,21 @@ export interface ReviewProtestResponseDTO {
|
||||
|
||||
export class ReviewProtestPresenter implements UseCaseOutputPort<ReviewProtestResult> {
|
||||
private model: ReviewProtestResponseDTO | null = null;
|
||||
private command: { stewardId: string; decision: 'uphold' | 'dismiss' } | null = null;
|
||||
|
||||
reset(): void {
|
||||
this.model = null;
|
||||
this.command = null;
|
||||
}
|
||||
|
||||
setCommand(command: { stewardId: string; decision: 'uphold' | 'dismiss' }): void {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
present(result: ReviewProtestResult): void {
|
||||
if (!this.command) {
|
||||
throw new Error('Command must be set before presenting result');
|
||||
present(result: ReviewProtestResult, context?: { stewardId: string; decision: 'uphold' | 'dismiss' }): void {
|
||||
if (!context) {
|
||||
throw new Error('Context must be provided when presenting result');
|
||||
}
|
||||
|
||||
this.model = {
|
||||
success: true,
|
||||
protestId: result.protestId,
|
||||
stewardId: this.command.stewardId,
|
||||
decision: this.command.decision,
|
||||
stewardId: context.stewardId,
|
||||
decision: context.decision,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user