From fd5f517de679a31a9604627db17c6b388cbbdb48 Mon Sep 17 00:00:00 2001 From: juliecoust Date: Thu, 25 Jan 2024 11:48:31 +0100 Subject: [PATCH] TST - convergeance and reset password --- src/domain/entities/auth.ts | 6 +- .../use-cases/auth/reset-password.ts | 4 +- src/domain/use-cases/auth/change-password.ts | 4 +- src/domain/use-cases/auth/reset-password.ts | 8 +- src/presentation/routers/auth-router.ts | 1 + .../repositories/user-repository.test.ts | 4 +- .../auth/reset-password-request.test.ts | 2 +- .../use-cases/auth/reset-password.test.ts | 325 ++++++++++++++++++ .../domain/use-cases/user/create-user.test.ts | 14 +- .../use-cases/user/get-all-users.test.ts | 10 +- .../domain/use-cases/user/update-user.test.ts | 34 +- test/presentation/routes/auth-router.test.ts | 2 +- 12 files changed, 390 insertions(+), 24 deletions(-) create mode 100644 test/domain/use-cases/auth/reset-password.test.ts diff --git a/src/domain/entities/auth.ts b/src/domain/entities/auth.ts index 6aefe5a..37d8f4d 100644 --- a/src/domain/entities/auth.ts +++ b/src/domain/entities/auth.ts @@ -24,9 +24,13 @@ export interface CustomRequest extends Request { export interface ChangeCredentialsModel { user_id: number; - password: string; + password?: string; new_password: string; password_hash?: string; reset_password_code?: string | null; reset_password_token?: string | null; } +export interface ResetCredentialsModel { + new_password: string; + reset_password_token: string | null; +} diff --git a/src/domain/interfaces/use-cases/auth/reset-password.ts b/src/domain/interfaces/use-cases/auth/reset-password.ts index 562f10d..51b1b73 100644 --- a/src/domain/interfaces/use-cases/auth/reset-password.ts +++ b/src/domain/interfaces/use-cases/auth/reset-password.ts @@ -1,4 +1,4 @@ -import { ChangeCredentialsModel } from "../../../entities/auth"; +import { ResetCredentialsModel } from "../../../entities/auth"; export interface ResetPasswordUseCase { - execute(credentials: ChangeCredentialsModel): Promise; + execute(credentials: ResetCredentialsModel): Promise; } diff --git a/src/domain/use-cases/auth/change-password.ts b/src/domain/use-cases/auth/change-password.ts index bf56cd7..dcc4146 100644 --- a/src/domain/use-cases/auth/change-password.ts +++ b/src/domain/use-cases/auth/change-password.ts @@ -17,8 +17,8 @@ export class ChangePassword implements ChangePasswordUseCase { nb_of_updated_user = await this.userRepository.changePassword(credentials) if (nb_of_updated_user == 0) throw new Error("Can't change password"); } else if (current_user.user_id == credentials.user_id) { - // Check if new password is different from old password - if (credentials.password === credentials.new_password) throw new Error("New password must be different from old password"); + // Check if new password exist and is different from old password + if (!credentials.password || credentials.password === credentials.new_password) throw new Error("New password must be different from old password"); // Check if old password is correct const verifyed = await this.userRepository.verifyUserLogin({ email: current_user.email, password: credentials.password }) if (verifyed) { diff --git a/src/domain/use-cases/auth/reset-password.ts b/src/domain/use-cases/auth/reset-password.ts index 5c54408..a89399c 100644 --- a/src/domain/use-cases/auth/reset-password.ts +++ b/src/domain/use-cases/auth/reset-password.ts @@ -1,6 +1,6 @@ import { UserRepository } from "../../interfaces/repositories/user-repository"; import { ResetPasswordUseCase } from "../../interfaces/use-cases/auth/reset-password"; -import { ChangeCredentialsModel, DecodedToken } from "../../entities/auth"; +import { DecodedToken, ResetCredentialsModel } from "../../entities/auth"; import { UserResponseModel } from "../../entities/user"; export class ResetPassword implements ResetPasswordUseCase { @@ -9,7 +9,7 @@ export class ResetPassword implements ResetPasswordUseCase { constructor(userRepository: UserRepository) { this.userRepository = userRepository } - async execute(credentials: ChangeCredentialsModel): Promise { + async execute(credentials: ResetCredentialsModel): Promise { let nb_of_updated_user: number = 0 let decoded_token: DecodedToken | null = null @@ -17,7 +17,7 @@ export class ResetPassword implements ResetPasswordUseCase { if (credentials.reset_password_token) { decoded_token = this.userRepository.verifyResetPasswordToken(credentials.reset_password_token) if (!decoded_token) throw new Error("Token is not valid"); - } else throw new Error("Token is not valid"); + } else throw new Error("No token provided"); // does the user bind to reset_password_code exist ? const preexistant_user: UserResponseModel | null = await this.userRepository.getUser( @@ -35,5 +35,7 @@ export class ResetPassword implements ResetPasswordUseCase { // change the password nb_of_updated_user = await this.userRepository.changePassword({ ...preexistant_user, ...credentials }) if (nb_of_updated_user == 0) throw new Error("Can't change password"); + //if (updatedUser.reset_password_code !== null) throw new Error("User reset password code not reset"); + } } \ No newline at end of file diff --git a/src/presentation/routers/auth-router.ts b/src/presentation/routers/auth-router.ts index 3e99235..653e55d 100644 --- a/src/presentation/routers/auth-router.ts +++ b/src/presentation/routers/auth-router.ts @@ -129,6 +129,7 @@ export default function AuthRouter( } catch (err) { console.log(err) if (err.message === "Token is not valid") res.status(401).send({ errors: ["Can't change password"] }) + if (err.message === "No token provided") res.status(401).send({ errors: ["Can't change password"] }) if (err.message === "User does not exist or token is not valid") res.status(404).send({ errors: ["Can't change password"] }) if (err.message === "User email is not validated") res.status(403).send({ errors: ["Can't change password"] }) else res.status(500).send({ errors: ["Can't reset password"] }) diff --git a/test/domain/repositories/user-repository.test.ts b/test/domain/repositories/user-repository.test.ts index 51da88e..8cc72cf 100644 --- a/test/domain/repositories/user-repository.test.ts +++ b/test/domain/repositories/user-repository.test.ts @@ -513,7 +513,7 @@ describe("User Repository", () => { const result = await userRepository.changePassword(credentials); expect(mockBcryptAdapter.hash).toHaveBeenCalledWith("new_password") - expect(mockUserDataSource.updateOne).toHaveBeenCalledWith({ user_id: 1, password_hash: "$2b$12$mMHjmPmUFsTrYFa3WUEVs.T1vaMz4q55FTfgpB.rNiL4GTt85BRkW" }) + expect(mockUserDataSource.updateOne).toHaveBeenCalledWith({ user_id: 1, password_hash: "$2b$12$mMHjmPmUFsTrYFa3WUEVs.T1vaMz4q55FTfgpB.rNiL4GTt85BRkW", reset_password_code: null }) expect(result).toBe(1) }); @@ -530,7 +530,7 @@ describe("User Repository", () => { const result = await userRepository.changePassword(credentials); expect(mockBcryptAdapter.hash).toHaveBeenCalledWith("new_password") - expect(mockUserDataSource.updateOne).toHaveBeenCalledWith({ user_id: 1, password_hash: "$2b$12$mMHjmPmUFsTrYFa3WUEVs.T1vaMz4q55FTfgpB.rNiL4GTt85BRkW" }) + expect(mockUserDataSource.updateOne).toHaveBeenCalledWith({ user_id: 1, password_hash: "$2b$12$mMHjmPmUFsTrYFa3WUEVs.T1vaMz4q55FTfgpB.rNiL4GTt85BRkW", reset_password_code: null }) expect(result).toBe(0) }); diff --git a/test/domain/use-cases/auth/reset-password-request.test.ts b/test/domain/use-cases/auth/reset-password-request.test.ts index f231376..d1f76a9 100644 --- a/test/domain/use-cases/auth/reset-password-request.test.ts +++ b/test/domain/use-cases/auth/reset-password-request.test.ts @@ -3,8 +3,8 @@ import { DecodedToken } from "../../../../src/domain/entities/auth"; import { UserRequestModel, UserResponseModel } from "../../../../src/domain/entities/user"; import { UserRepository } from "../../../../src/domain/interfaces/repositories/user-repository"; import { ResetPasswordRequest } from '../../../../src/domain/use-cases/auth/reset-password-request' -import { Transporter } from "nodemailer"; +import { Transporter } from "nodemailer"; import { NodemailerAdapter } from '../../../../src/infra/mailer/nodemailer' import { MailerWrapper } from "../../../../src/infra/mailer/nodemailer-wrapper"; diff --git a/test/domain/use-cases/auth/reset-password.test.ts b/test/domain/use-cases/auth/reset-password.test.ts new file mode 100644 index 0000000..222ccc9 --- /dev/null +++ b/test/domain/use-cases/auth/reset-password.test.ts @@ -0,0 +1,325 @@ + +import { DecodedToken, ResetCredentialsModel } from "../../../../src/domain/entities/auth"; +import { UserResponseModel } from "../../../../src/domain/entities/user"; +import { UserRepository } from "../../../../src/domain/interfaces/repositories/user-repository"; +import { ResetPassword } from '../../../../src/domain/use-cases/auth/reset-password' + +describe("Change password Use Case", () => { + class MockUserRepository implements UserRepository { + generateResetPasswordToken(): string { + throw new Error("Method not implemented."); + } + verifyResetPasswordToken(): DecodedToken | null { + throw new Error("Method not implemented."); + } + setResetPasswordCode(): Promise { + throw new Error("Method not implemented."); + } + toPublicUser(): UserResponseModel { + throw new Error("Method not implemented."); + } + changePassword(): Promise { + throw new Error("Method not implemented."); + } + adminUpdateUser(): Promise { + throw new Error("Method not implemented."); + } + standardUpdateUser(): Promise { + throw new Error("Method not implemented."); + } + isAdmin(): Promise { + throw new Error("Method not implemented."); + } + createUser(): Promise { + throw new Error("Method not implemented."); + } + getUsers(): Promise { + throw new Error("Method not implemented."); + } + getUser(): Promise { + throw new Error("Method not implemented."); + } + verifyUserLogin(): Promise { + throw new Error("Method not implemented."); + } + validUser(): Promise { + throw new Error("Method not implemented."); + } + generateValidationToken(): string { + throw new Error("Method not implemented."); + } + verifyValidationToken(): DecodedToken | null { + throw new Error("Method not implemented."); + } + } + + let mockUserRepository: UserRepository; + + beforeEach(async () => { + jest.clearAllMocks(); + mockUserRepository = new MockUserRepository() + }) + describe("reset password request SUCCESS", () => { + test("sucess test case", async () => { + const InputData: ResetCredentialsModel = { + reset_password_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyZXNldF9wYXNzd29yZF9jb2RlIjoiNjgzMzllZmItMDEwZS00ZjE4LWJhYmQtMjEyNWNiZDA4ZmU2IiwiaWF0IjoxNzA2MTcxNjcxLCJleHAiOjE3MDYxODI0NzF9.cJsCSTVldkPULrzz-i0NxumCerZLIDibbuy3vGXiHMY", + new_password: "new_password" + } + + const decoded_token: DecodedToken = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: false, + confirmation_code: "confirmation_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00', + + iat: 1693237789, + exp: 1724795389 + } + + const preexistant_user: UserResponseModel = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: true, + confirmation_code: "confirmation_code", + reset_password_code: "reset_password_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00' + } + const nb_of_updated_user = 1 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return decoded_token }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(preexistant_user)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + await reset_password.execute(InputData); + + expect(mockUserRepository.verifyResetPasswordToken).toHaveBeenCalledWith(InputData.reset_password_token); + expect(mockUserRepository.getUser).toHaveBeenCalledWith({ user_id: 1, reset_password_code: decoded_token.reset_password_code }); + expect(mockUserRepository.changePassword).toHaveBeenCalledWith({ ...preexistant_user, ...InputData }); + }); + + }) + describe("reset password request ERRORS", () => { + test("Token is not valid", async () => { + const InputData: ResetCredentialsModel = { + reset_password_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyZXNldF9wYXNzd29yZF9jb2RlIjoiNjgzMzllZmItMDEwZS00ZjE4LWJhYmQtMjEyNWNiZDA4ZmU2IiwiaWF0IjoxNzA2MTcxNjcxLCJleHAiOjE3MDYxODI0NzF9.cJsCSTVldkPULrzz-i0NxumCerZLIDibbuy3vGXiHMY", + new_password: "new_password" + } + + const nb_of_updated_user = 0 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return null }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(null)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + try { + await reset_password.execute(InputData); + } + catch (error) { + expect(error.message).toBe("Token is not valid"); + } + + expect(mockUserRepository.verifyResetPasswordToken).toHaveBeenCalledWith(InputData.reset_password_token); + expect(mockUserRepository.getUser).not.toHaveBeenCalled() + expect(mockUserRepository.changePassword).not.toHaveBeenCalled() + }) + test("No token provided", async () => { + + const InputData = { + reset_password_token: "", + new_password: "new_password" + } + + const nb_of_updated_user = 0 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return null }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(null)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + try { + await reset_password.execute(InputData); + } + catch (error) { + expect(error.message).toBe("No token provided"); + } + + expect(mockUserRepository.verifyResetPasswordToken).not.toHaveBeenCalled(); + expect(mockUserRepository.getUser).not.toHaveBeenCalled(); + expect(mockUserRepository.changePassword).not.toHaveBeenCalled(); + }) + test("User does not exist or token is not valid", async () => { + + const InputData: ResetCredentialsModel = { + reset_password_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyZXNldF9wYXNzd29yZF9jb2RlIjoiNjgzMzllZmItMDEwZS00ZjE4LWJhYmQtMjEyNWNiZDA4ZmU2IiwiaWF0IjoxNzA2MTcxNjcxLCJleHAiOjE3MDYxODI0NzF9.cJsCSTVldkPULrzz-i0NxumCerZLIDibbuy3vGXiHMY", + new_password: "new_password" + } + + const decoded_token: DecodedToken = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: true, + confirmation_code: "confirmation_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00', + + iat: 1693237789, + exp: 1724795389 + } + const nb_of_updated_user = 0 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return decoded_token }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(null)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + try { + await reset_password.execute(InputData); + } + catch (error) { + expect(error.message).toBe("User does not exist or token is not valid"); + } + + expect(mockUserRepository.verifyResetPasswordToken).toHaveBeenCalledWith(InputData.reset_password_token); + expect(mockUserRepository.getUser).toHaveBeenCalledWith({ user_id: 1, reset_password_code: decoded_token.reset_password_code }); + expect(mockUserRepository.changePassword).not.toHaveBeenCalled() + }) + test("User email is not validated", async () => { + + const InputData: ResetCredentialsModel = { + reset_password_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyZXNldF9wYXNzd29yZF9jb2RlIjoiNjgzMzllZmItMDEwZS00ZjE4LWJhYmQtMjEyNWNiZDA4ZmU2IiwiaWF0IjoxNzA2MTcxNjcxLCJleHAiOjE3MDYxODI0NzF9.cJsCSTVldkPULrzz-i0NxumCerZLIDibbuy3vGXiHMY", + new_password: "new_password" + } + + const decoded_token: DecodedToken = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: false, + confirmation_code: "confirmation_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00', + + iat: 1693237789, + exp: 1724795389 + } + + const preexistant_user: UserResponseModel = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: false, + confirmation_code: "confirmation_code", + reset_password_code: "reset_password_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00' + } + const nb_of_updated_user = 0 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return decoded_token }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(preexistant_user)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + try { + await reset_password.execute(InputData); + } + catch (error) { + expect(error.message).toBe("User email is not validated"); + } + + expect(mockUserRepository.verifyResetPasswordToken).toHaveBeenCalledWith(InputData.reset_password_token); + expect(mockUserRepository.getUser).toHaveBeenCalledWith({ user_id: 1, reset_password_code: decoded_token.reset_password_code }); + expect(mockUserRepository.changePassword).not.toHaveBeenCalled() + }) + test("Can't change password", async () => { + const InputData: ResetCredentialsModel = { + reset_password_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyZXNldF9wYXNzd29yZF9jb2RlIjoiNjgzMzllZmItMDEwZS00ZjE4LWJhYmQtMjEyNWNiZDA4ZmU2IiwiaWF0IjoxNzA2MTcxNjcxLCJleHAiOjE3MDYxODI0NzF9.cJsCSTVldkPULrzz-i0NxumCerZLIDibbuy3vGXiHMY", + new_password: "new_password" + } + + const decoded_token: DecodedToken = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: true, + confirmation_code: "confirmation_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00', + + iat: 1693237789, + exp: 1724795389 + } + + const preexistant_user: UserResponseModel = { + user_id: 1, + last_name: "Smith", + first_name: "John", + email: "john@gmail.com", + is_admin: false, + valid_email: true, + confirmation_code: "confirmation_code", + reset_password_code: "reset_password_code", + organisation: "LOV", + country: "France", + user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + user_creation_date: '2023-08-01 10:30:00' + } + const nb_of_updated_user = 0 + + jest.spyOn(mockUserRepository, "verifyResetPasswordToken").mockImplementation(() => { return decoded_token }) + jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(preexistant_user)) + jest.spyOn(mockUserRepository, "changePassword").mockImplementation(() => Promise.resolve(nb_of_updated_user)) + + + const reset_password = new ResetPassword(mockUserRepository) + try { + await reset_password.execute(InputData); + } + catch (error) { + expect(error.message).toBe("Can't change password"); + } + + expect(mockUserRepository.verifyResetPasswordToken).toHaveBeenCalledWith(InputData.reset_password_token); + expect(mockUserRepository.getUser).toHaveBeenCalledWith({ user_id: 1, reset_password_code: decoded_token.reset_password_code }); + expect(mockUserRepository.changePassword).toHaveBeenCalledWith({ ...preexistant_user, ...InputData }); + }) + }) + +}) diff --git a/test/domain/use-cases/user/create-user.test.ts b/test/domain/use-cases/user/create-user.test.ts index e8ece19..e989f37 100644 --- a/test/domain/use-cases/user/create-user.test.ts +++ b/test/domain/use-cases/user/create-user.test.ts @@ -130,6 +130,7 @@ describe("Create User Use Case", () => { jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(-1)) jest.spyOn(mockUserRepository, "generateValidationToken").mockImplementation(() => "token") jest.spyOn(mockMailerAdapter, "send_confirmation_email").mockImplementation(() => Promise.resolve()) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => { return OutputData }) const createUserUseCase = new CreateUser(mockUserRepository, mockTransporter, mockMailerAdapter) const result = await createUserUseCase.execute(InputData); @@ -139,7 +140,8 @@ describe("Create User Use Case", () => { expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).toHaveBeenNthCalledWith(2, { user_id: 1 }); expect(mockUserRepository.generateValidationToken).toHaveBeenCalledWith(created_user); - expect(mockMailerAdapter.send_confirmation_email).toHaveBeenCalledWith(mockTransporter, OutputData, "token"); + expect(mockMailerAdapter.send_confirmation_email).toHaveBeenCalledWith(mockTransporter, created_user, "token"); + expect(mockUserRepository.toPublicUser).toHaveBeenCalledWith(created_user); expect(result).toStrictEqual(OutputData); }); @@ -198,6 +200,7 @@ describe("Create User Use Case", () => { jest.spyOn(mockUserRepository, "createUser").mockImplementation(() => Promise.resolve(-1)) // not called jest.spyOn(mockUserRepository, "generateValidationToken").mockImplementation(() => "token") jest.spyOn(mockMailerAdapter, "send_confirmation_email").mockImplementation(() => Promise.resolve()) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => { return OutputData }) const createUserUseCase = new CreateUser(mockUserRepository, mockTransporter, mockMailerAdapter) const result = await createUserUseCase.execute(InputData); @@ -207,7 +210,8 @@ describe("Create User Use Case", () => { expect(mockUserRepository.standardUpdateUser).toHaveBeenCalledWith(preexistant_user); expect(mockUserRepository.getUser).toHaveBeenNthCalledWith(2, { user_id: 1 }); expect(mockUserRepository.generateValidationToken).toHaveBeenCalledWith(updated_user); - expect(mockMailerAdapter.send_confirmation_email).toHaveBeenCalledWith(mockTransporter, OutputData, "token"); + expect(mockMailerAdapter.send_confirmation_email).toHaveBeenCalledWith(mockTransporter, updated_user, "token"); + expect(mockUserRepository.toPublicUser).toHaveBeenCalledWith(updated_user); expect(result).toStrictEqual(OutputData); }); @@ -244,6 +248,7 @@ describe("Create User Use Case", () => { jest.spyOn(mockUserRepository, "createUser").mockImplementation(() => Promise.resolve(-1)) // not called jest.spyOn(mockUserRepository, "generateValidationToken").mockImplementation(() => "") // not called jest.spyOn(mockMailerAdapter, "send_confirmation_email").mockImplementation(() => Promise.resolve()) // not called + jest.spyOn(mockUserRepository, "toPublicUser") const createUserUseCase = new CreateUser(mockUserRepository, mockTransporter, mockMailerAdapter) try { @@ -257,6 +262,7 @@ describe("Create User Use Case", () => { expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.generateValidationToken).not.toBeCalled(); expect(mockMailerAdapter.send_confirmation_email).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); expect(err).toStrictEqual(expectedResponse); } @@ -295,6 +301,7 @@ describe("Create User Use Case", () => { jest.spyOn(mockUserRepository, "createUser").mockImplementation(() => Promise.resolve(-1)) // not called jest.spyOn(mockUserRepository, "generateValidationToken").mockImplementation(() => "token") // not called jest.spyOn(mockMailerAdapter, "send_confirmation_email").mockImplementation(() => Promise.resolve()) // not called + jest.spyOn(mockUserRepository, "toPublicUser") const createUserUseCase = new CreateUser(mockUserRepository, mockTransporter, mockMailerAdapter); try { @@ -307,6 +314,7 @@ describe("Create User Use Case", () => { expect(mockUserRepository.standardUpdateUser).toHaveBeenCalledWith(preexistant_user); expect(mockUserRepository.generateValidationToken).not.toBeCalled(); expect(mockMailerAdapter.send_confirmation_email).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); expect(err).toStrictEqual(expectedResponse); } @@ -343,6 +351,7 @@ describe("Create User Use Case", () => { jest.spyOn(mockUserRepository, "createUser").mockImplementation(() => Promise.resolve(-1)) // not called jest.spyOn(mockUserRepository, "generateValidationToken").mockImplementation(() => "token") // not called jest.spyOn(mockMailerAdapter, "send_confirmation_email").mockImplementation(() => Promise.resolve())// not called + jest.spyOn(mockUserRepository, "toPublicUser") const createUserUseCase = new CreateUser(mockUserRepository, mockTransporter, mockMailerAdapter); try { @@ -356,6 +365,7 @@ describe("Create User Use Case", () => { expect(mockUserRepository.getUser).toHaveBeenNthCalledWith(2, { user_id: 1 }); expect(mockUserRepository.generateValidationToken).not.toBeCalled(); expect(mockMailerAdapter.send_confirmation_email).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); expect(err).toStrictEqual(expectedResponse); } diff --git a/test/domain/use-cases/user/get-all-users.test.ts b/test/domain/use-cases/user/get-all-users.test.ts index d354a04..840879f 100644 --- a/test/domain/use-cases/user/get-all-users.test.ts +++ b/test/domain/use-cases/user/get-all-users.test.ts @@ -61,7 +61,7 @@ describe("Get All Users Use Case", () => { }) // TODO TEST when non user test("Should return data", async () => { - const ExpectedResult: UserResponseModel[] = [{ + const ExpectedResult: UserResponseModel = { user_id: 1, last_name: "Smith", first_name: "John", @@ -72,13 +72,13 @@ describe("Get All Users Use Case", () => { country: "France", user_planned_usage: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", user_creation_date: '2023-08-01 10:30:00' - }] + } - jest.spyOn(mockUserRepository, "getUsers").mockImplementation(() => Promise.resolve(ExpectedResult)) + jest.spyOn(mockUserRepository, "getUsers").mockImplementation(() => Promise.resolve([ExpectedResult])) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => { return ExpectedResult }) const getAllUsersUse = new GetAllUsers(mockUserRepository) const result = await getAllUsersUse.execute(); - expect(result).toStrictEqual(ExpectedResult) + expect(result).toStrictEqual([ExpectedResult]) }); - }) \ No newline at end of file diff --git a/test/domain/use-cases/user/update-user.test.ts b/test/domain/use-cases/user/update-user.test.ts index c4743b5..c457581 100644 --- a/test/domain/use-cases/user/update-user.test.ts +++ b/test/domain/use-cases/user/update-user.test.ts @@ -98,6 +98,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser") jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(OutputData)) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => OutputData) + const updateUserUseCase = new UpdateUser(mockUserRepository) const result = await updateUserUseCase.execute(current_user, user_to_update); expect(result).toStrictEqual(OutputData); @@ -106,6 +108,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).not.toBeCalled(); expect(mockUserRepository.standardUpdateUser).toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); + expect(mockUserRepository.toPublicUser).toBeCalled(); }); test("User is not admin : edit admin property on himself : nok", async () => { @@ -136,6 +139,7 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser") jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(0)) jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(getUserOutputData)) + jest.spyOn(mockUserRepository, "toPublicUser") const updateUserUseCase = new UpdateUser(mockUserRepository) try { @@ -149,6 +153,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).not.toBeCalled(); expect(mockUserRepository.standardUpdateUser).toBeCalled(); expect(mockUserRepository.getUser).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); }); @@ -180,6 +185,7 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser") jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(0)) jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(getUserOutputData)) + jest.spyOn(mockUserRepository, "toPublicUser") const updateUserUseCase = new UpdateUser(mockUserRepository) try { @@ -192,6 +198,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).not.toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); }); @@ -224,6 +231,7 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser") jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(0)) jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(getUserOutputData)) + jest.spyOn(mockUserRepository, "toPublicUser") const updateUserUseCase = new UpdateUser(mockUserRepository) try { @@ -236,14 +244,11 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).not.toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); }); - - - - // ADMIN test("User is admin : edit regular properties on himself : ok", async () => { const current_user: UserUpdateModel = { @@ -271,6 +276,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "standardUpdateUser") jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(OutputData)) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => OutputData) + const updateUserUseCase = new UpdateUser(mockUserRepository) const result = await updateUserUseCase.execute(current_user, user_to_update); expect(result).toStrictEqual(OutputData); @@ -279,6 +286,8 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); + expect(mockUserRepository.toPublicUser).toBeCalled(); + }); test("User is admin : edit admin property on himself : ok", async () => { @@ -307,6 +316,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "standardUpdateUser") jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(OutputData)) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => OutputData) + const updateUserUseCase = new UpdateUser(mockUserRepository) const result = await updateUserUseCase.execute(current_user, user_to_update); expect(result).toStrictEqual(OutputData); @@ -315,7 +326,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); - + expect(mockUserRepository.toPublicUser).toBeCalled(); }); test("User is admin : edit someone else regular properties : ok", async () => { @@ -344,6 +355,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "standardUpdateUser") jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(OutputData)) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => OutputData) + const updateUserUseCase = new UpdateUser(mockUserRepository) const result = await updateUserUseCase.execute(current_user, user_to_update); expect(result).toStrictEqual(OutputData); @@ -352,6 +365,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); + expect(mockUserRepository.toPublicUser).toBeCalled(); }); @@ -381,6 +395,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "standardUpdateUser") jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(OutputData)) + jest.spyOn(mockUserRepository, "toPublicUser").mockImplementation(() => OutputData) + const updateUserUseCase = new UpdateUser(mockUserRepository) const result = await updateUserUseCase.execute(current_user, user_to_update); expect(result).toStrictEqual(OutputData); @@ -389,6 +405,7 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); + expect(mockUserRepository.toPublicUser).toBeCalled(); }); @@ -409,6 +426,8 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser") jest.spyOn(mockUserRepository, "standardUpdateUser").mockImplementation(() => Promise.resolve(1)) jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(null)) + jest.spyOn(mockUserRepository, "toPublicUser") + const updateUserUseCase = new UpdateUser(mockUserRepository) try { @@ -421,6 +440,8 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).not.toBeCalled(); expect(mockUserRepository.standardUpdateUser).toBeCalled(); expect(mockUserRepository.getUser).toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); + }); test("Nothing to update on an admin user", async () => { @@ -439,6 +460,7 @@ describe("Update User Use Case", () => { jest.spyOn(mockUserRepository, "adminUpdateUser").mockImplementation(() => Promise.resolve(0)) jest.spyOn(mockUserRepository, "standardUpdateUser") jest.spyOn(mockUserRepository, "getUser").mockImplementation(() => Promise.resolve(null)) + jest.spyOn(mockUserRepository, "toPublicUser") const updateUserUseCase = new UpdateUser(mockUserRepository) try { @@ -451,6 +473,8 @@ describe("Update User Use Case", () => { expect(mockUserRepository.adminUpdateUser).toBeCalled(); expect(mockUserRepository.standardUpdateUser).not.toBeCalled(); expect(mockUserRepository.getUser).not.toBeCalled(); + expect(mockUserRepository.toPublicUser).not.toBeCalled(); + }); diff --git a/test/presentation/routes/auth-router.test.ts b/test/presentation/routes/auth-router.test.ts index 195e8d7..3bd48d0 100644 --- a/test/presentation/routes/auth-router.test.ts +++ b/test/presentation/routes/auth-router.test.ts @@ -30,7 +30,7 @@ class MockRefreshTokenUseCase implements RefreshTokenUseCase { } } class MockMiddlewareAuthValidation implements IMiddlewareAuthValidation { - rulesRequestResetPassword: []; + rulesRequestResetPassword = []; rulesPassword = [] rulesAuthUserCredentialsModel = []; }