diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js index 619cb2e94..deb210d32 100644 --- a/Server/controllers/authController.js +++ b/Server/controllers/authController.js @@ -103,7 +103,6 @@ const registerUser = async (req, res, next) => { data: { user: newUser, token: token }, }); } catch (error) { - console.log("ERROR", error); next(handleError(error, SERVICE_NAME, "registerController")); } }; diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index 3c43f7d31..b675ab652 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -77,7 +77,7 @@ const getMonitorStatsById = async (req, res, next) => { } }; -const getMonitorCertificate = async (req, res, next) => { +const getMonitorCertificate = async (req, res, next, fetchMonitorCertificate) => { try { await getCertificateParamValidation.validateAsync(req.params); } catch (error) { diff --git a/Server/routes/monitorRoute.js b/Server/routes/monitorRoute.js index 517bfb14d..d6ba03ece 100644 --- a/Server/routes/monitorRoute.js +++ b/Server/routes/monitorRoute.js @@ -1,25 +1,28 @@ import { Router } from "express"; import { - getAllMonitors, - getMonitorStatsById, - getMonitorCertificate, - getMonitorById, - getMonitorsAndSummaryByTeamId, - getMonitorsByTeamId, - createMonitor, - deleteMonitor, - deleteAllMonitors, - editMonitor, - pauseMonitor, - addDemoMonitors, + getAllMonitors, + getMonitorStatsById, + getMonitorCertificate, + getMonitorById, + getMonitorsAndSummaryByTeamId, + getMonitorsByTeamId, + createMonitor, + deleteMonitor, + deleteAllMonitors, + editMonitor, + pauseMonitor, + addDemoMonitors, } from "../controllers/monitorController.js"; import { isAllowed } from "../middleware/isAllowed.js"; +import { fetchMonitorCertificate } from "../controllers/controllerUtils.js"; const router = Router(); router.get("/", getAllMonitors); router.get("/stats/:monitorId", getMonitorStatsById); -router.get("/certificate/:monitorId", getMonitorCertificate); +router.get("/certificate/:monitorId", (req, res, next) => { + getMonitorCertificate(req, res, next, fetchMonitorCertificate); +}); router.get("/:monitorId", getMonitorById); router.get("/team/summary/:teamId", getMonitorsAndSummaryByTeamId); router.get("/team/:teamId", getMonitorsByTeamId); @@ -32,11 +35,7 @@ router.put("/:monitorId", isAllowed(["admin", "superadmin"]), editMonitor); router.delete("/", isAllowed(["superadmin"]), deleteAllMonitors); -router.post( - "/pause/:monitorId", - isAllowed(["admin", "superadmin"]), - pauseMonitor -); +router.post("/pause/:monitorId", isAllowed(["admin", "superadmin"]), pauseMonitor); router.post("/demo", isAllowed(["admin", "superadmin"]), addDemoMonitors); diff --git a/Server/tests/controllers/authController.test.js b/Server/tests/controllers/authController.test.js index d598ff02a..d06a0c61f 100644 --- a/Server/tests/controllers/authController.test.js +++ b/Server/tests/controllers/authController.test.js @@ -1,14 +1,14 @@ import { - issueToken, - registerUser, - loginUser, - editUser, - checkSuperadminExists, - requestRecovery, - validateRecovery, - resetPassword, - deleteUser, - getAllUsers, + issueToken, + registerUser, + loginUser, + editUser, + checkSuperadminExists, + requestRecovery, + validateRecovery, + resetPassword, + deleteUser, + getAllUsers, } from "../../controllers/authController.js"; import jwt from "jsonwebtoken"; import { errorMessages, successMessages } from "../../utils/messages.js"; @@ -16,796 +16,801 @@ import sinon from "sinon"; import logger from "../../utils/logger.js"; describe("Auth Controller - issueToken", () => { - it("should reject with an error if jwt.sign fails", () => { - const error = new Error("jwt.sign error"); - const stub = sinon.stub(jwt, "sign").throws(error); - const payload = { id: "123" }; - const appSettings = { jwtSecret: "my_secret" }; - expect(() => issueToken(payload, appSettings)).to.throw(error); - stub.restore(); - }); + it("should reject with an error if jwt.sign fails", () => { + const error = new Error("jwt.sign error"); + const stub = sinon.stub(jwt, "sign").throws(error); + const payload = { id: "123" }; + const appSettings = { jwtSecret: "my_secret" }; + expect(() => issueToken(payload, appSettings)).to.throw(error); + stub.restore(); + }); - it("should return a token if jwt.sign is successful and appSettings.jtwTTL is not defined", () => { - const payload = { id: "123" }; - const appSettings = { jwtSecret: "my_secret" }; - const token = issueToken(payload, appSettings); - expect(token).to.be.a("string"); - }); + it("should return a token if jwt.sign is successful and appSettings.jtwTTL is not defined", () => { + const payload = { id: "123" }; + const appSettings = { jwtSecret: "my_secret" }; + const token = issueToken(payload, appSettings); + expect(token).to.be.a("string"); + }); - it("should return a token if jwt.sign is successful and appSettings.jwtTTL is defined", () => { - const payload = { id: "123" }; - const appSettings = { jwtSecret: "my_secret", jwtTTL: "1s" }; - const token = issueToken(payload, appSettings); - expect(token).to.be.a("string"); - }); + it("should return a token if jwt.sign is successful and appSettings.jwtTTL is defined", () => { + const payload = { id: "123" }; + const appSettings = { jwtSecret: "my_secret", jwtTTL: "1s" }; + const token = issueToken(payload, appSettings); + expect(token).to.be.a("string"); + }); }); describe("Auth Controller - registerUser", () => { - let req, res, next; - beforeEach(() => { - req = { - body: { - firstName: "firstname", - lastName: "lastname", - email: "test@test.com", - password: "Uptime1!", - role: ["admin"], - teamId: "123", - inviteToken: "invite", - }, - db: { - checkSuperadmin: sinon.stub(), - getInviteTokenAndDelete: sinon.stub(), - updateAppSettings: sinon.stub(), - insertUser: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub().resolves({ - jwtSecret: "my_secret", - }), - }, - emailService: { - buildAndSendEmail: sinon.stub(), - }, - file: {}, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - sinon.stub(logger, "error"); - }); - afterEach(() => { - sinon.restore(); - }); + let req, res, next; + beforeEach(() => { + req = { + body: { + firstName: "firstname", + lastName: "lastname", + email: "test@test.com", + password: "Uptime1!", + role: ["admin"], + teamId: "123", + inviteToken: "invite", + }, + db: { + checkSuperadmin: sinon.stub(), + getInviteTokenAndDelete: sinon.stub(), + updateAppSettings: sinon.stub(), + insertUser: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub().resolves({ + jwtSecret: "my_secret", + }), + }, + emailService: { + buildAndSendEmail: sinon.stub(), + }, + file: {}, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + sinon.stub(logger, "error"); + }); + afterEach(() => { + sinon.restore(); + }); - it("should reject with an error if body validation fails", async () => { - req.body = {}; - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + it("should reject with an error if body validation fails", async () => { + req.body = {}; + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if checkSuperadmin fails", async () => { - req.db.checkSuperadmin.rejects(new Error("checkSuperadmin error")); - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("checkSuperadmin error"); - }); + it("should reject with an error if checkSuperadmin fails", async () => { + req.db.checkSuperadmin.throws(new Error("checkSuperadmin error")); + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("checkSuperadmin error"); + }); - it("should reject with an error if getInviteTokenAndDelete fails", async () => { - req.db.checkSuperadmin.resolves(true); - req.db.getInviteTokenAndDelete.rejects( - new Error("getInviteTokenAndDelete error") - ); - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal( - "getInviteTokenAndDelete error" - ); - }); + it("should reject with an error if getInviteTokenAndDelete fails", async () => { + req.db.checkSuperadmin.returns(true); + req.db.getInviteTokenAndDelete.throws(new Error("getInviteTokenAndDelete error")); + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("getInviteTokenAndDelete error"); + }); - it("should reject with an error if updateAppSettings fails", async () => { - req.db.checkSuperadmin.resolves(false); - req.db.updateAppSettings.rejects(new Error("updateAppSettings error")); - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("updateAppSettings error"); - }); + it("should reject with an error if updateAppSettings fails", async () => { + req.db.checkSuperadmin.returns(false); + req.db.updateAppSettings.throws(new Error("updateAppSettings error")); + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("updateAppSettings error"); + }); - it("should reject with an error if insertUser fails", async () => { - req.db.checkSuperadmin.resolves(false); - req.db.updateAppSettings.resolves(); - req.db.insertUser.rejects(new Error("insertUser error")); - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("insertUser error"); - }); + it("should reject with an error if insertUser fails", async () => { + req.db.checkSuperadmin.resolves(false); + req.db.updateAppSettings.resolves(); + req.db.insertUser.rejects(new Error("insertUser error")); + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("insertUser error"); + }); - it("should reject with an error if settingsService.getSettings fails", async () => { - req.db.checkSuperadmin.resolves(false); - req.db.updateAppSettings.resolves(); - req.db.insertUser.resolves({ _id: "123" }); - req.settingsService.getSettings.rejects( - new Error("settingsService.getSettings error") - ); - await registerUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal( - "settingsService.getSettings error" - ); - }); + it("should reject with an error if settingsService.getSettings fails", async () => { + req.db.checkSuperadmin.resolves(false); + req.db.updateAppSettings.resolves(); + req.db.insertUser.resolves({ _id: "123" }); + req.settingsService.getSettings.rejects( + new Error("settingsService.getSettings error") + ); + await registerUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("settingsService.getSettings error"); + }); - it("should log an error if emailService.buildAndSendEmail fails", async () => { - req.db.checkSuperadmin.resolves(false); - req.db.updateAppSettings.resolves(); - req.db.insertUser.returns({ _id: "123" }); - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.emailService.buildAndSendEmail.rejects(new Error("emailService error")); - await registerUser(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[1].error).to.equal("emailService error"); - }); - it("should return a success message and data if all operations are successful", async () => { - const user = { _id: "123" }; - req.db.checkSuperadmin.resolves(false); - req.db.updateAppSettings.resolves(); - req.db.insertUser.returns(user); - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.emailService.buildAndSendEmail.resolves("message-id"); - await registerUser(req, res, next); - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_CREATE_USER, - data: { user, token: sinon.match.string }, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + it("should log an error if emailService.buildAndSendEmail fails", async () => { + req.db.checkSuperadmin.resolves(false); + req.db.updateAppSettings.resolves(); + req.db.insertUser.returns({ _id: "123" }); + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.emailService.buildAndSendEmail.rejects(new Error("emailService error")); + await registerUser(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[1].error).to.equal("emailService error"); + }); + it("should return a success message and data if all operations are successful", async () => { + const user = { _id: "123" }; + req.db.checkSuperadmin.resolves(false); + req.db.updateAppSettings.resolves(); + req.db.insertUser.returns(user); + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.emailService.buildAndSendEmail.resolves("message-id"); + await registerUser(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_CREATE_USER, + data: { user, token: sinon.match.string }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); + it("should return a success message and data if all operations are successful and superAdmin true", async () => { + const user = { _id: "123" }; + req.db.checkSuperadmin.resolves(true); + req.db.updateAppSettings.resolves(); + req.db.insertUser.returns(user); + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.emailService.buildAndSendEmail.resolves("message-id"); + await registerUser(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_CREATE_USER, + data: { user, token: sinon.match.string }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); }); describe("Auth Controller - loginUser", () => { - let req, res, next, user; - beforeEach(() => { - req = { - body: { email: "test@example.com", password: "Password123!" }, - db: { - getUserByEmail: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub().resolves({ - jwtSecret: "my_secret", - }), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - user = { - _doc: { - email: "test@example.com", - }, - comparePassword: sinon.stub(), - }; - }); - it("should reject with an error if validation fails", async () => { - req.body = {}; - await loginUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + let req, res, next, user; + beforeEach(() => { + req = { + body: { email: "test@example.com", password: "Password123!" }, + db: { + getUserByEmail: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub().resolves({ + jwtSecret: "my_secret", + }), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + user = { + _doc: { + email: "test@example.com", + }, + comparePassword: sinon.stub(), + }; + }); + it("should reject with an error if validation fails", async () => { + req.body = {}; + await loginUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if getUserByEmail fails", async () => { - req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); - await loginUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); - }); + it("should reject with an error if getUserByEmail fails", async () => { + req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); + await loginUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); + }); - it("should login user successfully", async () => { - req.db.getUserByEmail.resolves(user); - user.comparePassword.resolves(true); - await loginUser(req, res, next); - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_LOGIN_USER, - data: { - user: { - email: "test@example.com", - avatarImage: undefined, - }, - token: sinon.match.string, - }, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); - it("should reject a user with an incorrect password", async () => { - req.body = { - email: "test@test.com", - password: "Password123!", - }; - req.db.getUserByEmail.resolves(user); - user.comparePassword.resolves(false); - await loginUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal( - errorMessages.AUTH_INCORRECT_PASSWORD - ); - }); + it("should login user successfully", async () => { + req.db.getUserByEmail.resolves(user); + user.comparePassword.resolves(true); + await loginUser(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_LOGIN_USER, + data: { + user: { + email: "test@example.com", + avatarImage: undefined, + }, + token: sinon.match.string, + }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); + it("should reject a user with an incorrect password", async () => { + req.body = { + email: "test@test.com", + password: "Password123!", + }; + req.db.getUserByEmail.resolves(user); + user.comparePassword.resolves(false); + await loginUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal( + errorMessages.AUTH_INCORRECT_PASSWORD + ); + }); }); describe("Auth Controller - editUser", async () => { - let req, res, next, stub, user; - beforeEach(() => { - req = { - params: { userId: "123" }, - body: { password: "Password1!", newPassword: "Password2!" }, - headers: { authorization: "Bearer token" }, - user: { _id: "123" }, - settingsService: { - getSettings: sinon.stub().returns({ jwtSecret: "my_secret" }), - }, - db: { - getUserByEmail: sinon.stub(), - updateUser: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - stub = sinon.stub(jwt, "verify").returns({ email: "test@example.com" }); - }); - afterEach(() => { - sinon.restore(); - stub.restore(); - }); + let req, res, next, stub, user; + beforeEach(() => { + req = { + params: { userId: "123" }, + body: { password: "Password1!", newPassword: "Password2!" }, + headers: { authorization: "Bearer token" }, + user: { _id: "123" }, + settingsService: { + getSettings: sinon.stub().returns({ jwtSecret: "my_secret" }), + }, + db: { + getUserByEmail: sinon.stub(), + updateUser: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + stub = sinon.stub(jwt, "verify").returns({ email: "test@example.com" }); + }); + afterEach(() => { + sinon.restore(); + stub.restore(); + }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if body validation fails", async () => { - req.body = { invalid: 1 }; - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + it("should reject with an error if body validation fails", async () => { + req.body = { invalid: 1 }; + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if param.userId !== req.user._id", async () => { - req.params = { userId: "456" }; - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(401); - }); + it("should reject with an error if param.userId !== req.user._id", async () => { + req.params = { userId: "456" }; + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(401); + }); - it("should reject with an error if !req.body.password and getUserByEmail fails", async () => { - req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); - }); + it("should reject with an error if !req.body.password and getUserByEmail fails", async () => { + req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); + }); - it("should reject with an error if user.comparePassword fails", async () => { - req.db.getUserByEmail.returns({ - comparePassword: sinon.stub().rejects(new Error("Bad Password Match")), - }); - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Bad Password Match"); - }); + it("should reject with an error if user.comparePassword fails", async () => { + req.db.getUserByEmail.returns({ + comparePassword: sinon.stub().rejects(new Error("Bad Password Match")), + }); + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Bad Password Match"); + }); - it("should reject with an error if user.comparePassword returns false", async () => { - req.db.getUserByEmail.returns({ - comparePassword: sinon.stub().returns(false), - }); - await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(403); - expect(next.firstCall.args[0].message).to.equal( - errorMessages.AUTH_INCORRECT_PASSWORD - ); - }); + it("should reject with an error if user.comparePassword returns false", async () => { + req.db.getUserByEmail.returns({ + comparePassword: sinon.stub().returns(false), + }); + await editUser(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(403); + expect(next.firstCall.args[0].message).to.equal( + errorMessages.AUTH_INCORRECT_PASSWORD + ); + }); - it("should edit a user if it receives a proper request", async () => { - const user = { - comparePassword: sinon.stub().resolves(true), - }; - req.db.getUserByEmail.resolves(user); - req.db.updateUser.resolves({ email: "test@example.com" }); + it("should edit a user if it receives a proper request", async () => { + const user = { + comparePassword: sinon.stub().resolves(true), + }; + req.db.getUserByEmail.resolves(user); + req.db.updateUser.resolves({ email: "test@example.com" }); - await editUser(req, res, next); + await editUser(req, res, next); - expect(req.db.getUserByEmail.calledOnce).to.be.true; - expect(req.db.updateUser.calledOnce).to.be.true; - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_UPDATE_USER, - data: { email: "test@example.com" }, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + expect(req.db.getUserByEmail.calledOnce).to.be.true; + expect(req.db.updateUser.calledOnce).to.be.true; + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_UPDATE_USER, + data: { email: "test@example.com" }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should edit a user if it receives a proper request and both password fields are undefined", async () => { - req.body.password = undefined; - req.body.newPassword = undefined; - req.db.getUserByEmail.resolves(user); - req.db.updateUser.resolves({ email: "test@example.com" }); + it("should edit a user if it receives a proper request and both password fields are undefined", async () => { + req.body.password = undefined; + req.body.newPassword = undefined; + req.db.getUserByEmail.resolves(user); + req.db.updateUser.resolves({ email: "test@example.com" }); - await editUser(req, res, next); - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_UPDATE_USER, - data: { email: "test@example.com" }, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + await editUser(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_UPDATE_USER, + data: { email: "test@example.com" }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should reject an edit request if password format is incorrect", async () => { - req.body = { password: "bad_password", newPassword: "bad_password" }; - const user = { - comparePassword: sinon.stub().resolves(true), - }; - req.db.getUserByEmail.resolves(user); + it("should reject an edit request if password format is incorrect", async () => { + req.body = { password: "bad_password", newPassword: "bad_password" }; + const user = { + comparePassword: sinon.stub().resolves(true), + }; + req.db.getUserByEmail.resolves(user); - await editUser(req, res, next); + await editUser(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); }); describe("Auth Controller - checkSuperadminExists", async () => { - let req, res, next; - beforeEach(() => { - req = { - db: { - checkSuperadmin: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); + let req, res, next; + beforeEach(() => { + req = { + db: { + checkSuperadmin: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); - it("should reject with an error if checkSuperadmin fails", async () => { - req.db.checkSuperadmin.rejects(new Error("checkSuperadmin error")); - await checkSuperadminExists(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("checkSuperadmin error"); - }); + it("should reject with an error if checkSuperadmin fails", async () => { + req.db.checkSuperadmin.rejects(new Error("checkSuperadmin error")); + await checkSuperadminExists(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("checkSuperadmin error"); + }); - it("should return true if a superadmin exists", async () => { - req.db.checkSuperadmin.resolves(true); - await checkSuperadminExists(req, res, next); - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_SUPERADMIN_EXISTS, - data: true, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + it("should return true if a superadmin exists", async () => { + req.db.checkSuperadmin.resolves(true); + await checkSuperadminExists(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_SUPERADMIN_EXISTS, + data: true, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should return false if a superadmin does not exist", async () => { - req.db.checkSuperadmin.resolves(false); - await checkSuperadminExists(req, res, next); - expect(res.status.calledWith(200)).to.be.true; - expect( - res.json.calledWith({ - success: true, - msg: successMessages.AUTH_SUPERADMIN_EXISTS, - data: false, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + it("should return false if a superadmin does not exist", async () => { + req.db.checkSuperadmin.resolves(false); + await checkSuperadminExists(req, res, next); + expect(res.status.calledWith(200)).to.be.true; + expect( + res.json.calledWith({ + success: true, + msg: successMessages.AUTH_SUPERADMIN_EXISTS, + data: false, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); }); describe("Auth Controller - requestRecovery", () => { - let req, res, next; - beforeEach(() => { - req = { - body: { email: "test@test.com" }, - db: { - getUserByEmail: sinon.stub(), - requestRecoveryToken: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub().returns({ clientHost: "http://localhost" }), - }, - emailService: { - buildAndSendEmail: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); + let req, res, next; + beforeEach(() => { + req = { + body: { email: "test@test.com" }, + db: { + getUserByEmail: sinon.stub(), + requestRecoveryToken: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub().returns({ clientHost: "http://localhost" }), + }, + emailService: { + buildAndSendEmail: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); - it("should reject with an error if validation fails", async () => { - req.body = {}; - await requestRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + it("should reject with an error if validation fails", async () => { + req.body = {}; + await requestRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if getUserByEmail fails", async () => { - req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); - await requestRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); - }); + it("should reject with an error if getUserByEmail fails", async () => { + req.db.getUserByEmail.rejects(new Error("getUserByEmail error")); + await requestRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("getUserByEmail error"); + }); - it("should throw an error if the user is not found", async () => { - req.db.getUserByEmail.resolves(null); - await requestRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - // expect(next.firstCall.args[0].message).to.equal( - // errorMessages.FRIENDLY_ERROR - // ); - }); + it("should throw an error if the user is not found", async () => { + req.db.getUserByEmail.resolves(null); + await requestRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + // expect(next.firstCall.args[0].message).to.equal( + // errorMessages.FRIENDLY_ERROR + // ); + }); - it("should throw an error if the email is not provided", async () => { - req.body = {}; - await requestRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should return a success message if the email is provided", async () => { - const user = { firstName: "John" }; - const recoveryToken = { token: "recovery-token" }; - const msgId = "message-id"; - req.db.getUserByEmail.resolves(user); - req.db.requestRecoveryToken.resolves(recoveryToken); - req.emailService.buildAndSendEmail.resolves(msgId); - await requestRecovery(req, res, next); - expect(req.db.getUserByEmail.calledOnceWith("test@test.com")).to.be.true; - expect(req.db.requestRecoveryToken.calledOnceWith(req, res)).to.be.true; - expect( - req.emailService.buildAndSendEmail.calledOnceWith( - "passwordResetTemplate", - { - name: "John", - email: "test@test.com", - url: "http://localhost/set-new-password/recovery-token", - }, - "test@test.com", - "Bluewave Uptime Password Reset" - ) - ).to.be.true; - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN, - data: msgId, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + it("should throw an error if the email is not provided", async () => { + req.body = {}; + await requestRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should return a success message if the email is provided", async () => { + const user = { firstName: "John" }; + const recoveryToken = { token: "recovery-token" }; + const msgId = "message-id"; + req.db.getUserByEmail.resolves(user); + req.db.requestRecoveryToken.resolves(recoveryToken); + req.emailService.buildAndSendEmail.resolves(msgId); + await requestRecovery(req, res, next); + expect(req.db.getUserByEmail.calledOnceWith("test@test.com")).to.be.true; + expect(req.db.requestRecoveryToken.calledOnceWith(req, res)).to.be.true; + expect( + req.emailService.buildAndSendEmail.calledOnceWith( + "passwordResetTemplate", + { + name: "John", + email: "test@test.com", + url: "http://localhost/set-new-password/recovery-token", + }, + "test@test.com", + "Bluewave Uptime Password Reset" + ) + ).to.be.true; + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN, + data: msgId, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); }); describe("Auth Controller - validateRecovery", () => { - let req, res, next; - beforeEach(() => { - req = { - body: { recoveryToken: "recovery-token" }, - db: { - validateRecoveryToken: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); + let req, res, next; + beforeEach(() => { + req = { + body: { recoveryToken: "recovery-token" }, + db: { + validateRecoveryToken: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); - it("should reject with an error if validation fails", async () => { - req.body = {}; - await validateRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + it("should reject with an error if validation fails", async () => { + req.body = {}; + await validateRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if validateRecoveryToken fails", async () => { - req.db.validateRecoveryToken.rejects( - new Error("validateRecoveryToken error") - ); - await validateRecovery(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal( - "validateRecoveryToken error" - ); - }); + it("should reject with an error if validateRecoveryToken fails", async () => { + req.db.validateRecoveryToken.rejects(new Error("validateRecoveryToken error")); + await validateRecovery(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("validateRecoveryToken error"); + }); - it("should return a success message if the token is valid", async () => { - req.db.validateRecoveryToken.resolves(); - await validateRecovery(req, res, next); - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + it("should return a success message if the token is valid", async () => { + req.db.validateRecoveryToken.resolves(); + await validateRecovery(req, res, next); + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); }); describe("Auth Controller - resetPassword", () => { - let req, res, next, newPasswordValidation, handleValidationError, handleError; - beforeEach(() => { - req = { - body: { - recoveryToken: "recovery-token", - password: "Password1!", - }, - db: { - resetPassword: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - newPasswordValidation = { - validateAsync: sinon.stub(), - }; - handleValidationError = sinon.stub(); - handleError = sinon.stub(); - }); - it("should reject with an error if validation fails", async () => { - req.body = { password: "bad_password" }; - await resetPassword(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); + let req, res, next, newPasswordValidation, handleValidationError, handleError; + beforeEach(() => { + req = { + body: { + recoveryToken: "recovery-token", + password: "Password1!", + }, + db: { + resetPassword: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + newPasswordValidation = { + validateAsync: sinon.stub(), + }; + handleValidationError = sinon.stub(); + handleError = sinon.stub(); + }); + it("should reject with an error if validation fails", async () => { + req.body = { password: "bad_password" }; + await resetPassword(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); - it("should reject with an error if resetPassword fails", async () => { - const error = new Error("resetPassword error"); - newPasswordValidation.validateAsync.resolves(); - req.db.resetPassword.rejects(error); - await resetPassword(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("resetPassword error"); - }); + it("should reject with an error if resetPassword fails", async () => { + const error = new Error("resetPassword error"); + newPasswordValidation.validateAsync.resolves(); + req.db.resetPassword.rejects(error); + await resetPassword(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("resetPassword error"); + }); - it("should reset password successfully", async () => { - const user = { _doc: {} }; - const appSettings = { jwtSecret: "my_secret" }; - const token = "token"; + it("should reset password successfully", async () => { + const user = { _doc: {} }; + const appSettings = { jwtSecret: "my_secret" }; + const token = "token"; - newPasswordValidation.validateAsync.resolves(); - req.db.resetPassword.resolves(user); - req.settingsService.getSettings.resolves(appSettings); + newPasswordValidation.validateAsync.resolves(); + req.db.resetPassword.resolves(user); + req.settingsService.getSettings.resolves(appSettings); - await resetPassword(req, res, next); + await resetPassword(req, res, next); - expect(req.db.resetPassword.calledOnceWith(req, res)).to.be.true; - expect(req.settingsService.getSettings.calledOnce).to.be.true; - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.AUTH_RESET_PASSWORD, - data: { user: sinon.match.object, token: sinon.match.string }, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + expect(req.db.resetPassword.calledOnceWith(req, res)).to.be.true; + expect(req.settingsService.getSettings.calledOnce).to.be.true; + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.AUTH_RESET_PASSWORD, + data: { user: sinon.match.object, token: sinon.match.string }, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); }); describe("Auth Controller - deleteUser", () => { - let req, res, next, handleError; - beforeEach(() => { - req = { - headers: { - authorization: "Bearer token", - }, - db: { - getUserByEmail: sinon.stub(), - getMonitorsByTeamId: sinon.stub(), - deleteJob: sinon.stub(), - deleteChecks: sinon.stub(), - deletePageSpeedChecksByMonitorId: sinon.stub(), - deleteNotificationsByMonitorId: sinon.stub(), - deleteTeam: sinon.stub(), - deleteAllOtherUsers: sinon.stub(), - deleteMonitorsByUserId: sinon.stub(), - deleteUser: sinon.stub(), - }, - jobQueue: { - deleteJob: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); + let req, res, next, handleError; + beforeEach(() => { + req = { + headers: { + authorization: "Bearer token", + }, + db: { + getUserByEmail: sinon.stub(), + getMonitorsByTeamId: sinon.stub(), + deleteJob: sinon.stub(), + deleteChecks: sinon.stub(), + deletePageSpeedChecksByMonitorId: sinon.stub(), + deleteNotificationsByMonitorId: sinon.stub(), + deleteTeam: sinon.stub(), + deleteAllOtherUsers: sinon.stub(), + deleteMonitorsByUserId: sinon.stub(), + deleteUser: sinon.stub(), + }, + jobQueue: { + deleteJob: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); - sinon.stub(jwt, "decode"); + sinon.stub(jwt, "decode"); - handleError = sinon.stub(); - }); + handleError = sinon.stub(); + }); - afterEach(() => { - sinon.restore(); - }); - it("should return 404 if user is not found", async () => { - jwt.decode.returns({ email: "test@example.com" }); - req.db.getUserByEmail.resolves(null); + afterEach(() => { + sinon.restore(); + }); + it("should return 404 if user is not found", async () => { + jwt.decode.returns({ email: "test@example.com" }); + req.db.getUserByEmail.resolves(null); - await deleteUser(req, res, next); + await deleteUser(req, res, next); - expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; - expect(next.calledOnce).to.be.true; - expect(next.firstCall.args[0].message).to.equal( - errorMessages.DB_USER_NOT_FOUND - ); - expect(res.status.notCalled).to.be.true; - expect(res.json.notCalled).to.be.true; - }); + expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; + expect(next.calledOnce).to.be.true; + expect(next.firstCall.args[0].message).to.equal(errorMessages.DB_USER_NOT_FOUND); + expect(res.status.notCalled).to.be.true; + expect(res.json.notCalled).to.be.true; + }); - it("should delete user and associated data if user is superadmin", async () => { - const user = { - _id: "user_id", - email: "test@example.com", - role: ["superadmin"], - teamId: "team_id", - }; - const monitors = [{ _id: "monitor_id" }]; + it("should delete user and associated data if user is superadmin", async () => { + const user = { + _id: "user_id", + email: "test@example.com", + role: ["superadmin"], + teamId: "team_id", + }; + const monitors = [{ _id: "monitor_id" }]; - jwt.decode.returns({ email: "test@example.com" }); - req.db.getUserByEmail.resolves(user); - req.db.getMonitorsByTeamId.resolves({ monitors }); + jwt.decode.returns({ email: "test@example.com" }); + req.db.getUserByEmail.resolves(user); + req.db.getMonitorsByTeamId.resolves({ monitors }); - await deleteUser(req, res, next); + await deleteUser(req, res, next); - expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; - expect( - req.db.getMonitorsByTeamId.calledOnceWith({ - params: { teamId: "team_id" }, - }) - ).to.be.true; - expect(req.jobQueue.deleteJob.calledOnceWith(monitors[0])).to.be.true; - expect(req.db.deleteChecks.calledOnceWith("monitor_id")).to.be.true; - expect(req.db.deletePageSpeedChecksByMonitorId.calledOnceWith("monitor_id")) - .to.be.true; - expect(req.db.deleteNotificationsByMonitorId.calledOnceWith("monitor_id")) - .to.be.true; - expect(req.db.deleteTeam.calledOnceWith("team_id")).to.be.true; - expect(req.db.deleteAllOtherUsers.calledOnce).to.be.true; - expect(req.db.deleteMonitorsByUserId.calledOnceWith("user_id")).to.be.true; - expect(req.db.deleteUser.calledOnceWith("user_id")).to.be.true; - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.AUTH_DELETE_USER, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; + expect( + req.db.getMonitorsByTeamId.calledOnceWith({ + params: { teamId: "team_id" }, + }) + ).to.be.true; + expect(req.jobQueue.deleteJob.calledOnceWith(monitors[0])).to.be.true; + expect(req.db.deleteChecks.calledOnceWith("monitor_id")).to.be.true; + expect(req.db.deletePageSpeedChecksByMonitorId.calledOnceWith("monitor_id")).to.be + .true; + expect(req.db.deleteNotificationsByMonitorId.calledOnceWith("monitor_id")).to.be.true; + expect(req.db.deleteTeam.calledOnceWith("team_id")).to.be.true; + expect(req.db.deleteAllOtherUsers.calledOnce).to.be.true; + expect(req.db.deleteMonitorsByUserId.calledOnceWith("user_id")).to.be.true; + expect(req.db.deleteUser.calledOnceWith("user_id")).to.be.true; + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.AUTH_DELETE_USER, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should delete user if user is not superadmin", async () => { - const user = { - _id: "user_id", - email: "test@example.com", - role: ["user"], - teamId: "team_id", - }; + it("should delete user if user is not superadmin", async () => { + const user = { + _id: "user_id", + email: "test@example.com", + role: ["user"], + teamId: "team_id", + }; - jwt.decode.returns({ email: "test@example.com" }); - req.db.getUserByEmail.resolves(user); + jwt.decode.returns({ email: "test@example.com" }); + req.db.getUserByEmail.resolves(user); - await deleteUser(req, res, next); + await deleteUser(req, res, next); - expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; - expect( - req.db.getMonitorsByTeamId.calledOnceWith({ - params: { teamId: "team_id" }, - }) - ).to.be.true; - expect(req.db.deleteUser.calledOnceWith("user_id")).to.be.true; - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.AUTH_DELETE_USER, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + expect(req.db.getUserByEmail.calledOnceWith("test@example.com")).to.be.true; + expect( + req.db.getMonitorsByTeamId.calledOnceWith({ + params: { teamId: "team_id" }, + }) + ).to.be.true; + expect(req.db.deleteUser.calledOnceWith("user_id")).to.be.true; + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.AUTH_DELETE_USER, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should handle errors", async () => { - const error = new Error("Something went wrong"); - const SERVICE_NAME = "AuthController"; - jwt.decode.returns({ email: "test@example.com" }); - req.db.getUserByEmail.rejects(error); - await deleteUser(req, res, next); - expect(next.calledOnce).to.be.true; - expect(next.firstCall.args[0].message).to.equal("Something went wrong"); - expect(res.status.notCalled).to.be.true; - expect(res.json.notCalled).to.be.true; - }); + it("should handle errors", async () => { + const error = new Error("Something went wrong"); + const SERVICE_NAME = "AuthController"; + jwt.decode.returns({ email: "test@example.com" }); + req.db.getUserByEmail.rejects(error); + await deleteUser(req, res, next); + expect(next.calledOnce).to.be.true; + expect(next.firstCall.args[0].message).to.equal("Something went wrong"); + expect(res.status.notCalled).to.be.true; + expect(res.json.notCalled).to.be.true; + }); }); describe("Auth Controller - getAllUsers", () => { - let req, res, next; + let req, res, next; - beforeEach(() => { - req = { - db: { - getAllUsers: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); + beforeEach(() => { + req = { + db: { + getAllUsers: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); - afterEach(() => { - sinon.restore(); // Restore the original methods after each test - }); + afterEach(() => { + sinon.restore(); // Restore the original methods after each test + }); - it("should return 200 and all users", async () => { - const allUsers = [{ id: 1, name: "John Doe" }]; - req.db.getAllUsers.resolves(allUsers); + it("should return 200 and all users", async () => { + const allUsers = [{ id: 1, name: "John Doe" }]; + req.db.getAllUsers.resolves(allUsers); - await getAllUsers(req, res, next); + await getAllUsers(req, res, next); - expect(req.db.getAllUsers.calledOnce).to.be.true; - expect(res.status.calledOnceWith(200)).to.be.true; - expect( - res.json.calledOnceWith({ - success: true, - msg: "Got all users", - data: allUsers, - }) - ).to.be.true; - expect(next.notCalled).to.be.true; - }); + expect(req.db.getAllUsers.calledOnce).to.be.true; + expect(res.status.calledOnceWith(200)).to.be.true; + expect( + res.json.calledOnceWith({ + success: true, + msg: "Got all users", + data: allUsers, + }) + ).to.be.true; + expect(next.notCalled).to.be.true; + }); - it("should call next with error when an exception occurs", async () => { - const error = new Error("Something went wrong"); - req.db.getAllUsers.rejects(error); - await getAllUsers(req, res, next); - expect(req.db.getAllUsers.calledOnce).to.be.true; - expect(next.calledOnce).to.be.true; - expect(res.status.notCalled).to.be.true; - expect(res.json.notCalled).to.be.true; - }); + it("should call next with error when an exception occurs", async () => { + const error = new Error("Something went wrong"); + req.db.getAllUsers.rejects(error); + await getAllUsers(req, res, next); + expect(req.db.getAllUsers.calledOnce).to.be.true; + expect(next.calledOnce).to.be.true; + expect(res.status.notCalled).to.be.true; + expect(res.json.notCalled).to.be.true; + }); }); diff --git a/Server/tests/controllers/controllerUtils.test.js b/Server/tests/controllers/controllerUtils.test.js index 353827084..55c16b857 100644 --- a/Server/tests/controllers/controllerUtils.test.js +++ b/Server/tests/controllers/controllerUtils.test.js @@ -204,7 +204,7 @@ describe("controllerUtils - fetchMonitorCertificate", () => { try { await fetchMonitorCertificate(tls, monitor); } catch (error) { - console.log(error); + expect(error.message).to.equal("Certificate error"); } }); }); diff --git a/Server/tests/controllers/monitorController.test.js b/Server/tests/controllers/monitorController.test.js index 235c26627..b14626204 100644 --- a/Server/tests/controllers/monitorController.test.js +++ b/Server/tests/controllers/monitorController.test.js @@ -1,1017 +1,1017 @@ import { - getAllMonitors, - getMonitorStatsById, - getMonitorCertificate, - getMonitorById, - getMonitorsAndSummaryByTeamId, - getMonitorsByTeamId, - createMonitor, - deleteMonitor, - deleteAllMonitors, - editMonitor, - pauseMonitor, - addDemoMonitors, + getAllMonitors, + getMonitorStatsById, + getMonitorCertificate, + getMonitorById, + getMonitorsAndSummaryByTeamId, + getMonitorsByTeamId, + createMonitor, + deleteMonitor, + deleteAllMonitors, + editMonitor, + pauseMonitor, + addDemoMonitors, } from "../../controllers/monitorController.js"; import jwt from "jsonwebtoken"; import sinon from "sinon"; import { successMessages } from "../../utils/messages.js"; import logger from "../../utils/logger.js"; +import * as monitorController from "../../controllers/monitorController.js"; +import { fetchMonitorCertificate } from "../../controllers/controllerUtils.js"; + const SERVICE_NAME = "monitorController"; describe("Monitor Controller - getAllMonitors", () => { - let req, res, next; - beforeEach(() => { - req = { - params: {}, - query: {}, - body: {}, - db: { - getAllMonitors: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if DB operations fail", async () => { - req.db.getAllMonitors.throws(new Error("DB error")); - await getAllMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); + let req, res, next; + beforeEach(() => { + req = { + params: {}, + query: {}, + body: {}, + db: { + getAllMonitors: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if DB operations fail", async () => { + req.db.getAllMonitors.throws(new Error("DB error")); + await getAllMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); - it("should return success message and data if all operations succeed", async () => { - const data = [{ monitor: "data" }]; - req.db.getAllMonitors.returns(data); - await getAllMonitors(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_GET_ALL, - data: data, - }) - ).to.be.true; - }); + it("should return success message and data if all operations succeed", async () => { + const data = [{ monitor: "data" }]; + req.db.getAllMonitors.returns(data); + await getAllMonitors(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_GET_ALL, + data: data, + }) + ).to.be.true; + }); }); describe("Monitor Controller - getMonitorStatsById", () => { - let req, res, next; - beforeEach(() => { - req = { - params: { - monitorId: "123", - }, - query: {}, - body: {}, - db: { - getMonitorStatsById: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); + let req, res, next; + beforeEach(() => { + req = { + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorStatsById: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await getMonitorStatsById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if query validation fails", async () => { - req.query = { invalid: 1 }; - await getMonitorStatsById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB operations fail", async () => { - req.db.getMonitorStatsById.throws(new Error("DB error")); - await getMonitorStatsById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should return success message and data if all operations succeed", async () => { - const data = [{ monitorStats: "data" }]; - req.db.getMonitorStatsById.returns(data); - await getMonitorStatsById(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_STATS_BY_ID, - data: data, - }) - ).to.be.true; - }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await getMonitorStatsById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if query validation fails", async () => { + req.query = { invalid: 1 }; + await getMonitorStatsById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB operations fail", async () => { + req.db.getMonitorStatsById.throws(new Error("DB error")); + await getMonitorStatsById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should return success message and data if all operations succeed", async () => { + const data = [{ monitorStats: "data" }]; + req.db.getMonitorStatsById.returns(data); + await getMonitorStatsById(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_STATS_BY_ID, + data: data, + }) + ).to.be.true; + }); }); -// describe("Monitor Controller - getMonitorCertificate", () => { -// let req, res, next, sslCheckerStub; -// beforeEach(() => { -// req = { -// params: { -// monitorId: "123", -// }, -// query: {}, -// body: {}, -// db: { -// getMonitorById: sinon.stub(), -// }, -// }; -// res = { -// status: sinon.stub().returnsThis(), -// json: sinon.stub(), -// }; -// next = sinon.stub(); -// }); +describe("Monitor Controller - getMonitorCertificate", () => { + let req, res, next, fetchMonitorCertificate; + beforeEach(() => { + req = { + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorById: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + fetchMonitorCertificate = sinon.stub(); + }); -// afterEach(() => { -// sinon.restore(); -// }); + afterEach(() => { + sinon.restore(); + }); -// it("should reject with an error if param validation fails", async () => { -// req.params = {}; -// await getMonitorCertificate(req, res, next); -// expect(next.firstCall.args[0]).to.be.an("error"); -// expect(next.firstCall.args[0].status).to.equal(422); -// }); -// it("should reject with an error if creating a URL fails", async () => { -// req.db.getMonitorById.returns(null); -// await getMonitorCertificate(req, res, next); -// expect(next.firstCall.args[0]).to.be.an("error"); -// expect(next.firstCall.args[0]).to.be.instanceOf(TypeError); -// }); -// it("should reject with an error if SSL checker fails", async () => { -// req.db.getMonitorById.returns({ url: "https://example.com" }); -// await monitorController.getMonitorCertificate(req, res, next); -// expect(next.firstCall.args[0]).to.be.an("error"); -// expect(next.firstCall.args[0].message).to.equal("SSL checker error"); -// }); -// it("should return success message and data if all operations succeed", async () => { -// req.db.getMonitorById.returns({ url: "https://example.com" }); -// const certificate = { validTo: 1 }; -// sslCheckerStub.returns(certificate); -// await getMonitorCertificate(req, res, next); -// expect(res.status.firstCall.args[0]).to.equal(200); -// expect( -// res.json.calledOnceWith({ -// success: true, -// msg: successMessages.MONITOR_CERTIFICATE, -// data: { -// certificateDate: new Date(certificate.validTo).toLocaleDateString(), -// }, -// }) -// ).to.be.true; -// }); -// it("should return success message and N/A if certificate is not found", async () => { -// req.db.getMonitorById.returns({ url: "https://example.com" }); -// // sslCheckerStub.returns(null); -// await getMonitorCertificate(req, res, next); -// expect(res.status.firstCall.args[0]).to.equal(200); -// expect( -// res.json.calledOnceWith({ -// success: true, -// msg: successMessages.MONITOR_CERTIFICATE, -// data: { -// certificateDate: "N/A", -// }, -// }) -// ).to.be.true; -// }); - -// it("should return success message and N/A if certificate doesn't have validTo", async () => { -// req.db.getMonitorById.returns({ url: "https://example.com" }); -// // sslCheckerStub.returns({ valid: 1 }); -// await getMonitorCertificate(req, res, next); -// expect(res.status.firstCall.args[0]).to.equal(200); -// expect( -// res.json.calledOnceWith({ -// success: true, -// msg: successMessages.MONITOR_CERTIFICATE, -// data: { -// certificateDate: "N/A", -// }, -// }) -// ).to.be.true; -// }); -// }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await getMonitorCertificate(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if getMonitorById operation fails", async () => { + req.db.getMonitorById.throws(new Error("DB error")); + await getMonitorCertificate(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should return success message and data if all operations succeed with a valid cert", async () => { + req.db.getMonitorById.returns({ url: "https://www.google.com" }); + const data = { certificate: "cert", validTo: "2024/08/08" }; + fetchMonitorCertificate.returns(data); + await getMonitorCertificate(req, res, next, fetchMonitorCertificate); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_CERTIFICATE, + data: { certificateDate: new Date(data.validTo) }, + }) + ).to.be.true; + }); + it("should return success message and data if all operations succeed with an invalid cert", async () => { + req.db.getMonitorById.returns({ url: "https://www.google.com" }); + fetchMonitorCertificate.returns({}); + await getMonitorCertificate(req, res, next, fetchMonitorCertificate); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_CERTIFICATE, + data: { certificateDate: "N/A" }, + }) + ).to.be.true; + }); + it("should return an error if fetchMonitorCertificate fails", async () => { + req.db.getMonitorById.returns({ url: "https://www.google.com" }); + fetchMonitorCertificate.throws(new Error("Certificate error")); + await getMonitorCertificate(req, res, next, fetchMonitorCertificate); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Certificate error"); + }); +}); describe("Monitor Controller - getMonitorById", () => { - let req, res, next; - beforeEach(() => { - req = { - params: { - monitorId: "123", - }, - query: {}, - body: {}, - db: { - getMonitorById: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await getMonitorById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if query param validation fails", async () => { - req.query = { invalid: 1 }; - await getMonitorById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB operations fail", async () => { - req.db.getMonitorById.throws(new Error("DB error")); - await getMonitorById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should return 404 if a monitor is not found", async () => { - req.db.getMonitorById.returns(null); - await getMonitorById(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(404); - }); - it("should return success message and data if all operations succeed", async () => { - const data = { monitor: "data" }; - req.db.getMonitorById.returns(data); - await getMonitorById(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_GET_BY_ID, - data: data, - }) - ).to.be.true; - }); + let req, res, next; + beforeEach(() => { + req = { + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorById: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await getMonitorById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if query param validation fails", async () => { + req.query = { invalid: 1 }; + await getMonitorById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB operations fail", async () => { + req.db.getMonitorById.throws(new Error("DB error")); + await getMonitorById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should return 404 if a monitor is not found", async () => { + req.db.getMonitorById.returns(null); + await getMonitorById(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(404); + }); + it("should return success message and data if all operations succeed", async () => { + const data = { monitor: "data" }; + req.db.getMonitorById.returns(data); + await getMonitorById(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_GET_BY_ID, + data: data, + }) + ).to.be.true; + }); }); describe("Monitor Controller - getMonitorsAndSummaryByTeamId", () => { - let req, res, next; - beforeEach(() => { - req = { - params: { - teamId: "123", - }, - query: {}, - body: {}, - db: { - getMonitorsAndSummaryByTeamId: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); + let req, res, next; + beforeEach(() => { + req = { + params: { + teamId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorsAndSummaryByTeamId: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await getMonitorsAndSummaryByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if query validation fails", async () => { - req.query = { invalid: 1 }; - await getMonitorsAndSummaryByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB operations fail", async () => { - req.db.getMonitorsAndSummaryByTeamId.throws(new Error("DB error")); - await getMonitorsAndSummaryByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should return success message and data if all operations succeed", async () => { - const data = { monitors: "data", summary: "data" }; - req.db.getMonitorsAndSummaryByTeamId.returns(data); - await getMonitorsAndSummaryByTeamId(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.teamId), - data: data, - }) - ).to.be.true; - }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await getMonitorsAndSummaryByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if query validation fails", async () => { + req.query = { invalid: 1 }; + await getMonitorsAndSummaryByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB operations fail", async () => { + req.db.getMonitorsAndSummaryByTeamId.throws(new Error("DB error")); + await getMonitorsAndSummaryByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should return success message and data if all operations succeed", async () => { + const data = { monitors: "data", summary: "data" }; + req.db.getMonitorsAndSummaryByTeamId.returns(data); + await getMonitorsAndSummaryByTeamId(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.teamId), + data: data, + }) + ).to.be.true; + }); }); describe("Monitor Controller - getMonitorsByTeamId", () => { - let req, res, next; - beforeEach(() => { - req = { - params: { - teamId: "123", - }, - query: {}, - body: {}, - db: { - getMonitorsByTeamId: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await getMonitorsByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if query validation fails", async () => { - req.query = { invalid: 1 }; - await getMonitorsByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB operations fail", async () => { - req.db.getMonitorsByTeamId.throws(new Error("DB error")); - await getMonitorsByTeamId(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should return success message and data if all operations succeed", async () => { - const data = { monitors: "data" }; - req.db.getMonitorsByTeamId.returns(data); - await getMonitorsByTeamId(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.teamId), - data: data, - }) - ).to.be.true; - }); + let req, res, next; + beforeEach(() => { + req = { + params: { + teamId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorsByTeamId: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await getMonitorsByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if query validation fails", async () => { + req.query = { invalid: 1 }; + await getMonitorsByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB operations fail", async () => { + req.db.getMonitorsByTeamId.throws(new Error("DB error")); + await getMonitorsByTeamId(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should return success message and data if all operations succeed", async () => { + const data = { monitors: "data" }; + req.db.getMonitorsByTeamId.returns(data); + await getMonitorsByTeamId(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.teamId), + data: data, + }) + ).to.be.true; + }); }); describe("Monitor Controller - createMonitor", () => { - let req, res, next; - beforeEach(() => { - req = { - params: {}, - query: {}, - body: { - userId: "123", - teamId: "123", - name: "test_monitor", - description: "test_monitor_desc", - type: "http", - url: "https://example.com", - notifications: [{ email: "example@example.com" }], - }, - db: { - createMonitor: sinon.stub(), - createNotification: sinon.stub(), - }, - jobQueue: { - addJob: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if body validation fails", async () => { - req.body = {}; - await createMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB createMonitor operation fail", async () => { - req.db.createMonitor.throws(new Error("DB error")); - await createMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if DB createNotification operation fail", async () => { - req.db.createNotification.throws(new Error("DB error")); - req.db.createMonitor.returns({ _id: "123" }); - await createMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if monitor.save operation fail", async () => { - req.db.createMonitor.returns({ - _id: "123", - save: sinon.stub().throws(new Error("Monitor save error")), - }); - await createMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Monitor save error"); - }); - it("should throw an error if addJob operation fails", async () => { - req.db.createMonitor.returns({ _id: "123", save: sinon.stub() }); - req.jobQueue.addJob.throws(new Error("Job error")); - await createMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Job error"); - }); - it("should return success message and data if all operations succeed with empty notifications", async () => { - req.body.notifications = []; - const monitor = { _id: "123", save: sinon.stub() }; - req.db.createMonitor.returns(monitor); - await createMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(201); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_CREATE, - data: monitor, - }) - ).to.be.true; - }); - it("should return success message and data if all operations succeed", async () => { - const monitor = { _id: "123", save: sinon.stub() }; - req.db.createMonitor.returns(monitor); - await createMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(201); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_CREATE, - data: monitor, - }) - ).to.be.true; - }); + let req, res, next; + beforeEach(() => { + req = { + params: {}, + query: {}, + body: { + userId: "123", + teamId: "123", + name: "test_monitor", + description: "test_monitor_desc", + type: "http", + url: "https://example.com", + notifications: [{ email: "example@example.com" }], + }, + db: { + createMonitor: sinon.stub(), + createNotification: sinon.stub(), + }, + jobQueue: { + addJob: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if body validation fails", async () => { + req.body = {}; + await createMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB createMonitor operation fail", async () => { + req.db.createMonitor.throws(new Error("DB error")); + await createMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if DB createNotification operation fail", async () => { + req.db.createNotification.throws(new Error("DB error")); + req.db.createMonitor.returns({ _id: "123" }); + await createMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if monitor.save operation fail", async () => { + req.db.createMonitor.returns({ + _id: "123", + save: sinon.stub().throws(new Error("Monitor save error")), + }); + await createMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Monitor save error"); + }); + it("should throw an error if addJob operation fails", async () => { + req.db.createMonitor.returns({ _id: "123", save: sinon.stub() }); + req.jobQueue.addJob.throws(new Error("Job error")); + await createMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Job error"); + }); + it("should return success message and data if all operations succeed with empty notifications", async () => { + req.body.notifications = []; + const monitor = { _id: "123", save: sinon.stub() }; + req.db.createMonitor.returns(monitor); + await createMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(201); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_CREATE, + data: monitor, + }) + ).to.be.true; + }); + it("should return success message and data if all operations succeed", async () => { + const monitor = { _id: "123", save: sinon.stub() }; + req.db.createMonitor.returns(monitor); + await createMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(201); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_CREATE, + data: monitor, + }) + ).to.be.true; + }); }); describe("Monitor Controller - deleteMonitor", () => { - let req, res, next; - beforeEach(() => { - req = { - params: { - monitorId: "123", - }, - query: {}, - body: {}, - db: { - deleteMonitor: sinon.stub(), - deleteChecks: sinon.stub(), - deletePageSpeedChecksByMonitorId: sinon.stub(), - deleteNotificationsByMonitorId: sinon.stub(), - }, - jobQueue: { - deleteJob: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - sinon.stub(logger, "error"); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await deleteMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if DB deleteMonitor operation fail", async () => { - req.db.deleteMonitor.throws(new Error("DB error")); - await deleteMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should log an error if deleteJob throws an error", async () => { - const error = new Error("Job error"); - const monitor = { name: "test_monitor", _id: "123" }; - req.db.deleteMonitor.returns(monitor); - req.jobQueue.deleteJob.rejects(error); - await deleteMonitor(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.equal( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` - ); - expect(logger.error.firstCall.args[1]).to.deep.equal({ - method: "deleteMonitor", - service: SERVICE_NAME, - error: error.message, - }); - }); - it("should log an error if deleteChecks throws an error", async () => { - const error = new Error("Checks error"); - const monitor = { name: "test_monitor", _id: "123" }; - req.db.deleteMonitor.returns(monitor); - req.db.deleteChecks.rejects(error); - await deleteMonitor(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.equal( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` - ); - expect(logger.error.firstCall.args[1]).to.deep.equal({ - method: "deleteMonitor", - service: SERVICE_NAME, - error: error.message, - }); - }); - it("should log an error if deletePageSpeedChecksByMonitorId throws an error", async () => { - const error = new Error("PageSpeed error"); - const monitor = { name: "test_monitor", _id: "123" }; - req.db.deleteMonitor.returns(monitor); - req.db.deletePageSpeedChecksByMonitorId.rejects(error); - await deleteMonitor(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.equal( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` - ); - expect(logger.error.firstCall.args[1]).to.deep.equal({ - method: "deleteMonitor", - service: SERVICE_NAME, - error: error.message, - }); - }); - it("should log an error if deleteNotificationsByMonitorId throws an error", async () => { - const error = new Error("Notifications error"); - const monitor = { name: "test_monitor", _id: "123" }; - req.db.deleteMonitor.returns(monitor); - req.db.deleteNotificationsByMonitorId.rejects(error); - await deleteMonitor(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.equal( - `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` - ); - expect(logger.error.firstCall.args[1]).to.deep.equal({ - method: "deleteMonitor", - service: SERVICE_NAME, - error: error.message, - }); - }); - it("should return success message if all operations succeed", async () => { - const monitor = { name: "test_monitor", _id: "123" }; - req.db.deleteMonitor.returns(monitor); - await deleteMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_DELETE, - }) - ).to.be.true; - }); + let req, res, next; + beforeEach(() => { + req = { + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + deleteMonitor: sinon.stub(), + deleteChecks: sinon.stub(), + deletePageSpeedChecksByMonitorId: sinon.stub(), + deleteNotificationsByMonitorId: sinon.stub(), + }, + jobQueue: { + deleteJob: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + sinon.stub(logger, "error"); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await deleteMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if DB deleteMonitor operation fail", async () => { + req.db.deleteMonitor.throws(new Error("DB error")); + await deleteMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should log an error if deleteJob throws an error", async () => { + const error = new Error("Job error"); + const monitor = { name: "test_monitor", _id: "123" }; + req.db.deleteMonitor.returns(monitor); + req.jobQueue.deleteJob.rejects(error); + await deleteMonitor(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.equal( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` + ); + expect(logger.error.firstCall.args[1]).to.deep.equal({ + method: "deleteMonitor", + service: SERVICE_NAME, + error: error.message, + }); + }); + it("should log an error if deleteChecks throws an error", async () => { + const error = new Error("Checks error"); + const monitor = { name: "test_monitor", _id: "123" }; + req.db.deleteMonitor.returns(monitor); + req.db.deleteChecks.rejects(error); + await deleteMonitor(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.equal( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` + ); + expect(logger.error.firstCall.args[1]).to.deep.equal({ + method: "deleteMonitor", + service: SERVICE_NAME, + error: error.message, + }); + }); + it("should log an error if deletePageSpeedChecksByMonitorId throws an error", async () => { + const error = new Error("PageSpeed error"); + const monitor = { name: "test_monitor", _id: "123" }; + req.db.deleteMonitor.returns(monitor); + req.db.deletePageSpeedChecksByMonitorId.rejects(error); + await deleteMonitor(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.equal( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` + ); + expect(logger.error.firstCall.args[1]).to.deep.equal({ + method: "deleteMonitor", + service: SERVICE_NAME, + error: error.message, + }); + }); + it("should log an error if deleteNotificationsByMonitorId throws an error", async () => { + const error = new Error("Notifications error"); + const monitor = { name: "test_monitor", _id: "123" }; + req.db.deleteMonitor.returns(monitor); + req.db.deleteNotificationsByMonitorId.rejects(error); + await deleteMonitor(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.equal( + `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}` + ); + expect(logger.error.firstCall.args[1]).to.deep.equal({ + method: "deleteMonitor", + service: SERVICE_NAME, + error: error.message, + }); + }); + it("should return success message if all operations succeed", async () => { + const monitor = { name: "test_monitor", _id: "123" }; + req.db.deleteMonitor.returns(monitor); + await deleteMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_DELETE, + }) + ).to.be.true; + }); }); describe("Monitor Controller - deleteAllMonitors", () => { - let req, res, next, stub; - beforeEach(() => { - stub = sinon.stub(jwt, "verify").callsFake(() => { - return { teamId: "123" }; - }); - req = { - headers: { - authorization: "Bearer token", - }, - params: { - monitorId: "123", - }, - query: {}, - body: {}, - db: { - deleteAllMonitors: sinon.stub(), - deleteChecks: sinon.stub(), - deletePageSpeedChecksByMonitorId: sinon.stub(), - deleteNotificationsByMonitorId: sinon.stub(), - }, - jobQueue: { - deleteJob: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - sinon.stub(logger, "error"); - }); - afterEach(() => { - sinon.restore(); - stub.restore(); - }); - it("should reject with an error if getTokenFromHeaders throws an error", async () => { - req.headers = {}; - await deleteAllMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("No auth headers"); - expect(next.firstCall.args[0].status).to.equal(500); - }); - it("should reject with an error if token validation fails", async () => { - stub.restore(); - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - await deleteAllMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.instanceOf(jwt.JsonWebTokenError); - }); - it("should reject with an error if DB deleteAllMonitors operation fail", async () => { - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.deleteAllMonitors.throws(new Error("DB error")); - await deleteAllMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should log an error if deleteJob throws an error", async () => { - const monitors = [{ name: "test_monitor", _id: "123" }]; - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); - const error = new Error("Job error"); - req.jobQueue.deleteJob.rejects(error); - await deleteAllMonitors(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.deep.equal( - `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` - ); - }); - it("should log an error if deleteChecks throws an error", async () => { - const monitors = [{ name: "test_monitor", _id: "123" }]; - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); - const error = new Error("Check error"); - req.db.deleteChecks.rejects(error); - await deleteAllMonitors(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.deep.equal( - `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` - ); - }); - it("should log an error if deletePageSpeedChecksByMonitorId throws an error", async () => { - const monitors = [{ name: "test_monitor", _id: "123" }]; - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); - const error = new Error("Pagespeed Check error"); - req.db.deletePageSpeedChecksByMonitorId.rejects(error); - await deleteAllMonitors(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.deep.equal( - `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` - ); - }); - it("should log an error if deleteNotificationsByMonitorId throws an error", async () => { - const monitors = [{ name: "test_monitor", _id: "123" }]; - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); - const error = new Error("Notifications Check error"); - req.db.deleteNotificationsByMonitorId.rejects(error); - await deleteAllMonitors(req, res, next); - expect(logger.error.calledOnce).to.be.true; - expect(logger.error.firstCall.args[0]).to.deep.equal( - `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` - ); - }); + let req, res, next, stub; + beforeEach(() => { + stub = sinon.stub(jwt, "verify").callsFake(() => { + return { teamId: "123" }; + }); + req = { + headers: { + authorization: "Bearer token", + }, + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + deleteAllMonitors: sinon.stub(), + deleteChecks: sinon.stub(), + deletePageSpeedChecksByMonitorId: sinon.stub(), + deleteNotificationsByMonitorId: sinon.stub(), + }, + jobQueue: { + deleteJob: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + sinon.stub(logger, "error"); + }); + afterEach(() => { + sinon.restore(); + stub.restore(); + }); + it("should reject with an error if getTokenFromHeaders throws an error", async () => { + req.headers = {}; + await deleteAllMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("No auth headers"); + expect(next.firstCall.args[0].status).to.equal(500); + }); + it("should reject with an error if token validation fails", async () => { + stub.restore(); + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + await deleteAllMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.instanceOf(jwt.JsonWebTokenError); + }); + it("should reject with an error if DB deleteAllMonitors operation fail", async () => { + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.throws(new Error("DB error")); + await deleteAllMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should log an error if deleteJob throws an error", async () => { + const monitors = [{ name: "test_monitor", _id: "123" }]; + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); + const error = new Error("Job error"); + req.jobQueue.deleteJob.rejects(error); + await deleteAllMonitors(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.deep.equal( + `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` + ); + }); + it("should log an error if deleteChecks throws an error", async () => { + const monitors = [{ name: "test_monitor", _id: "123" }]; + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); + const error = new Error("Check error"); + req.db.deleteChecks.rejects(error); + await deleteAllMonitors(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.deep.equal( + `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` + ); + }); + it("should log an error if deletePageSpeedChecksByMonitorId throws an error", async () => { + const monitors = [{ name: "test_monitor", _id: "123" }]; + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); + const error = new Error("Pagespeed Check error"); + req.db.deletePageSpeedChecksByMonitorId.rejects(error); + await deleteAllMonitors(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.deep.equal( + `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` + ); + }); + it("should log an error if deleteNotificationsByMonitorId throws an error", async () => { + const monitors = [{ name: "test_monitor", _id: "123" }]; + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.returns({ monitors, deletedCount: 1 }); + const error = new Error("Notifications Check error"); + req.db.deleteNotificationsByMonitorId.rejects(error); + await deleteAllMonitors(req, res, next); + expect(logger.error.calledOnce).to.be.true; + expect(logger.error.firstCall.args[0]).to.deep.equal( + `Error deleting associated records for monitor ${monitors[0]._id} with name ${monitors[0].name}` + ); + }); + it("should return success message if all operations succeed", async () => { + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.deleteAllMonitors.returns({ + monitors: [{ name: "test_monitor", _id: "123" }], + deletedCount: 1, + }); + await deleteAllMonitors(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: "Deleted 1 monitors", + }) + ).to.be.true; + }); }); describe("Monitor Controller - editMonitor", () => { - let req, res, next; - beforeEach(() => { - req = { - headers: {}, - params: { - monitorId: "123", - }, - query: {}, - body: { - notifications: [{ email: "example@example.com" }], - }, - db: { - getMonitorById: sinon.stub(), - editMonitor: sinon.stub(), - deleteNotificationsByMonitorId: sinon.stub(), - createNotification: sinon.stub(), - }, - jobQueue: { - deleteJob: sinon.stub(), - addJob: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if body validation fails", async () => { - req.body = { invalid: 1 }; - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if getMonitorById operation fails", async () => { - req.db.getMonitorById.throws(new Error("DB error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if editMonitor operation fails", async () => { - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.throws(new Error("DB error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if deleteNotificationsByMonitorId operation fails", async () => { - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns({ _id: "123" }); - req.db.deleteNotificationsByMonitorId.throws(new Error("DB error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if createNotification operation fails", async () => { - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns({ _id: "123" }); - req.db.createNotification.throws(new Error("DB error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if deleteJob operation fails", async () => { - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns({ _id: "123" }); - req.jobQueue.deleteJob.throws(new Error("Job error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Job error"); - }); - it("should reject with an error if addJob operation fails", async () => { - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns({ _id: "123" }); - req.jobQueue.addJob.throws(new Error("Add Job error")); - await editMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Add Job error"); - }); - it("should return success message with data if all operations succeed and empty notifications", async () => { - req.body.notifications = []; - const monitor = { _id: "123" }; - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns(monitor); - await editMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_EDIT, - data: monitor, - }) - ).to.be.true; - }); - it("should return success message with data if all operations succeed", async () => { - const monitor = { _id: "123" }; - req.db.getMonitorById.returns({ teamId: "123" }); - req.db.editMonitor.returns(monitor); - await editMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_EDIT, - data: monitor, - }) - ).to.be.true; - }); + let req, res, next; + beforeEach(() => { + req = { + headers: {}, + params: { + monitorId: "123", + }, + query: {}, + body: { + notifications: [{ email: "example@example.com" }], + }, + db: { + getMonitorById: sinon.stub(), + editMonitor: sinon.stub(), + deleteNotificationsByMonitorId: sinon.stub(), + createNotification: sinon.stub(), + }, + jobQueue: { + deleteJob: sinon.stub(), + addJob: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if body validation fails", async () => { + req.body = { invalid: 1 }; + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if getMonitorById operation fails", async () => { + req.db.getMonitorById.throws(new Error("DB error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if editMonitor operation fails", async () => { + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.throws(new Error("DB error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if deleteNotificationsByMonitorId operation fails", async () => { + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns({ _id: "123" }); + req.db.deleteNotificationsByMonitorId.throws(new Error("DB error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if createNotification operation fails", async () => { + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns({ _id: "123" }); + req.db.createNotification.throws(new Error("DB error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if deleteJob operation fails", async () => { + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns({ _id: "123" }); + req.jobQueue.deleteJob.throws(new Error("Job error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Job error"); + }); + it("should reject with an error if addJob operation fails", async () => { + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns({ _id: "123" }); + req.jobQueue.addJob.throws(new Error("Add Job error")); + await editMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Add Job error"); + }); + it("should return success message with data if all operations succeed and empty notifications", async () => { + req.body.notifications = []; + const monitor = { _id: "123" }; + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns(monitor); + await editMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_EDIT, + data: monitor, + }) + ).to.be.true; + }); + it("should return success message with data if all operations succeed", async () => { + const monitor = { _id: "123" }; + req.db.getMonitorById.returns({ teamId: "123" }); + req.db.editMonitor.returns(monitor); + await editMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_EDIT, + data: monitor, + }) + ).to.be.true; + }); }); describe("Monitor Controller - pauseMonitor", () => { - let req, res, next; - beforeEach(() => { - req = { - headers: {}, - params: { - monitorId: "123", - }, - query: {}, - body: {}, - db: { - getMonitorById: sinon.stub(), - }, - jobQueue: { - deleteJob: sinon.stub(), - addJob: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - }); + let req, res, next; + beforeEach(() => { + req = { + headers: {}, + params: { + monitorId: "123", + }, + query: {}, + body: {}, + db: { + getMonitorById: sinon.stub(), + }, + jobQueue: { + deleteJob: sinon.stub(), + addJob: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + }); - it("should reject with an error if param validation fails", async () => { - req.params = {}; - await pauseMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].status).to.equal(422); - }); - it("should reject with an error if getMonitorById operation fails", async () => { - req.db.getMonitorById.throws(new Error("DB error")); - await pauseMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if deleteJob operation fails", async () => { - const monitor = { _id: req.params.monitorId, isActive: true }; - req.db.getMonitorById.returns(monitor); - req.jobQueue.deleteJob.throws(new Error("Delete Job error")); - await pauseMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Delete Job error"); - }); + it("should reject with an error if param validation fails", async () => { + req.params = {}; + await pauseMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].status).to.equal(422); + }); + it("should reject with an error if getMonitorById operation fails", async () => { + req.db.getMonitorById.throws(new Error("DB error")); + await pauseMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if deleteJob operation fails", async () => { + const monitor = { _id: req.params.monitorId, isActive: true }; + req.db.getMonitorById.returns(monitor); + req.jobQueue.deleteJob.throws(new Error("Delete Job error")); + await pauseMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Delete Job error"); + }); - it("should reject with an error if addJob operation fails", async () => { - const monitor = { _id: req.params.monitorId, isActive: false }; - req.db.getMonitorById.returns(monitor); - req.jobQueue.addJob.throws(new Error("Add Job error")); - await pauseMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Add Job error"); - }); - it("should reject with an error if monitor.save operation fails", async () => { - const monitor = { - _id: req.params.monitorId, - active: false, - save: sinon.stub().throws(new Error("Save error")), - }; - req.db.getMonitorById.returns(monitor); - await pauseMonitor(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Save error"); - }); - it("should return success pause message with data if all operations succeed with inactive monitor", async () => { - const monitor = { - _id: req.params.monitorId, - isActive: false, - save: sinon.stub().resolves(), - }; - req.db.getMonitorById.returns(monitor); - await pauseMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_PAUSE, - data: monitor, - }) - ).to.be.true; - }); - it("should return success resume message with data if all operations succeed with active monitor", async () => { - const monitor = { - _id: req.params.monitorId, - isActive: true, - save: sinon.stub().resolves(), - }; - req.db.getMonitorById.returns(monitor); - await pauseMonitor(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_RESUME, - data: monitor, - }) - ).to.be.true; - }); + it("should reject with an error if addJob operation fails", async () => { + const monitor = { _id: req.params.monitorId, isActive: false }; + req.db.getMonitorById.returns(monitor); + req.jobQueue.addJob.throws(new Error("Add Job error")); + await pauseMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Add Job error"); + }); + it("should reject with an error if monitor.save operation fails", async () => { + const monitor = { + _id: req.params.monitorId, + active: false, + save: sinon.stub().throws(new Error("Save error")), + }; + req.db.getMonitorById.returns(monitor); + await pauseMonitor(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Save error"); + }); + it("should return success pause message with data if all operations succeed with inactive monitor", async () => { + const monitor = { + _id: req.params.monitorId, + isActive: false, + save: sinon.stub().resolves(), + }; + req.db.getMonitorById.returns(monitor); + await pauseMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_PAUSE, + data: monitor, + }) + ).to.be.true; + }); + it("should return success resume message with data if all operations succeed with active monitor", async () => { + const monitor = { + _id: req.params.monitorId, + isActive: true, + save: sinon.stub().resolves(), + }; + req.db.getMonitorById.returns(monitor); + await pauseMonitor(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_RESUME, + data: monitor, + }) + ).to.be.true; + }); }); describe("Monitor Controller - addDemoMonitors", () => { - let req, res, next, stub; - beforeEach(() => { - stub = sinon.stub(jwt, "verify").callsFake(() => { - return { _id: "123", teamId: "123" }; - }); - req = { - headers: { - authorization: "Bearer token", - }, - params: {}, - query: {}, - body: {}, - db: { - addDemoMonitors: sinon.stub(), - }, - settingsService: { - getSettings: sinon.stub(), - }, - jobQueue: { - addJob: sinon.stub(), - }, - }; - res = { - status: sinon.stub().returnsThis(), - json: sinon.stub(), - }; - next = sinon.stub(); - }); - afterEach(() => { - sinon.restore(); - stub.restore(); - }); - it("should reject with an error if getTokenFromHeaders fails", async () => { - req.headers = {}; - await addDemoMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("No auth headers"); - expect(next.firstCall.args[0].status).to.equal(500); - }); - it("should reject with an error if getting settings fails", async () => { - req.settingsService.getSettings.throws(new Error("Settings error")); - await addDemoMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Settings error"); - }); - it("should reject with an error if JWT validation fails", async () => { - stub.restore(); - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - await addDemoMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.instanceOf(jwt.JsonWebTokenError); - }); - it("should reject with an error if addDemoMonitors operation fails", async () => { - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.addDemoMonitors.throws(new Error("DB error")); - await addDemoMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("DB error"); - }); - it("should reject with an error if addJob operation fails", async () => { - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.addDemoMonitors.returns([{ _id: "123" }]); - req.jobQueue.addJob.throws(new Error("Add Job error")); - await addDemoMonitors(req, res, next); - expect(next.firstCall.args[0]).to.be.an("error"); - expect(next.firstCall.args[0].message).to.equal("Add Job error"); - }); - it("should return success message with data if all operations succeed", async () => { - const monitors = [{ _id: "123" }]; - req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); - req.db.addDemoMonitors.returns(monitors); - await addDemoMonitors(req, res, next); - expect(res.status.firstCall.args[0]).to.equal(200); - expect( - res.json.calledOnceWith({ - success: true, - msg: successMessages.MONITOR_DEMO_ADDED, - data: monitors.length, - }) - ).to.be.true; - }); + let req, res, next, stub; + beforeEach(() => { + stub = sinon.stub(jwt, "verify").callsFake(() => { + return { _id: "123", teamId: "123" }; + }); + req = { + headers: { + authorization: "Bearer token", + }, + params: {}, + query: {}, + body: {}, + db: { + addDemoMonitors: sinon.stub(), + }, + settingsService: { + getSettings: sinon.stub(), + }, + jobQueue: { + addJob: sinon.stub(), + }, + }; + res = { + status: sinon.stub().returnsThis(), + json: sinon.stub(), + }; + next = sinon.stub(); + }); + afterEach(() => { + sinon.restore(); + stub.restore(); + }); + it("should reject with an error if getTokenFromHeaders fails", async () => { + req.headers = {}; + await addDemoMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("No auth headers"); + expect(next.firstCall.args[0].status).to.equal(500); + }); + it("should reject with an error if getting settings fails", async () => { + req.settingsService.getSettings.throws(new Error("Settings error")); + await addDemoMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Settings error"); + }); + it("should reject with an error if JWT validation fails", async () => { + stub.restore(); + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + await addDemoMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.instanceOf(jwt.JsonWebTokenError); + }); + it("should reject with an error if addDemoMonitors operation fails", async () => { + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.addDemoMonitors.throws(new Error("DB error")); + await addDemoMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("DB error"); + }); + it("should reject with an error if addJob operation fails", async () => { + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.addDemoMonitors.returns([{ _id: "123" }]); + req.jobQueue.addJob.throws(new Error("Add Job error")); + await addDemoMonitors(req, res, next); + expect(next.firstCall.args[0]).to.be.an("error"); + expect(next.firstCall.args[0].message).to.equal("Add Job error"); + }); + it("should return success message with data if all operations succeed", async () => { + const monitors = [{ _id: "123" }]; + req.settingsService.getSettings.returns({ jwtSecret: "my_secret" }); + req.db.addDemoMonitors.returns(monitors); + await addDemoMonitors(req, res, next); + expect(res.status.firstCall.args[0]).to.equal(200); + expect( + res.json.calledOnceWith({ + success: true, + msg: successMessages.MONITOR_DEMO_ADDED, + data: monitors.length, + }) + ).to.be.true; + }); });