From d4a25743daf60891ade48798d664afa486ffd30a Mon Sep 17 00:00:00 2001 From: "Embruch, Gerd" <gerd.embruch@uni-hamburg.de> Date: Sat, 27 Jul 2024 19:22:51 +0200 Subject: [PATCH] finished testing route auth/request-password-reset --- .../requestpasswordreset.test.js.snap | 31 +++ __tests__/auth/requestpasswordreset.test.js | 131 ++++++++++++ __tests__/auth/requestverification.test.js | 2 +- .../users/confirmemailchange.test.js | 189 ------------------ .../users/requestemailchange.test.js | 127 ------------ .../users/requestpasswordreset.test.js | 102 ---------- 6 files changed, 163 insertions(+), 419 deletions(-) create mode 100644 __tests__/auth/__snapshots__/requestpasswordreset.test.js.snap create mode 100644 __tests__/auth/requestpasswordreset.test.js delete mode 100644 logs/__tests__/users/confirmemailchange.test.js delete mode 100644 logs/__tests__/users/requestemailchange.test.js delete mode 100644 logs/__tests__/users/requestpasswordreset.test.js diff --git a/__tests__/auth/__snapshots__/requestpasswordreset.test.js.snap b/__tests__/auth/__snapshots__/requestpasswordreset.test.js.snap new file mode 100644 index 0000000..10a8e6b --- /dev/null +++ b/__tests__/auth/__snapshots__/requestpasswordreset.test.js.snap @@ -0,0 +1,31 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`user request password reset > given the email format is invalid > should respond with a proper body 1`] = ` +{ + "message": "Validation errors. Please check the error messages.", + "validationErrors": { + "email": "Invalid email", + }, +} +`; + +exports[`user request password reset > given the email is unknown > should respond with a proper body 1`] = ` +{ + "message": "If the email **user@mail.local** is correct you will receive an eMail with further instructions.", +} +`; + +exports[`user request password reset > given the inputs are valid > should respond with a proper body 1`] = ` +{ + "message": "If the email **user@mail.local** is correct you will receive an eMail with further instructions.", +} +`; + +exports[`user request password reset > the request body is empty > should respond with a proper body 1`] = ` +{ + "message": "Validation errors. Please check the error messages.", + "validationErrors": { + "email": "Required", + }, +} +`; diff --git a/__tests__/auth/requestpasswordreset.test.js b/__tests__/auth/requestpasswordreset.test.js new file mode 100644 index 0000000..d1f9fdb --- /dev/null +++ b/__tests__/auth/requestpasswordreset.test.js @@ -0,0 +1,131 @@ +// import vitest, supertest & app +import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest'; +import supertest from "supertest"; +import app from "../../app.js"; +// set route +const ROUTE = '/auth/password-reset'; +// prepare response of each test +let response; + +// ############################ +// OBJECTS +// ############################ +const mockedVals = vi.hoisted(() => { + return { + foundUser: { + _id: '66a29da2942b3eb', + username: 'snoopy', + name: 'My User', + email: 'user@mail.local', + verified: true, + role: 0, + createdAt: '2024-07 - 25T18: 46: 58.982Z', + updatedAt: '2024-07 - 25T18: 46: 58.982Z', + __v: 0, + password: 'StrongPass1!', + // password, + id: '66a29da2942b3ebcaf047f07' + }, + validInput: { + email: 'user@mail.local' + } + }; +}); + +// ############################ +// MOCKS +// ############################ +// import Database Service +import * as dbService from '../../utils/handleDB.js'; +// mock dbService +vi.mock('../../utils/handleDB.js', async (importOriginal) => { + return { + ...await importOriginal(), + dbConnection: vi.fn(() => 'mocked'), + findOneRecord: vi.fn(() => mockedVals.foundUser), + updateOneRecord: vi.fn(() => { return { ...mockedVals.foundUser, resetPasswordToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY2MOCKED' }; }) + }; +}); +// mock mailer +vi.mock('../../utils/handleMailer.js', async (importOriginal) => { + return { + ...await importOriginal(), + sendEmail: vi.fn(() => 'mocked') + }; +}); + +// ############################ +// TESTS +// ############################ +describe('user request password reset', () => { + describe('given the inputs are valid', async () => { + // set response by running route + beforeAll(async () => { + response = await supertest(app) + .post(ROUTE) + .send(mockedVals.validInput); + }); + it('should return a proper status code', () => { + expect(response.status).toBe(200); + }); + it('should respond with a proper body', () => { + expect(response.body).toMatchSnapshot(); + }); + }); + + + // ############################ + + describe('given the email is unknown', async () => { + // set response by running route + beforeAll(async () => { + dbService.findOneRecord.mockImplementationOnce(() => null); + + response = await supertest(app) + .post(ROUTE) + .send(mockedVals.validInput); + }); + it('should return a proper status code', () => { + expect(response.status).toBe(200); + }); + it('should respond with a proper body', () => { + expect(response.body).toMatchSnapshot(); + }); + }); + + // ############################ + + describe('given the email format is invalid', () => { + beforeAll(async () => { + const input = { ...mockedVals.validInput, email: 'invalid-email-format' }; + + response = await supertest(app) + .post(ROUTE) + .send(input); + }); + + it('should return a proper status code status', () => { + expect(response.status).toBe(400); + }); + it('should respond with a proper body', () => { + expect(response.body).toMatchSnapshot(); + }); + }); + + // ############################ + + describe('the request body is empty', () => { + beforeAll(async () => { + response = await supertest(app) + .post(ROUTE) + .send(); + }); + + it('should return a proper status code status', () => { + expect(response.status).toBe(400); + }); + it('should respond with a proper body', () => { + expect(response.body).toMatchSnapshot(); + }); + }); +}); \ No newline at end of file diff --git a/__tests__/auth/requestverification.test.js b/__tests__/auth/requestverification.test.js index 01c8ebc..6e29441 100644 --- a/__tests__/auth/requestverification.test.js +++ b/__tests__/auth/requestverification.test.js @@ -27,7 +27,7 @@ const mockedVals = vi.hoisted(() => { } }, validInput: { - email: 'john.doe@local.local' + email: 'user@mail.local' } }; }); diff --git a/logs/__tests__/users/confirmemailchange.test.js b/logs/__tests__/users/confirmemailchange.test.js deleted file mode 100644 index a1a7c02..0000000 --- a/logs/__tests__/users/confirmemailchange.test.js +++ /dev/null @@ -1,189 +0,0 @@ -// import vitest, supertest & app -import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest'; -import supertest from "supertest"; -import app from "../../app.js"; -// ignore expiration of the (self-signed) certificate -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; -// set timeout -const BEFORE_ALL_TIMEOUT = 30000; // 30 sec -// set route -const ROUTE = '/users/confirmemailchange'; -// prepare response of each test -let response; - -// ############################ -// OBJECTS -// ############################ - -const invalidTokenOrPasswordRsponse = { - code: 400, - message: 'Something went wrong while processing your request.', - data: { - password: { - code: 'validation_invalid_password', - message: 'Missing or invalid auth record password.' - }, - token: { - code: 'validation_invalid_token_payload', - message: 'Invalid token payload - newEmail must be set.' - } - } -}; - -// ############################ -// MOCKS -// ############################ -// import PocketBase Service -import * as pbService from '../../utils/pocketbase/handlePocketBase.js'; -// mock pbService -vi.mock('../../utils/pocketbase/handlePocketBase.js', async (importOriginal) => { - return { - ...await importOriginal(), - pbVerifyAccessToken: vi.fn().mockImplementation((req, res, next) => { - next(); - }), - pbConfirmEmailChange: vi.fn(() => 'mocked') - }; -}); - -// ############################ -// TESTS -// ############################ -describe('user request email reset', () => { - describe('given the inputs are valid', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ - token: 'validToken123', - password: 'StrongPass123!', - }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(200); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('Email successfully changed.'); - }); - }); - - // ############################ - - describe('given the token or password is invalid', () => { - beforeAll(async () => { - - let error = new Error(); - error.name = 'PBError'; - error.response = invalidTokenOrPasswordRsponse; - error.status = 400; - pbService.pbConfirmEmailChange.mockImplementation(() => { throw error; }); - - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ - token: 'invalidToken123', - password: 'StrongPass123!', - }); - }, BEFORE_ALL_TIMEOUT); - it('should force pbConfirmEmailChange to throw an error', () => { - expect(pbService.pbConfirmEmailChange).toThrowError(); - }); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors).toEqual({ - "password": "Missing or invalid auth record password.", - "token": "Invalid token payload - newEmail must be set.", - }); - }); - }); - - // ############################ - - describe('given password is missing', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ - token: 'validToken123' - }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.password).toEqual('Required'); - }); - }); - - // ############################ - - describe('given token is missing', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ - password: 'StrongPass123!', - }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.token).toEqual('Required'); - }); - }); - - // // ############################ - - describe('given JWT is missing', () => { - beforeAll(async () => { - pbService.pbVerifyAccessToken.mockImplementation((req, res, next) => { - res.status(403).json({ message: 'You are not logged in.' }); - }); - - response = await supertest(app) - .post(ROUTE) - .send({ - token: 'validToken123', - password: 'StrongPass123!', - }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(403); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('You are not logged in.'); - }); - }); - - // ############################ - - describe('given JWT is invalid', () => { - beforeAll(async () => { - pbService.pbVerifyAccessToken.mockImplementation((req, res, next) => { - res.status(403).json({ message: 'You are not logged in.' }); - }); - - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123invalid') - .send({ - token: 'validToken123', - password: 'StrongPass123!', - }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(403); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('You are not logged in.'); - }); - }); - -}); diff --git a/logs/__tests__/users/requestemailchange.test.js b/logs/__tests__/users/requestemailchange.test.js deleted file mode 100644 index 5ca77db..0000000 --- a/logs/__tests__/users/requestemailchange.test.js +++ /dev/null @@ -1,127 +0,0 @@ -// import vitest, supertest & app -import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest'; -import supertest from "supertest"; -import app from "../../app.js"; -// ignore expiration of the (self-signed) certificate -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; -// set timeout -const BEFORE_ALL_TIMEOUT = 30000; // 30 sec -// set route -const ROUTE = '/users/requestemailchange'; -// prepare response of each test -let response; - -// ############################ -// OBJECTS -// ############################ - -// ############################ -// MOCKS -// ############################ -// import PocketBase Service -import * as pbService from '../../utils/pocketbase/handlePocketBase.js'; -// mock pbService -vi.mock('../../utils/pocketbase/handlePocketBase.js', async (importOriginal) => { - return { - ...await importOriginal(), - pbVerifyAccessToken: vi.fn().mockImplementation((req, res, next) => { - next(); - }), - pbRequestEmailChange: vi.fn(() => 'mocked') - }; -}); - -// ############################ -// TESTS -// ############################ -describe('user request email reset', () => { - describe('given the inputs are valid', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ email: 'valid.mail@local.local' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(200); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('You will receive an eMail with further instructions to your new eMail-Account.'); - }); - }); - - // ############################ - - describe('given the email format is invalid', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid') - .send({ email: 'invalid-email-format' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.email).toEqual('Invalid email'); - }); - }); - - // ############################ - - describe('given email is missing', () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123valid'); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.email).toEqual('Required'); - }); - }); - - // ############################ - - describe('given JWT is missing', () => { - beforeAll(async () => { - pbService.pbVerifyAccessToken.mockImplementation((req, res, next) => { - res.status(403).json({ message: 'You are not logged in.' }); - }); - - response = await supertest(app) - .post(ROUTE) - .send({ email: 'valid.mail@local.local' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(403); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('You are not logged in.'); - }); - }); - - // ############################ - - describe('given JWT is invalid', () => { - beforeAll(async () => { - pbService.pbVerifyAccessToken.mockImplementation((req, res, next) => { - res.status(403).json({ message: 'You are not logged in.' }); - }); - - response = await supertest(app) - .post(ROUTE) - .set('Authorization', 'Bearer 123invalid') - .send({ email: 'valid.mail@local.local' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(403); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('You are not logged in.'); - }); - }); - -}); diff --git a/logs/__tests__/users/requestpasswordreset.test.js b/logs/__tests__/users/requestpasswordreset.test.js deleted file mode 100644 index 0be8626..0000000 --- a/logs/__tests__/users/requestpasswordreset.test.js +++ /dev/null @@ -1,102 +0,0 @@ -// import vitest, supertest & app -import { vi, beforeAll, beforeEach, describe, expect, expectTypeOf, test, it, afterEach } from 'vitest'; -import supertest from "supertest"; -import app from "../../app.js"; -// ignore expiration of the (self-signed) certificate -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; -// set timeout -const BEFORE_ALL_TIMEOUT = 30000; // 30 sec -// set route -const ROUTE = '/users/requestpasswordreset'; -// prepare response of each test -let response; - -// ############################ -// OBJECTS -// ############################ - -// ############################ -// MOCKS -// ############################ -// import PocketBase Service -import * as pbService from '../../utils/pocketbase/handlePocketBase.js'; -// mock pbService -vi.mock('../../utils/pocketbase/handlePocketBase.js', async (importOriginal) => { - return { - ...await importOriginal(), - pbRequestPasswordReset: vi.fn(() => 'mocked') - }; -}); - -// ############################ -// TESTS -// ############################ -describe('user request password reset', () => { - describe('given the inputs are valid', async () => { - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .send({ email: 'well.known@local.local' }); - }, BEFORE_ALL_TIMEOUT); - it('should call required mocks', () => { - expect(pbService.pbRequestPasswordReset()).toEqual('mocked'); - }); - it('should return a proper status code', () => { - expect(response.status).toBe(200); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('If the email **well.known@local.local** is correct you will receive an eMail with further instructions.'); - }); - }); - - // ############################ - - describe('given the email is missing', async () => { - // set response by running route - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.email).toEqual('Required'); - - }); - }); - - // ############################ - - describe('given the email format is invalid', async () => { - // set response by running route - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .send({ email: 'invalid-email' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(400); - }); - it('should respond with a proper message', () => { - expect(response.body.validationErrors.email).toEqual('Invalid email'); - }); - }); - - // ############################ - - describe('given the email is unknown', async () => { - // set response by running route - beforeAll(async () => { - response = await supertest(app) - .post(ROUTE) - .send({ email: 'un.known@local.local' }); - }, BEFORE_ALL_TIMEOUT); - it('should return a proper status code', () => { - expect(response.status).toBe(200); - }); - it('should respond with a proper message', () => { - expect(response.body.message).toEqual('If the email **un.known@local.local** is correct you will receive an eMail with further instructions.'); - }); - }); -}); \ No newline at end of file -- GitLab