From 6a5ffdeb795c084845ba445e756369af20c1cd1b Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 7 Nov 2024 12:37:16 +0800 Subject: [PATCH] add tests for checkModule --- Server/tests/db/checkModule.test.js | 565 ++++++++++++++++++++++++++++ 1 file changed, 565 insertions(+) create mode 100644 Server/tests/db/checkModule.test.js diff --git a/Server/tests/db/checkModule.test.js b/Server/tests/db/checkModule.test.js new file mode 100644 index 000000000..96854b3f3 --- /dev/null +++ b/Server/tests/db/checkModule.test.js @@ -0,0 +1,565 @@ +import sinon from "sinon"; +import { + createCheck, + getChecksCount, + getChecks, + getTeamChecks, + deleteChecks, + deleteChecksByTeamId, + updateChecksTTL, +} from "../../db/mongo/modules/checkModule.js"; +import Check from "../../db/models/Check.js"; +import Monitor from "../../db/models/Monitor.js"; +import User from "../../db/models/User.js"; +import logger from "../../utils/logger.js"; + +describe("checkModule", () => { + describe("createCheck", () => { + let checkCountDocumentsStub, checkSaveStub, monitorFindByIdStub, monitorSaveStub; + const mockMonitor = { + _id: "123", + uptimePercentage: 0.5, + status: true, + save: () => this, + }; + const mockCheck = { active: true }; + beforeEach(() => { + checkSaveStub = sinon.stub(Check.prototype, "save"); + checkCountDocumentsStub = sinon.stub(Check, "countDocuments"); + monitorFindByIdStub = sinon.stub(Monitor, "findById"); + monitorSaveStub = sinon.stub(Monitor.prototype, "save"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should return undefined early if no monitor is found", async () => { + monitorFindByIdStub.returns(null); + const check = await createCheck({ monitorId: "123" }); + expect(check).to.be.undefined; + }); + + it("should return a check", async () => { + monitorFindByIdStub.returns(mockMonitor); + checkSaveStub.returns(mockCheck); + monitorSaveStub.returns(mockMonitor); + const check = await createCheck({ monitorId: "123", status: true }); + expect(check).to.deep.equal(mockCheck); + }); + it("should return a check if status is down", async () => { + mockMonitor.status = false; + monitorFindByIdStub.returns(mockMonitor); + checkSaveStub.returns(mockCheck); + monitorSaveStub.returns(mockMonitor); + const check = await createCheck({ monitorId: "123", status: false }); + expect(check).to.deep.equal(mockCheck); + }); + it("should return a check if uptimePercentage is undefined", async () => { + mockMonitor.uptimePercentage = undefined; + monitorFindByIdStub.returns(mockMonitor); + checkSaveStub.returns(mockCheck); + monitorSaveStub.returns(mockMonitor); + const check = await createCheck({ monitorId: "123", status: true }); + expect(check).to.deep.equal(mockCheck); + }); + it("should return a check if uptimePercentage is undefined and status is down", async () => { + mockMonitor.uptimePercentage = undefined; + monitorFindByIdStub.returns(mockMonitor); + checkSaveStub.returns(mockCheck); + monitorSaveStub.returns(mockMonitor); + const check = await createCheck({ monitorId: "123", status: false }); + expect(check).to.deep.equal(mockCheck); + }); + it("should monitor save error", async () => { + const err = new Error("Save Error"); + monitorSaveStub.throws(err); + try { + await createCheck({ monitorId: "123" }); + } catch (error) { + expect(error).to.deep.equal(err); + } + }); + it("should handle errors", async () => { + const err = new Error("DB Error"); + checkCountDocumentsStub.throws(err); + try { + await createCheck({ monitorId: "123" }); + } catch (error) { + expect(error).to.deep.equal(err); + } + }); + }); + describe("getChecksCount", () => { + let checkCountDocumentStub; + + beforeEach(() => { + checkCountDocumentStub = sinon.stub(Check, "countDocuments"); + }); + + afterEach(() => { + checkCountDocumentStub.restore(); + }); + + it("should return count with basic monitorId query", async () => { + const req = { + params: { monitorId: "test123" }, + query: {}, + }; + checkCountDocumentStub.resolves(5); + + const result = await getChecksCount(req); + + expect(result).to.equal(5); + expect(checkCountDocumentStub.calledOnce).to.be.true; + expect(checkCountDocumentStub.firstCall.args[0]).to.deep.equal({ + monitorId: "test123", + }); + }); + + it("should include dateRange in query when provided", async () => { + const req = { + params: { monitorId: "test123" }, + query: { dateRange: "day" }, + }; + checkCountDocumentStub.resolves(3); + + const result = await getChecksCount(req); + + expect(result).to.equal(3); + expect(checkCountDocumentStub.firstCall.args[0]).to.have.property("createdAt"); + expect(checkCountDocumentStub.firstCall.args[0].createdAt).to.have.property("$gte"); + }); + + it('should handle "all" filter correctly', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "all" }, + }; + checkCountDocumentStub.resolves(2); + + const result = await getChecksCount(req); + + expect(result).to.equal(2); + expect(checkCountDocumentStub.firstCall.args[0]).to.deep.equal({ + monitorId: "test123", + status: false, + }); + }); + + it('should handle "down" filter correctly', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "down" }, + }; + checkCountDocumentStub.resolves(2); + + const result = await getChecksCount(req); + + expect(result).to.equal(2); + expect(checkCountDocumentStub.firstCall.args[0]).to.deep.equal({ + monitorId: "test123", + status: false, + }); + }); + + it('should handle "resolve" filter correctly', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "resolve" }, + }; + checkCountDocumentStub.resolves(1); + + const result = await getChecksCount(req); + + expect(result).to.equal(1); + expect(checkCountDocumentStub.firstCall.args[0]).to.deep.equal({ + monitorId: "test123", + status: false, + statusCode: 5000, + }); + }); + it("should handle unknown filter correctly", async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "unknown" }, + }; + checkCountDocumentStub.resolves(1); + + const result = await getChecksCount(req); + + expect(result).to.equal(1); + expect(checkCountDocumentStub.firstCall.args[0]).to.deep.equal({ + monitorId: "test123", + status: false, + }); + }); + + it("should combine dateRange and filter in query", async () => { + const req = { + params: { monitorId: "test123" }, + query: { + dateRange: "week", + filter: "down", + }, + }; + checkCountDocumentStub.resolves(4); + + const result = await getChecksCount(req); + + expect(result).to.equal(4); + expect(checkCountDocumentStub.firstCall.args[0]).to.have.all.keys( + "monitorId", + "createdAt", + "status" + ); + }); + }); + describe("getChecks", () => { + let checkFindStub, monitorFindStub; + + beforeEach(() => { + checkFindStub = sinon.stub(Check, "find").returns({ + skip: sinon.stub().returns({ + limit: sinon.stub().returns({ + sort: sinon.stub().returns([{ id: 1 }, { id: 2 }]), + }), + }), + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should return checks with basic monitorId query", async () => { + const req = { + params: { monitorId: "test123" }, + query: {}, + }; + + const result = await getChecks(req); + + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + it("should return checks with limit query", async () => { + const req = { + params: { monitorId: "test123" }, + query: { limit: 10 }, + }; + + const result = await getChecks(req); + + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it("should handle pagination correctly", async () => { + const req = { + params: { monitorId: "test123" }, + query: { + page: 2, + rowsPerPage: 10, + }, + }; + + const result = await getChecks(req); + + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it("should handle dateRange filter", async () => { + const req = { + params: { monitorId: "test123" }, + query: { dateRange: "week" }, + }; + const result = await getChecks(req); + + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it('should handle "all" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "all" }, + }; + + await getChecks(req); + const result = await getChecks(req); + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + it('should handle "down" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "down" }, + }; + + await getChecks(req); + const result = await getChecks(req); + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it('should handle "resolve" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "resolve" }, + }; + + await getChecks(req); + const result = await getChecks(req); + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + it('should handle "unknown" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "unknown" }, + }; + + await getChecks(req); + const result = await getChecks(req); + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it("should handle ascending sort order", async () => { + const req = { + params: { monitorId: "test123" }, + query: { sortOrder: "asc" }, + }; + + await getChecks(req); + const result = await getChecks(req); + expect(result).to.deep.equal([{ id: 1 }, { id: 2 }]); + }); + + it("should handle error case", async () => { + const req = { + params: { monitorId: "test123" }, + query: {}, + }; + + checkFindStub.throws(new Error("Database error")); + + try { + await getChecks(req); + } catch (error) { + expect(error.message).to.equal("Database error"); + expect(error.service).to.equal("checkModule"); + expect(error.method).to.equal("getChecks"); + } + }); + }); + describe("getTeamChecks", () => { + let checkFindStub, checkCountDocumentsStub, monitorFindStub; + const mockMonitors = [{ _id: "123" }]; + beforeEach(() => { + monitorFindStub = sinon.stub(Monitor, "find").returns({ + select: sinon.stub().returns(mockMonitors), + }); + checkCountDocumentsStub = sinon.stub(Check, "countDocuments").returns(2); + checkFindStub = sinon.stub(Check, "find").returns({ + skip: sinon.stub().returns({ + limit: sinon.stub().returns({ + sort: sinon.stub().returns({ + select: sinon.stub().returns([{ id: 1 }, { id: 2 }]), + }), + }), + }), + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should return checks with basic monitorId query", async () => { + const req = { + params: { teamId: "test123" }, + query: {}, + }; + + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it("should handle pagination correctly", async () => { + const req = { + params: { monitorId: "test123" }, + query: { limit: 1, page: 2, rowsPerPage: 10 }, + }; + + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it("should handle dateRange filter", async () => { + const req = { + params: { monitorId: "test123" }, + query: { dateRange: "week" }, + }; + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it('should handle "all" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "all" }, + }; + + await getChecks(req); + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + it('should handle "down" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "down" }, + }; + + await getChecks(req); + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it('should handle "resolve" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "resolve" }, + }; + + await getChecks(req); + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + it('should handle "unknown" filter', async () => { + const req = { + params: { monitorId: "test123" }, + query: { filter: "unknown" }, + }; + + await getChecks(req); + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it("should handle ascending sort order", async () => { + const req = { + params: { monitorId: "test123" }, + query: { sortOrder: "asc" }, + }; + + await getChecks(req); + const result = await getTeamChecks(req); + expect(result).to.deep.equal({ checksCount: 2, checks: [{ id: 1 }, { id: 2 }] }); + }); + + it("should handle error case", async () => { + const req = { + params: { monitorId: "test123" }, + query: {}, + }; + + checkFindStub.throws(new Error("Database error")); + + try { + await getTeamChecks(req); + } catch (error) { + expect(error.message).to.equal("Database error"); + expect(error.service).to.equal("checkModule"); + expect(error.method).to.equal("getTeamChecks"); + } + }); + }); + describe("deleteChecks", () => { + let checkDeleteManyStub; + beforeEach(() => { + checkDeleteManyStub = sinon.stub(Check, "deleteMany").resolves({ deletedCount: 1 }); + }); + afterEach(() => { + sinon.restore(); + }); + + it("should return a value if a check is deleted", async () => { + const result = await deleteChecks("123"); + expect(result).to.equal(1); + }); + it("should handle an error", async () => { + checkDeleteManyStub.throws(new Error("Database error")); + try { + await deleteChecks("123"); + } catch (error) { + expect(error.message).to.equal("Database error"); + expect(error.method).to.equal("deleteChecks"); + } + }); + }); + describe("deleteChecksByTeamId", () => { + let mockMonitors = [{ _id: 123, save: () => this }]; + let monitorFindStub, monitorSaveStub, checkDeleteManyStub; + beforeEach(() => { + monitorSaveStub = sinon.stub(Monitor.prototype, "save"); + monitorFindStub = sinon.stub(Monitor, "find").returns(mockMonitors); + checkDeleteManyStub = sinon.stub(Check, "deleteMany").resolves({ deletedCount: 1 }); + }); + afterEach(() => { + sinon.restore(); + }); + it("should return a deleted count", async () => { + const result = await deleteChecksByTeamId("123"); + expect(result).to.equal(1); + }); + it("should handle errors", async () => { + const err = new Error("DB Error"); + monitorFindStub.throws(err); + try { + const result = await deleteChecksByTeamId("123"); + } catch (error) { + expect(error).to.deep.equal(err); + } + }); + }); + describe("updateChecksTTL", () => { + let userUpdateManyStub; + let loggerStub; + beforeEach(() => { + loggerStub = sinon.stub(logger, "error"); + userUpdateManyStub = sinon.stub(User, "updateMany"); + Check.collection = { dropIndex: sinon.stub(), createIndex: sinon.stub() }; + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should return undefined", async () => { + const result = await updateChecksTTL("123", 10); + expect(result).to.be.undefined; + }); + + it("should log an error if dropIndex throws an error", async () => { + const err = new Error("Drop Index Error"); + Check.collection.dropIndex.throws(err); + await updateChecksTTL("123", 10); + expect(loggerStub.calledOnce).to.be.true; + expect(loggerStub.firstCall.args[0].message).to.equal(err.message); + }); + + it("should throw an error if createIndex throws an error", async () => { + const err = new Error("Create Index Error"); + Check.collection.createIndex.throws(err); + try { + await updateChecksTTL("123", 10); + } catch (error) { + expect(error).to.deep.equal(err); + } + }); + it("should throw an error if User.updateMany throws an error", async () => { + const err = new Error("Update Many Error"); + userUpdateManyStub.throws(err); + try { + await updateChecksTTL("123", 10); + } catch (error) { + expect(error).to.deep.equal(err); + } + }); + }); +});