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