From fdd021a25221564b2a5c91f65b09592a532395d9 Mon Sep 17 00:00:00 2001 From: leonardo dimarchi <62081192+leonardodimarchi@users.noreply.github.com> Date: Mon, 1 Jan 2024 13:51:02 -0300 Subject: [PATCH] feat(password-reset): implementing password reset request method at the controller --- .../password-reset.controller.test.ts | 59 +++++++++++++++++++ .../controllers/password-reset.controller.ts | 38 +++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 src/modules/password-reset/presenter/controllers/password-reset.controller.test.ts diff --git a/src/modules/password-reset/presenter/controllers/password-reset.controller.test.ts b/src/modules/password-reset/presenter/controllers/password-reset.controller.test.ts new file mode 100644 index 0000000..974e746 --- /dev/null +++ b/src/modules/password-reset/presenter/controllers/password-reset.controller.test.ts @@ -0,0 +1,59 @@ +import { RequestPasswordResetUseCase } from '@modules/password-reset/domain/usecases/request/request-password-reset.usecase'; +import { PasswordResetController } from './password-reset.controller'; +import { faker } from '@faker-js/faker'; +import { ExecutePasswordResetUseCase } from '@modules/password-reset/domain/usecases/execute/execute-password-reset.usecase'; +import { ValidatePasswordResetUseCase } from '@modules/password-reset/domain/usecases/validate/validate-password-reset.usecase'; +import { right, left } from '@shared/helpers/either'; +import { DeepMocked, createMock } from 'test/utils/create-mock'; +import { MockPasswordReset } from 'test/factories/password-reset-mock'; +import { UserNotFoundError } from '@modules/user/domain/errors/user-not-found.error'; +import { InternalServerErrorException } from '@nestjs/common'; + +describe('PasswordResetController', () => { + let controller: PasswordResetController; + let requestPasswordResetUseCase: DeepMocked; + let validatePasswordResetUseCase: DeepMocked; + let executePasswordResetUseCase: DeepMocked; + + beforeEach(() => { + requestPasswordResetUseCase = createMock(); + validatePasswordResetUseCase = createMock(); + executePasswordResetUseCase = createMock(); + controller = new PasswordResetController( + requestPasswordResetUseCase, + validatePasswordResetUseCase, + executePasswordResetUseCase, + ); + }); + + describe('request', () => { + it('should have no feedback if the reset was successfully requested', async () => { + requestPasswordResetUseCase.exec.mockResolvedValueOnce( + right({ + createdPasswordReset: MockPasswordReset.createEntity(), + }), + ); + + const result = await controller.request(faker.internet.email()); + + expect(result).toBeUndefined(); + }); + + it('should have no feedback if the user was not found', async () => { + requestPasswordResetUseCase.exec.mockResolvedValueOnce( + left(new UserNotFoundError()), + ); + + const result = await controller.request(faker.internet.email()); + + expect(result).toBeUndefined(); + }); + + it('should throw an internal server exception when receiving an unknown error', async () => { + requestPasswordResetUseCase.exec.mockResolvedValueOnce(left(new Error())); + + const call = async () => await controller.request(faker.internet.email()); + expect(call).rejects.toThrow(InternalServerErrorException); + }); + }); +}); diff --git a/src/modules/password-reset/presenter/controllers/password-reset.controller.ts b/src/modules/password-reset/presenter/controllers/password-reset.controller.ts index 2d79412..5f58246 100644 --- a/src/modules/password-reset/presenter/controllers/password-reset.controller.ts +++ b/src/modules/password-reset/presenter/controllers/password-reset.controller.ts @@ -1,8 +1,40 @@ -import { Controller } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; +import { ExecutePasswordResetUseCase } from '@modules/password-reset/domain/usecases/execute/execute-password-reset.usecase'; +import { RequestPasswordResetUseCase } from '@modules/password-reset/domain/usecases/request/request-password-reset.usecase'; +import { ValidatePasswordResetUseCase } from '@modules/password-reset/domain/usecases/validate/validate-password-reset.usecase'; +import { UserNotFoundError } from '@modules/user/domain/errors/user-not-found.error'; +import { + Controller, + InternalServerErrorException, + Param, + Post, +} from '@nestjs/common'; +import { ApiHeader, ApiOperation, ApiTags } from '@nestjs/swagger'; @ApiTags('Password Resets') @Controller('password-resets') export class PasswordResetController { - constructor() {} + constructor( + private readonly requestPasswordResetUseCase: RequestPasswordResetUseCase, + private readonly validatePasswordResetUseCase: ValidatePasswordResetUseCase, + private readonly executePasswordResetUseCase: ExecutePasswordResetUseCase, + ) {} + + @ApiOperation({ summary: 'Requests a password reset' }) + @ApiHeader({ name: 'Accept-Language', example: 'en', required: false }) + @Post('request/:email') + public async request(@Param('email') email: string): Promise { + const result = await this.requestPasswordResetUseCase.exec({ + email, + }); + + if (result.isRight()) { + return; + } + + if (result.value instanceof UserNotFoundError) { + return; + } + + throw new InternalServerErrorException(); + } }