From 367b690f923646992be15770f1c207ea8eae087a Mon Sep 17 00:00:00 2001 From: FancMa01 Date: Tue, 5 Mar 2024 11:43:23 -0700 Subject: [PATCH] backend routes, models and and migration files for integration_mapping (#702) * backend routes, models and and migration files for integration_mapping * update integration.js * update integration_mapping * remove integration creation * add error messages, validation, and testing to all routes * remove lines --- server/job-scheduler.js | 11 +- server/jobs/integrationCreation.js | 59 ---- ...240301202952-remove_integration_columns.js | 24 ++ ...-create_integration_application_mapping.js | 49 +++ server/models/application.js | 9 +- server/models/integration_mapping.js | 58 ++++ server/routes/integrations/read.js | 166 +++++++---- server/server.js | 11 +- server/tests/mock-data/global.json | 3 +- server/tests/unit/integration.test.js | 166 +++++++---- server/tests/unit/jobmonitoring.test.js | 121 -------- server/tests/unit/notification.test.js | 77 ----- server/tests/unit/orbit.test.js | 279 ------------------ 13 files changed, 362 insertions(+), 671 deletions(-) delete mode 100644 server/jobs/integrationCreation.js create mode 100644 server/migrations/20240301202952-remove_integration_columns.js create mode 100644 server/migrations/20240301203455-create_integration_application_mapping.js create mode 100644 server/models/integration_mapping.js delete mode 100644 server/tests/unit/jobmonitoring.test.js delete mode 100644 server/tests/unit/notification.test.js delete mode 100644 server/tests/unit/orbit.test.js diff --git a/server/job-scheduler.js b/server/job-scheduler.js index 94137675e..3851a85cf 100644 --- a/server/job-scheduler.js +++ b/server/job-scheduler.js @@ -52,7 +52,8 @@ const { } = require("./jobSchedularMethods/orbitJobs.js"); //import job directly to run it only once on server start -const { createIntegrations } = require("./jobs/integrationCreation.js"); +//remove this +// const { createIntegrations } = require("./jobs/integrationCreation.js"); class JobScheduler { constructor() { @@ -128,7 +129,7 @@ class JobScheduler { await this.createOrbitMegaphoneJob(); //one off jobs on server start - await this.createIntegrations(); + // await this.createIntegrations(); })(); } @@ -345,9 +346,9 @@ class JobScheduler { return createOrbitMonitoringJob.call(this, { orbitMonitoring_id, cron }); } - createIntegrations() { - return createIntegrations.call(this); - } + // createIntegrations() { + // return createIntegrations.call(this); + // } } module.exports = new JobScheduler(); diff --git a/server/jobs/integrationCreation.js b/server/jobs/integrationCreation.js deleted file mode 100644 index 9bf34c1e7..000000000 --- a/server/jobs/integrationCreation.js +++ /dev/null @@ -1,59 +0,0 @@ -const { parentPort } = require("worker_threads"); - -const logger = require("../config/logger"); -const models = require("../models"); -const application = models.application; -const integrations = models.integrations; - -async function createIntegrations() { - try { - //grab all applications so we can have one entry per integration per application - const applications = await application.findAll({}); - - let integrationList = []; - - //build list of integrations - applications.map((application) => { - //for each application, add an object of each integration, for now we only have orbit - - if (process.env.ASR === "true") { - integrationList.push({ - application_id: application.id, - name: "ASR", - description: - "Enabling this integration will allow Tombolo to collect data from Orbit, FIDO, and other ASR sources in order to provide monitoring and alerting functionality. Additional fields will be made available in certain monitoring types as well.", - active: "false", - metaData: { - notificationEmails: "", - notificationWebhooks: "", - }, - }); - } - }); - - await Promise.all( - //create integrations, double checking they don't already exist - integrationList.map(async (integration) => { - let exists = await integrations.findOne({ - where: { - name: integration.name, - application_id: integration.application_id, - }, - raw: true, - }); - - //if it doesn't exist, create integration - if (!exists) { - await integrations.create(integration); - } - return true; - }) - ); - } catch (error) { - logger.error("Failed to create integrations, error: " + error); - } finally { - if (parentPort) parentPort.postMessage("done"); - } -} - -module.exports = { createIntegrations }; diff --git a/server/migrations/20240301202952-remove_integration_columns.js b/server/migrations/20240301202952-remove_integration_columns.js new file mode 100644 index 000000000..166b53f8c --- /dev/null +++ b/server/migrations/20240301202952-remove_integration_columns.js @@ -0,0 +1,24 @@ +"use strict"; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn("integrations", "config"); + await queryInterface.removeColumn("integrations", "metadata"); + await queryInterface.removeColumn("integrations", "active"); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.addColumn("integrations", "config", { + type: Sequelize.STRING, + allowNull: true, + }); + await queryInterface.addColumn("integrations", "metadata", { + type: Sequelize.STRING, + allowNull: true, + }); + await queryInterface.addColumn("integrations", "active", { + type: Sequelize.BOOLEAN, + defaultValue: true, + }); + }, +}; diff --git a/server/migrations/20240301203455-create_integration_application_mapping.js b/server/migrations/20240301203455-create_integration_application_mapping.js new file mode 100644 index 000000000..633e53d57 --- /dev/null +++ b/server/migrations/20240301203455-create_integration_application_mapping.js @@ -0,0 +1,49 @@ +"use strict"; +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("integration_mapping", { + id: { + allowNull: false, + primaryKey: true, + type: Sequelize.UUID, + defaultValue: Sequelize.UUIDV4, + }, + integration_id: { + type: Sequelize.UUID, + references: { + model: "integrations", + key: "id", + }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + }, + application_id: { + type: Sequelize.UUID, + references: { + model: "application", + key: "id", + }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + }, + metaData: { + type: Sequelize.JSON, + allowNull: true, + }, + createdAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, + updatedAt: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("integration_mapping"); + }, +}; diff --git a/server/models/application.js b/server/models/application.js index 4b60b23c9..4b1c5cdc8 100644 --- a/server/models/application.js +++ b/server/models/application.js @@ -1,7 +1,7 @@ -'use strict'; +"use strict"; module.exports = (sequelize, DataTypes) => { const application = sequelize.define( - 'application', + "application", { id: { primaryKey: true, @@ -101,8 +101,11 @@ module.exports = (sequelize, DataTypes) => { foreignKey: "application_id", onDelete: "CASCADE", }); + application.hasMany(models.integration_mapping, { + foreignKey: "application_id", + onDelete: "CASCADE", + }); }; - return application; }; diff --git a/server/models/integration_mapping.js b/server/models/integration_mapping.js new file mode 100644 index 000000000..7d06447e9 --- /dev/null +++ b/server/models/integration_mapping.js @@ -0,0 +1,58 @@ +"use strict"; +module.exports = (sequelize, DataTypes) => { + const IntegrationMapping = sequelize.define( + "integration_mapping", + { + id: { + type: DataTypes.UUID, + primaryKey: true, + defaultValue: DataTypes.UUIDV4, + allowNull: false, + }, + integration_id: { + type: DataTypes.UUID, + references: { + model: "integrations", + key: "id", + }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + }, + application_id: { + type: DataTypes.UUID, + references: { + model: "application", + key: "id", + }, + onUpdate: "CASCADE", + onDelete: "CASCADE", + }, + metaData: { + type: DataTypes.JSON, + allowNull: true, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + }, + }, + { freezeTableName: true } + ); + + IntegrationMapping.associate = (models) => { + IntegrationMapping.belongsTo(models.integrations, { + foreignKey: "integration_id", + }); + IntegrationMapping.belongsTo(models.application, { + foreignKey: "application_id", + }); + }; + + return IntegrationMapping; +}; diff --git a/server/routes/integrations/read.js b/server/routes/integrations/read.js index 78a9044b0..2eb0dc849 100644 --- a/server/routes/integrations/read.js +++ b/server/routes/integrations/read.js @@ -1,6 +1,6 @@ const models = require("../../models"); const integrations = models.integrations; -let application = models.application; +const integration_mapping = models.integration_mapping; const express = require("express"); const router = express.Router(); const path = require("path"); @@ -8,101 +8,149 @@ const fs = require("fs"); const rootENV = path.join(process.cwd(), "..", ".env"); const serverENV = path.join(process.cwd(), ".env"); const ENVPath = fs.existsSync(rootENV) ? rootENV : serverENV; -const { param, validationResult } = require("express-validator"); -const validatorUtil = require("../../utils/validator"); +const { param, body, validationResult } = require("express-validator"); require("dotenv").config({ path: ENVPath }); +//return all integrations +router.get("/getAll", async (req, res) => { + try { + console.log("running"); + const result = await integrations.findAll(); + res.status(200).send(result); + } catch (err) { + // ... error checks + console.log(err); + res.status(500).send("Failed to get integrations: " + err); + } +}); + +//get all integration_mappings with application_id router.get( - "/get/:application_id", - [param("application_id").isUUID(4).withMessage("Invalid application id")], + "/getAll/:application_id", + [param("application_id").isUUID()], async (req, res) => { - const errors = validationResult(req).formatWith( - validatorUtil.errorFormatter - ); + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } try { - if (!errors.isEmpty()) - return res.status(422).json({ success: false, errors: errors.array() }); const { application_id } = req.params; - if (!application_id) throw Error("Invalid app ID"); - - const result = await integrations.findAll({ + const result = await integration_mapping.findAll({ where: { application_id, }, }); - res.status(200).send(result); } catch (err) { // ... error checks console.log(err); + res.status(500).send("Failed to get integration mappings: " + err); } } ); -//activate or deactive integration -router.put( - "/toggle/:application_id/:name", - [param("application_id").isUUID(4).withMessage("Invalid application id")], +//return one integration_mapping entry with application_id and integration_id paramter +router.get( + "/getOne/:application_id/:integration_id", + [param("application_id").isUUID(), param("integration_id").isUUID()], async (req, res) => { - const errors = validationResult(req).formatWith( - validatorUtil.errorFormatter - ); + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } try { - if (!errors.isEmpty()) - return res.status(422).json({ success: false, errors: errors.array() }); - const { application_id, name } = req.params; - - const integration = await integrations.findOne({ - where: { application_id, name }, - raw: true, + const { application_id, integration_id } = req.params; + const result = await integration_mapping.findOne({ + where: { + application_id, + integration_id, + }, }); - - const { active, id } = integration; - - // flipping Active - await integrations.update({ active: !active }, { where: { id } }); - - res.status(200).send("integration toggled succesfully"); + res.status(200).send(result); } catch (err) { // ... error checks console.log(err); + res.status(500).send("Failed to get integration mapping: " + err); } } ); -//update integration notifications -router.put( - "/update/:application_id/:name", - [param("application_id").isUUID(4).withMessage("Invalid application id")], +//create entry into integration_mapping table with application_id paramter +router.post( + "/create", + [body("application_id").isUUID(), body("integration_id").isUUID()], async (req, res) => { - const errors = validationResult(req).formatWith( - validatorUtil.errorFormatter - ); + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } try { - if (!errors.isEmpty()) - return res.status(422).json({ success: false, errors: errors.array() }); - const { application_id, name } = req.params; - - if (!application_id) throw Error("Invalid app ID"); - const oldintegration = await integrations.findOne({ - where: { application_id, name }, - raw: true, + const { application_id, integration_id, metaData } = req.body; + const result = await integration_mapping.create({ + application_id, + integration_id, + metaData, }); + res.status(200).send(result); + } catch (err) { + // ... error checks + console.log(err); + res.status(500).send("Failed to create integration mapping: " + err); + } + } +); - const { id } = oldintegration; - - console.log(req.body); +//delete integration_mapping entry with application_id and integration_id paramter +router.delete( + "/delete", + [body("application_id").isUUID(), body("integration_id").isUUID()], + async (req, res) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } + try { + const { application_id, integration_id } = req.body; + const result = await integration_mapping.destroy({ + where: { + application_id, + integration_id, + }, + }); + res.status(200).send(result); + } catch (err) { + // ... error checks + console.log(err); + res.status(500).send("Failed to delete integration mapping: " + err); + } + } +); - // adjusting - await integrations.update( - { metaData: req.body.notifications, config: req.body.active }, - { where: { id } } +//update integration_mapping entry with application_id and integration_id paramter +router.put( + "/update", + [body("application_id").isUUID(), body("integration_id").isUUID()], + async (req, res) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }); + } + try { + const { application_id, integration_id, metaData } = req.body; + const result = await integration_mapping.update( + { metaData }, + { + where: { + application_id, + integration_id, + }, + } ); - - res.status(200).send("integration updated succesfully"); + res.status(200).send(result); } catch (err) { // ... error checks console.log(err); + res.status(500).send("Failed to update integration mapping: " + err); } } ); diff --git a/server/server.js b/server/server.js index 81c2a7c9e..cec5928dc 100644 --- a/server/server.js +++ b/server/server.js @@ -32,7 +32,7 @@ app.set("trust proxy", 1); // Limit rate of requests to 400 per 15 minutes const limiter = rateLimit({ - windowMs: 15 * 60 * 1000, + windowMs: 15 * 60 * 1000, max: 400, }); @@ -95,7 +95,6 @@ app.use("/api/updateNotification", updateNotifications); //exposed API, requires api key for any routes app.use("/api/apikeys", api); -// Authenticate token before proceeding to route app.use(tokenService.verifyToken); app.use("/api/job", job); @@ -126,7 +125,8 @@ app.use("/api/cluster", cluster); app.use("/api/orbit", orbit); app.use("/api/integrations", integrations); app.use("/api/teamsHook", teamsHook); -app.use("/api/fido", fido);fido +app.use("/api/fido", fido); +fido; app.use("/api/notification_queue", notification_queue); // Safety net for unhandled errors @@ -135,8 +135,9 @@ app.use((err, req, res, next) => { res.status(500).send("Something went wrong"); }); -// Disables SSL verification for self-signed certificates in development mode -process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = process.env.NODE_ENV === "production" ? 1 : 0; +// Disables SSL verification for self-signed certificates in development mode +process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = + process.env.NODE_ENV === "production" ? 1 : 0; /* Start server */ server.listen(port, "0.0.0.0", async () => { diff --git a/server/tests/mock-data/global.json b/server/tests/mock-data/global.json index dd4c80261..1f0a0f971 100644 --- a/server/tests/mock-data/global.json +++ b/server/tests/mock-data/global.json @@ -4,5 +4,6 @@ "clusterId": "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000", "name": "test", "keyword": "test2", - "id": "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000" + "id": "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000", + "metaData": {} } diff --git a/server/tests/unit/integration.test.js b/server/tests/unit/integration.test.js index 5835e8ebb..21fcaafc5 100644 --- a/server/tests/unit/integration.test.js +++ b/server/tests/unit/integration.test.js @@ -1,86 +1,128 @@ -//dependencies to start app.js and make calls const express = require("express"); const request = require("supertest"); const app = express(); app.use(express.json()); +const integrationAPI = require("../../routes/integrations/read"); +app.use("/api/integrations", integrationAPI); //import model and spy functions that will be called const models = require("../../models"); const integrations = models.integrations; -integrations.findOne = jest.fn(() => { - return mockIntegrationData; -}); +const integration_mapping = models.integration_mapping; + +//mock all of the sequelize functions from integration model +integrations.findOne = jest.fn(); integrations.findAll = jest.fn(); +integrations.create = jest.fn(); integrations.update = jest.fn(); +integrations.destroy = jest.fn(); + +//mock all of the sequelize functions from integration_mappings model +integration_mapping.findOne = jest.fn(); +integration_mapping.findAll = jest.fn(); +integration_mapping.create = jest.fn(); +integration_mapping.update = jest.fn(); +integration_mapping.destroy = jest.fn(); -//bring in standard testing data const mockData = require("../mock-data/global.json"); -const mockIntegrationData = require("../mock-data/integration.json"); +const { application_id, id, metaData } = mockData; -//route and models imported for testing -const integration = require("../../routes/integrations/read"); -app.use("/api/integration", integration); +describe("integration Routes", () => { + beforeEach(() => { + // Clear all mocks before each test + jest.clearAllMocks(); + }); -//write tests -describe("Integration Tests", () => { - //globals needed for multiple tests - const { application_id, badApplicationId, name } = mockData; - let response; + //test getAll + it("should return all integrations", async () => { + // Mock the response from the integration model + const res = await request(app).get("/api/integrations/getAll"); + expect(res.statusCode).toEqual(200); + }); - beforeEach(() => { - jest.resetModules(); // Most important - it clears the cache - response = null; + it("should return all integration_mappings with application_id", async () => { + const res = await request(app).get( + `/api/integrations/getAll/${application_id}` + ); + expect(res.statusCode).toEqual(200); + expect(integration_mapping.findAll).toBeCalled(); + }); + + it("should return one integration_mapping entry with application_id and integration_id", async () => { + const res = await request(app).get( + `/api/integrations/getOne/${application_id}/${id}` + ); + expect(res.statusCode).toEqual(200); + expect(integration_mapping.findOne).toBeCalled(); + }); + + it("should create an entry into integration_mapping table with application_id", async () => { + const data = { + application_id: application_id, + integration_id: id, + metaData: metaData, + }; + const res = await request(app).post("/api/integrations/create").send(data); + expect(res.statusCode).toEqual(200); + expect(integration_mapping.create).toBeCalled(); }); - describe("Route Checks", () => { - test("Get all", async () => { - response = await request(app).get( - `/api/integration/get/${application_id}` - ); - expect(integrations.findAll).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); + it("should delete integration_mapping entry with application_id and integration_id", async () => { + const data = { + application_id: application_id, + integration_id: id, + }; + const res = await request(app) + .delete("/api/integrations/delete") + .send(data); + expect(res.statusCode).toEqual(200); + expect(integration_mapping.destroy).toBeCalled(); + }); - test("Get all - Bad App ID", async () => { - response = await request(app).get( - `/api/integration/get/${badApplicationId}` - ); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); + it("should update integration_mapping entry with application_id and integration_id", async () => { + const data = { + application_id: application_id, + integration_id: id, + metaData: metaData, + }; + const res = await request(app).put("/api/integrations/update").send(data); + expect(res.statusCode).toEqual(200); + expect(integration_mapping.update).toBeCalled(); + }); - test("toggle active", async () => { - response = await request(app).put( - `/api/integration/toggle/${application_id}/${name}` - ); - expect(response.status).toBe(200); - expect(integrations.findOne).toHaveBeenCalledTimes(1); - expect(integrations.update).toHaveBeenCalledTimes(1); - }); + //test error messages for these routes when bad data is sent + it("should return error message for bad application_id", async () => { + const res = await request(app).get( + "/api/integrations/getAll/badapplicationid" + ); + expect(res.statusCode).toEqual(422); + }); - test("toggle active - Bad App ID", async () => { - response = await request(app).put( - `/api/integration/toggle/${badApplicationId}/${name}` - ); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); + it("should return error message for bad application_id and integration_id", async () => { + const res = await request(app).get( + "/api/integrations/getOne/badapplicationid/badintegrationid" + ); + expect(res.statusCode).toEqual(422); + }); - test("update ", async () => { - response = await request(app).put( - `/api/integration/update/${application_id}/${name}` - ); - expect(integrations.findOne).toHaveBeenCalledTimes(1); - expect(integrations.update).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); + it("should return error message for bad application_id and integration_id", async () => { + const data = { + application_id: "badapplicationid", + integration_id: "badintegrationid", + }; + const res = await request(app) + .delete("/api/integrations/delete") + .send(data); + expect(res.statusCode).toEqual(422); + }); - test("update - Bad App ID", async () => { - response = await request(app).put( - `/api/integration/update/${badApplicationId}/${name}` - ); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); + it("should return error message for bad application_id and integration_id", async () => { + const data = { + application_id: "badapplicationid", + integration_id: "badintegrationid", + metaData: metaData, + }; + const res = await request(app).put("/api/integrations/update").send(data); + expect(res.statusCode).toEqual(422); }); }); diff --git a/server/tests/unit/jobmonitoring.test.js b/server/tests/unit/jobmonitoring.test.js deleted file mode 100644 index 88ed84c71..000000000 --- a/server/tests/unit/jobmonitoring.test.js +++ /dev/null @@ -1,121 +0,0 @@ -//dependencies to start app.js and make calls -const express = require("express"); -const request = require("supertest"); -const app = express(); -app.use(express.json()); - -//import model and spy functions that will be called -const models = require("../../models"); -const JobMonitoring = models.jobMonitoring; -const hpccJSComms = require("@hpcc-js/comms"); -const hpccUtil = require("../../utils/hpcc-util"); -const JobScheduler = require("../../job-scheduler"); - -//route and models imported for testing -const jobmonitoring = require("../../routes/jobmonitoring/read"); -app.use("/api/job", jobmonitoring); - -//bring in standard testing data -const mockData = require("../mock-data/job.json"); - -JobMonitoring.create = jest.fn(async () => { - return mockData; -}); -JobMonitoring.findOne = jest.fn(async () => { - return mockData; -}); -JobMonitoring.findAll = jest.fn(); -JobMonitoring.destroy = jest.fn(); -JobMonitoring.update = jest.fn(async () => { - return mockData; -}); - -JobScheduler.createJobMonitoringBreeJob = jest.fn(); -JobScheduler.removeJobFromScheduler = jest.fn(); - -//write tests -describe("File Monitoring Tests", () => { - //globals needed for multiple tests - const application_id = "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc001"; - const id = "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc003"; - let response; - - beforeEach(() => { - jest.resetModules(); // Most important - it clears the cache - response = null; - }); - - describe("Route Checks", () => { - test("Create Job Monitoring", async () => { - response = await request(app) - .post(`/api/job/`) - .send(mockData) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); - - expect(JobMonitoring.create).toHaveBeenCalledTimes(1); - expect(response.status).toBe(201); - expect(response.body).toStrictEqual(mockData); - }); - test("Create File - No Data Error", async () => { - response = await request(app).post(`/api/job/`); - expect(JobMonitoring.create).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - }); - - test("Get All - No Data Error", async () => { - response = await request(app).get(`/api/job/all/${application_id}`); - expect(JobMonitoring.findAll).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get All", async () => { - response = await request(app).get(`/api/job/all/badapplicationid`); - expect(JobMonitoring.findAll).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - }); - - test("Get One", async () => { - response = await request(app).get(`/api/job/${id}`); - expect(JobMonitoring.findOne).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - expect(response.body).toStrictEqual(mockData); - }); - - test("Get One - Error", async () => { - response = await request(app).get(`/api/job/badId`); - expect(JobMonitoring.findOne).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - }); - - test("Delete", async () => { - response = await request(app).delete(`/api/job/${id}`); - expect(JobMonitoring.destroy).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Delete - Error", async () => { - response = await request(app).delete(`/api/job/badID`); - expect(JobMonitoring.destroy).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - }); - - test("Update Monitoring Active", async () => { - response = await request(app).put(`/api/job/jobMonitoringStatus/${id}`); - expect(JobMonitoring.findOne).toHaveBeenCalledTimes(1); - expect(JobMonitoring.update).toHaveBeenCalledTimes(1); - expect(JobScheduler.createJobMonitoringBreeJob).toHaveBeenCalledTimes(1); - expect(JobScheduler.removeJobFromScheduler).toHaveBeenCalledTimes(0); - expect(response.status).toBe(200); - }); - - test("Update Monitoring Active - Error", async () => { - response = await request(app).put(`/api/job/jobMonitoringStatus/badid`); - expect(JobMonitoring.findOne).toHaveBeenCalledTimes(0); - expect(JobMonitoring.update).toHaveBeenCalledTimes(0); - expect(JobScheduler.createJobMonitoringBreeJob).toHaveBeenCalledTimes(0); - expect(JobScheduler.removeJobFromScheduler).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - }); - }); -}); diff --git a/server/tests/unit/notification.test.js b/server/tests/unit/notification.test.js deleted file mode 100644 index 08380fa8b..000000000 --- a/server/tests/unit/notification.test.js +++ /dev/null @@ -1,77 +0,0 @@ -//dependencies to start app.js -const express = require("express"); -const request = require("supertest"); - -//need express to mock calls -const app = express(); - -// create Database for Mocking -// const { sequelize: dbConnection } = require("../../models"); - -//routes imported for testing -const notifications = require("../../routes/notifications/read"); - -// necessary to parse request body as JSON -app.use(express.json()); -app.use("/api/notifications/read", notifications); - -describe("Notifications Tests", () => { - const application_id = "11bf5b37-e0b8-42e0-8dcf-dc8c4aefc001"; - let response; - - beforeEach(() => { - jest.resetModules(); // Most important - it clears the cache - response = null; - }); - - describe("Notifications Endpoint Check", () => { - test("Get all", async () => { - response = await request(app).get( - `/api/notifications/read/${application_id}` - ); - - expect(response.status).toBe(200); - }); - - // test("Get all - Bad Application ID", async () => { - // response = await request(app).get( - // `/api/notifications/read/badapplicationid` - // ); - // expect(response.status).toBe(422); - // expect(response.body.success).toBe(false); - // }); - - test("Get CSV File", async () => { - response = await request(app).get( - `/api/notifications/read/${application_id}/file/CSV` - ); - - expect(response.status).toBe(200); - expect(response.text).toBe( - "id,monitoringId,Channel,Reason,Status,Created,Deleted" - ); - expect(response.headers["content-disposition"]).toBe( - 'attachment; filename="Tombolo-Notifications.CSV"' - ); - }); - - test("Get JSON File", async () => { - response = await request(app).get( - `/api/notifications/read/${application_id}/file/JSON` - ); - - expect(response.status).toBe(200); - expect(response.text).toBe("[]"); - expect(response.headers["content-disposition"]).toBe( - 'attachment; filename="Tombolo-Notifications.JSON"' - ); - }); - - test("Get File - Bad Type", async () => { - response = await request(app).get( - `/api/notifications/read/${application_id}/file/XML` - ); - expect(response.status).toBe(500); - }); - }); -}); diff --git a/server/tests/unit/orbit.test.js b/server/tests/unit/orbit.test.js deleted file mode 100644 index d8c7f504c..000000000 --- a/server/tests/unit/orbit.test.js +++ /dev/null @@ -1,279 +0,0 @@ -//dependencies to start app.js and make calls -const express = require("express"); -const request = require("supertest"); -const app = express(); -app.use(express.json()); -const sql = require("mssql"); - -//bring in standard testing data -const mockData = require("../mock-data/global.json"); -const mockOrbitMonitoringData = require("../mock-data/orbitMonitoring.json"); -const mockOrbitMonitoringDataBadID = require("../mock-data/orbitMonitoringBad.json"); -const mockSqlReturnData = require("../mock-data/sqlData.json"); - -//import model and spy functions that will be called -const models = require("../../models"); -const jobScheduler = require("../../job-scheduler"); -const orbitBuild = models.orbitBuilds; -const orbitMonitoring = models.orbitMonitoring; -const monitoring_notifications = models.monitoring_notifications; - -//orbit Builds mocks -orbitBuild.findOne = jest.fn(); -orbitBuild.findAll = jest.fn(); -orbitBuild.update = jest.fn(); -orbitBuild.create = jest.fn(); -orbitBuild.destroy = jest.fn(); - -//orbit Monitoring mocks -orbitMonitoring.findOne = jest.fn(() => { - return mockOrbitMonitoringData; -}); -orbitMonitoring.findAll = jest.fn(() => { - return mockOrbitMonitoringData; -}); -orbitMonitoring.update = jest.fn(); -orbitMonitoring.create = jest.fn(() => { - return mockOrbitMonitoringData; -}); -orbitMonitoring.destroy = jest.fn(); - -//monitoring notifications mocks -monitoring_notifications.bulkCreate = jest.fn(); - -//job scheduler mocks -jobScheduler.createOrbitMonitoringJob = jest.fn(); -jobScheduler.removeJobFromScheduler = jest.fn(); -jobScheduler.getAllJobs = jest.fn(); - -//sql mocks -sql.connect = jest.fn(); -sql.query = jest.fn(() => { - return mockSqlReturnData; -}); - -//route and models imported for testing -const orbit = require("../../routes/orbit/read"); -const orbitbuilds = require("../../models/orbitbuilds"); -app.use("/api/orbit", orbit); - -describe("Integration Tests", () => { - //globals needed for multiple tests - const { application_id, badApplicationId, name, keyword, id } = mockData; - let response; - - beforeEach(() => { - jest.resetModules(); // Most important - it clears the cache - response = null; - }); - - describe("Route Checks", () => { - test("Create One", async () => { - response = await request(app) - .post(`/api/orbit/`) - .send(mockOrbitMonitoringData) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); - - expect(orbitMonitoring.create).toHaveBeenCalledTimes(1); - expect(sql.query).toHaveBeenCalledTimes(1); - expect(response.status).toBe(201); - }); - - test("Create One - Bad App ID", async () => { - response = await request(app) - .post(`/api/orbit/`) - .send(mockOrbitMonitoringDataBadID) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); - - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get All Monitorings", async () => { - response = await request(app).get( - `/api/orbit/allMonitorings/${application_id}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get All Monitorings - Bad Data", async () => { - response = await request(app).get( - `/api/orbit/allMonitorings/${badApplicationId}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get All Builds", async () => { - response = await request(app).get( - `/api/orbit/allMonitorings/${application_id}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get All Builds - Bad Data", async () => { - response = await request(app).get( - `/api/orbit/allMonitorings/${badApplicationId}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get Searched Results", async () => { - response = await request(app).get( - `/api/orbit/search/${application_id}/${keyword}` - ); - expect(sql.query).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get Searched Results - Bad Data", async () => { - response = await request(app).get( - `/api/orbit/search/${badApplicationId}/${keyword}` - ); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get Build Details from SQL", async () => { - response = await request(app).get( - `/api/orbit/getOrbitBuildDetails/${name}` - ); - expect(sql.query).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get Build Details from SQL", async () => { - response = await request(app).get( - `/api/orbit/getOrbitBuildDetails/${"&"}` - ); - expect(sql.query).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Update Monitoring", async () => { - response = await request(app) - .put(`/api/orbit/`) - .send(mockOrbitMonitoringData) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); - - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(1); - expect(orbitMonitoring.update).toHaveBeenCalledTimes(1); - expect(sql.connect).toHaveBeenCalledTimes(1); - expect(sql.query).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Update Monitoring", async () => { - response = await request(app) - .put(`/api/orbit/`) - .send(mockOrbitMonitoringDataBadID) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); - - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(0); - expect(orbitMonitoring.update).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("toggle status", async () => { - response = await request(app).put( - `/api/orbit/togglestatus/${application_id}` - ); - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(1); - expect(orbitMonitoring.update).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("toggle status - bad id", async () => { - response = await request(app).put( - `/api/orbit/togglestatus/${badApplicationId}` - ); - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(0); - expect(orbitMonitoring.update).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Delete", async () => { - response = await request(app).delete( - `/api/orbit/delete/${application_id}/${name}` - ); - expect(orbitMonitoring.destroy).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Delete", async () => { - response = await request(app).delete( - `/api/orbit/delete/${badApplicationId}/${name}` - ); - expect(orbitMonitoring.destroy).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get one", async () => { - response = await request(app).get( - `/api/orbit/getOne/${application_id}/${id}` - ); - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get one - Bad ID", async () => { - response = await request(app).get( - `/api/orbit/getOne/${badApplicationId}/${id}` - ); - expect(orbitMonitoring.findOne).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Get WorkUnits", async () => { - response = await request(app).get( - `/api/orbit/getWorkunits/${application_id}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(1); - expect(response.status).toBe(200); - }); - - test("Get WorkUnits - Bad ID", async () => { - response = await request(app).get( - `/api/orbit/getWorkunits/${badApplicationId}` - ); - expect(orbitMonitoring.findAll).toHaveBeenCalledTimes(0); - expect(orbitBuild.findAll).toHaveBeenCalledTimes(0); - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - - test("Update List", async () => { - response = await request(app).post( - `/api/orbit/updateList/${application_id}` - ); - - expect(sql.connect).toHaveBeenCalledTimes(1); - expect(sql.query).toHaveBeenCalledTimes(1); - - expect(response.status).toBe(200); - }); - - test("Update List - Bad ID", async () => { - response = await request(app).post( - `/api/orbit/updateList/${badApplicationId}` - ); - - expect(response.status).toBe(422); - expect(response.body.success).toBe(false); - }); - }); -});