From bfff6d0207ef14134deeaf7fe6625110e4459c93 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Wed, 20 Oct 2021 23:26:33 -0500 Subject: [PATCH 01/29] SMTP notification tests --- config/jest-backend.config.js | 2 +- server/notification-providers/smtp.spec.js | 50 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 server/notification-providers/smtp.spec.js diff --git a/config/jest-backend.config.js b/config/jest-backend.config.js index 1a88d9a6b9..db39512910 100644 --- a/config/jest-backend.config.js +++ b/config/jest-backend.config.js @@ -1,5 +1,5 @@ module.exports = { "rootDir": "..", - "testRegex": "./test/backend.spec.js", + "testRegex": ["./test/backend.spec.js", "./server/.*.spec.js"], }; diff --git a/server/notification-providers/smtp.spec.js b/server/notification-providers/smtp.spec.js new file mode 100644 index 0000000000..2cf0876fcc --- /dev/null +++ b/server/notification-providers/smtp.spec.js @@ -0,0 +1,50 @@ +jest.mock("nodemailer", () => ({ + createTransport: jest.fn(), +})); +const mockNodEmailer = require("nodemailer"); + +const SMTP = require("./smtp"); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new SMTP(); + expect(notification.name).toBe("smtp"); + }); +}); + +describe("notification to act properly on send", () => { + it("should call transport with the proper default data", async () => { + let sender = jest.fn() + .mockResolvedValue(() => { + return; + }); + mockNodEmailer.createTransport.mockImplementationOnce(() => { + return { sendMail: sender }; + }); + + let notif = new SMTP(); + let notificationConf = { + smtpHost: "host", + smtpPort: "port", + smtpSecure: "secure", + smtpUsername: "username", + smtpPassword: "password", + customSubject: "custom subject", + }; + let msg = "Message"; + let monitorConf = { }; + let heartbeatConf = { }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(mockNodEmailer.createTransport).toHaveBeenCalledWith({ + auth: { + pass: "password", + user: "username", + }, + host: "host", + port: "port", + secure: "secure", + }); + expect(res).toBe("Sent Successfully."); + }); +}); From 27ce95daf85907ee9b822ab841f4976eab5a8039 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 01:15:06 -0500 Subject: [PATCH 02/29] add check for what email data was passed to nodemailer --- server/notification-providers/smtp.spec.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/server/notification-providers/smtp.spec.js b/server/notification-providers/smtp.spec.js index 2cf0876fcc..dcae96791b 100644 --- a/server/notification-providers/smtp.spec.js +++ b/server/notification-providers/smtp.spec.js @@ -1,7 +1,7 @@ jest.mock("nodemailer", () => ({ createTransport: jest.fn(), })); -const mockNodEmailer = require("nodemailer"); +const mockNodeMailer = require("nodemailer"); const SMTP = require("./smtp"); @@ -18,7 +18,7 @@ describe("notification to act properly on send", () => { .mockResolvedValue(() => { return; }); - mockNodEmailer.createTransport.mockImplementationOnce(() => { + mockNodeMailer.createTransport.mockImplementationOnce(() => { return { sendMail: sender }; }); @@ -31,12 +31,12 @@ describe("notification to act properly on send", () => { smtpPassword: "password", customSubject: "custom subject", }; - let msg = "Message"; + let msg = "PassedInMessage"; let monitorConf = { }; let heartbeatConf = { }; let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); - expect(mockNodEmailer.createTransport).toHaveBeenCalledWith({ + expect(mockNodeMailer.createTransport).toHaveBeenCalledWith({ auth: { pass: "password", user: "username", @@ -46,5 +46,16 @@ describe("notification to act properly on send", () => { secure: "secure", }); expect(res).toBe("Sent Successfully."); + expect(sender).toHaveBeenCalledWith({ + bcc: undefined, + cc: undefined, + from: undefined, + subject: "custom subject", + text: "PassedInMessage\nTime (UTC): undefined", + tls: { + rejectUnauthorized: false, + }, + to: undefined, + }); }); }); From 1ff1fc6edfb34ddcc720d690955582bf8894bd70 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 02:31:17 -0500 Subject: [PATCH 03/29] add tests for SMTP errors --- server/notification-providers/smtp.spec.js | 134 ++++++++++++++++++++- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/server/notification-providers/smtp.spec.js b/server/notification-providers/smtp.spec.js index dcae96791b..14442350ef 100644 --- a/server/notification-providers/smtp.spec.js +++ b/server/notification-providers/smtp.spec.js @@ -2,9 +2,14 @@ jest.mock("nodemailer", () => ({ createTransport: jest.fn(), })); const mockNodeMailer = require("nodemailer"); +const { UP } = require("../../src/util"); const SMTP = require("./smtp"); +beforeEach(() => { + mockNodeMailer.createTransport.mockReset(); +}); + describe("notification default information", () => { it("should have the correct name", () => { let notification = new SMTP(); @@ -29,7 +34,11 @@ describe("notification to act properly on send", () => { smtpSecure: "secure", smtpUsername: "username", smtpPassword: "password", - customSubject: "custom subject", + customSubject: "", + smtpFrom: "From", + smtpCC: "CC", + smtpBCC: "BCC", + smtpTo: "To", }; let msg = "PassedInMessage"; let monitorConf = { }; @@ -47,15 +56,128 @@ describe("notification to act properly on send", () => { }); expect(res).toBe("Sent Successfully."); expect(sender).toHaveBeenCalledWith({ - bcc: undefined, - cc: undefined, - from: undefined, - subject: "custom subject", + bcc: "BCC", + cc: "CC", + from: "From", + subject: "PassedInMessage", text: "PassedInMessage\nTime (UTC): undefined", tls: { rejectUnauthorized: false, }, - to: undefined, + to: "To", }); }); + + it("should use the proper email subject", async () => { + let sender = jest.fn() + .mockResolvedValue(() => { + return; + }); + mockNodeMailer.createTransport.mockImplementationOnce(() => { + return { sendMail: sender }; + }); + + let notif = new SMTP(); + let notificationConf = { + smtpHost: "host", + smtpPort: "port", + smtpSecure: "secure", + smtpUsername: "username", + smtpPassword: "password", + customSubject: "Name: {{NAME}} | Status: {{STATUS}} | Hostname: {{HOSTNAME_OR_URL}}", + smtpFrom: "From", + smtpCC: "CC", + smtpBCC: "BCC", + smtpTo: "To", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(mockNodeMailer.createTransport).toHaveBeenCalledWith({ + auth: { + pass: "password", + user: "username", + }, + host: "host", + port: "port", + secure: "secure", + }); + expect(res).toBe("Sent Successfully."); + expect(sender).toHaveBeenCalledWith({ + bcc: "BCC", + cc: "CC", + from: "From", + subject: "Name: testing | Status: ✅ Up | Hostname: https://www.google.com", + text: "PassedInMessage\nTime (UTC): undefined", + tls: { + rejectUnauthorized: false, + }, + to: "To", + }); + }); +}); + +describe("notification to act properly on error from transport", () => { + it("should pass a createTransport error on", async () => { + let sender = jest.fn() + .mockResolvedValue(() => { + return; + }); + mockNodeMailer.createTransport.mockImplementationOnce(() => { + throw new Error("Test Error"); + }); + + let notif = new SMTP(); + let notificationConf = { }; + let msg = "PassedInMessage"; + let monitorConf = { }; + let heartbeatConf = { }; + let res = ""; + try { + res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(true).toBe(false); + } catch (e) { + expect(e.message).toBe("Test Error"); + } + + expect(mockNodeMailer.createTransport).toHaveBeenCalledTimes(1); + expect(res).toBe(""); + expect(sender).toHaveBeenCalledTimes(0); + }); + + it("should pass a send mail error on", async () => { + let sender = jest.fn() + .mockRejectedValue(new Error("Test Error")); + mockNodeMailer.createTransport.mockImplementationOnce(() => { + return { sendMail: sender }; + + }); + + let notif = new SMTP(); + let notificationConf = { }; + let msg = "PassedInMessage"; + let monitorConf = { }; + let heartbeatConf = { }; + let res = ""; + try { + res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + expect("threw error").toBe(false); + } catch (e) { + expect(e.message).toBe("Test Error"); + } + + expect(mockNodeMailer.createTransport).toHaveBeenCalledTimes(1); + expect(res).toBe(""); + expect(sender).toHaveBeenCalledTimes(1); + }); + }); From 6be97fbb4d8c4354a91559917bd52304d2d08b2e Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 02:56:52 -0500 Subject: [PATCH 04/29] Starting test file for all notifications. --- .../notification-providers/aliyun-sms.spec.js | 18 ++++++++++++++++++ server/notification-providers/apprise.spec.js | 18 ++++++++++++++++++ server/notification-providers/dingding.spec.js | 18 ++++++++++++++++++ server/notification-providers/discord.spec.js | 18 ++++++++++++++++++ server/notification-providers/feishu.spec.js | 18 ++++++++++++++++++ server/notification-providers/gotify.spec.js | 18 ++++++++++++++++++ server/notification-providers/line.spec.js | 18 ++++++++++++++++++ server/notification-providers/lunasea.spec.js | 18 ++++++++++++++++++ server/notification-providers/matrix.spec.js | 18 ++++++++++++++++++ .../notification-providers/mattermost.spec.js | 18 ++++++++++++++++++ .../notification-provider.spec.js | 18 ++++++++++++++++++ server/notification-providers/octopush.spec.js | 18 ++++++++++++++++++ server/notification-providers/promosms.spec.js | 18 ++++++++++++++++++ .../notification-providers/pushbullet.spec.js | 18 ++++++++++++++++++ server/notification-providers/pushover.spec.js | 18 ++++++++++++++++++ server/notification-providers/pushy.spec.js | 18 ++++++++++++++++++ .../notification-providers/rocket-chat.spec.js | 18 ++++++++++++++++++ server/notification-providers/signal.spec.js | 18 ++++++++++++++++++ server/notification-providers/slack.spec.js | 18 ++++++++++++++++++ server/notification-providers/teams.spec.js | 18 ++++++++++++++++++ server/notification-providers/telegram.spec.js | 18 ++++++++++++++++++ server/notification-providers/webhook.spec.js | 18 ++++++++++++++++++ 22 files changed, 396 insertions(+) create mode 100644 server/notification-providers/aliyun-sms.spec.js create mode 100644 server/notification-providers/apprise.spec.js create mode 100644 server/notification-providers/dingding.spec.js create mode 100644 server/notification-providers/discord.spec.js create mode 100644 server/notification-providers/feishu.spec.js create mode 100644 server/notification-providers/gotify.spec.js create mode 100644 server/notification-providers/line.spec.js create mode 100644 server/notification-providers/lunasea.spec.js create mode 100644 server/notification-providers/matrix.spec.js create mode 100644 server/notification-providers/mattermost.spec.js create mode 100644 server/notification-providers/notification-provider.spec.js create mode 100644 server/notification-providers/octopush.spec.js create mode 100644 server/notification-providers/promosms.spec.js create mode 100644 server/notification-providers/pushbullet.spec.js create mode 100644 server/notification-providers/pushover.spec.js create mode 100644 server/notification-providers/pushy.spec.js create mode 100644 server/notification-providers/rocket-chat.spec.js create mode 100644 server/notification-providers/signal.spec.js create mode 100644 server/notification-providers/slack.spec.js create mode 100644 server/notification-providers/teams.spec.js create mode 100644 server/notification-providers/telegram.spec.js create mode 100644 server/notification-providers/webhook.spec.js diff --git a/server/notification-providers/aliyun-sms.spec.js b/server/notification-providers/aliyun-sms.spec.js new file mode 100644 index 0000000000..c8eb9488bb --- /dev/null +++ b/server/notification-providers/aliyun-sms.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const AliyunSMS = require("./aliyun-sms"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new AliyunSMS(); + expect(notification.name).toBe("AliyunSMS"); + }); +}); diff --git a/server/notification-providers/apprise.spec.js b/server/notification-providers/apprise.spec.js new file mode 100644 index 0000000000..6cb5a1f2d8 --- /dev/null +++ b/server/notification-providers/apprise.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Apprise = require("./apprise"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Apprise(); + expect(notification.name).toBe("apprise"); + }); +}); diff --git a/server/notification-providers/dingding.spec.js b/server/notification-providers/dingding.spec.js new file mode 100644 index 0000000000..e90bdbe5db --- /dev/null +++ b/server/notification-providers/dingding.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const DingDing = require("./dingding"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new DingDing(); + expect(notification.name).toBe("DingDing"); + }); +}); diff --git a/server/notification-providers/discord.spec.js b/server/notification-providers/discord.spec.js new file mode 100644 index 0000000000..1f9feb0e29 --- /dev/null +++ b/server/notification-providers/discord.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Discord = require("./discord"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Discord(); + expect(notification.name).toBe("discord"); + }); +}); diff --git a/server/notification-providers/feishu.spec.js b/server/notification-providers/feishu.spec.js new file mode 100644 index 0000000000..5d349068bd --- /dev/null +++ b/server/notification-providers/feishu.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Feishu = require("./feishu"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Feishu(); + expect(notification.name).toBe("Feishu"); + }); +}); diff --git a/server/notification-providers/gotify.spec.js b/server/notification-providers/gotify.spec.js new file mode 100644 index 0000000000..02f3c71fc5 --- /dev/null +++ b/server/notification-providers/gotify.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Gotify = require("./gotify"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Gotify(); + expect(notification.name).toBe("gotify"); + }); +}); diff --git a/server/notification-providers/line.spec.js b/server/notification-providers/line.spec.js new file mode 100644 index 0000000000..10aa265409 --- /dev/null +++ b/server/notification-providers/line.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Line = require("./line"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Line(); + expect(notification.name).toBe("line"); + }); +}); diff --git a/server/notification-providers/lunasea.spec.js b/server/notification-providers/lunasea.spec.js new file mode 100644 index 0000000000..344e79433f --- /dev/null +++ b/server/notification-providers/lunasea.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const LunaSea = require("./lunasea"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new LunaSea(); + expect(notification.name).toBe("lunasea"); + }); +}); diff --git a/server/notification-providers/matrix.spec.js b/server/notification-providers/matrix.spec.js new file mode 100644 index 0000000000..94c84b56af --- /dev/null +++ b/server/notification-providers/matrix.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Matrix = require("./matrix"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Matrix(); + expect(notification.name).toBe("matrix"); + }); +}); diff --git a/server/notification-providers/mattermost.spec.js b/server/notification-providers/mattermost.spec.js new file mode 100644 index 0000000000..81d6490070 --- /dev/null +++ b/server/notification-providers/mattermost.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Mattermost = require("./mattermost"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Mattermost(); + expect(notification.name).toBe("mattermost"); + }); +}); diff --git a/server/notification-providers/notification-provider.spec.js b/server/notification-providers/notification-provider.spec.js new file mode 100644 index 0000000000..56d929b055 --- /dev/null +++ b/server/notification-providers/notification-provider.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const NotificationProvider = require("./notification-provider"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new NotificationProvider(); + expect(notification.name).toBe(undefined); + }); +}); diff --git a/server/notification-providers/octopush.spec.js b/server/notification-providers/octopush.spec.js new file mode 100644 index 0000000000..3c16c3a5e6 --- /dev/null +++ b/server/notification-providers/octopush.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Octopush = require("./octopush"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Octopush(); + expect(notification.name).toBe("octopush"); + }); +}); diff --git a/server/notification-providers/promosms.spec.js b/server/notification-providers/promosms.spec.js new file mode 100644 index 0000000000..3d9dde7f27 --- /dev/null +++ b/server/notification-providers/promosms.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const PromoSMS = require("./promosms"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new PromoSMS(); + expect(notification.name).toBe("promosms"); + }); +}); diff --git a/server/notification-providers/pushbullet.spec.js b/server/notification-providers/pushbullet.spec.js new file mode 100644 index 0000000000..1cad877994 --- /dev/null +++ b/server/notification-providers/pushbullet.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Pushbullet = require("./pushbullet"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Pushbullet(); + expect(notification.name).toBe("pushbullet"); + }); +}); diff --git a/server/notification-providers/pushover.spec.js b/server/notification-providers/pushover.spec.js new file mode 100644 index 0000000000..dcc3adc037 --- /dev/null +++ b/server/notification-providers/pushover.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Pushover = require("./pushover"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Pushover(); + expect(notification.name).toBe("pushover"); + }); +}); diff --git a/server/notification-providers/pushy.spec.js b/server/notification-providers/pushy.spec.js new file mode 100644 index 0000000000..477e2cee77 --- /dev/null +++ b/server/notification-providers/pushy.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Pushy = require("./pushy"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Pushy(); + expect(notification.name).toBe("pushy"); + }); +}); diff --git a/server/notification-providers/rocket-chat.spec.js b/server/notification-providers/rocket-chat.spec.js new file mode 100644 index 0000000000..a34cc89647 --- /dev/null +++ b/server/notification-providers/rocket-chat.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const RocketChat = require("./rocket-chat"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new RocketChat(); + expect(notification.name).toBe("rocket.chat"); + }); +}); diff --git a/server/notification-providers/signal.spec.js b/server/notification-providers/signal.spec.js new file mode 100644 index 0000000000..dc3403a2ad --- /dev/null +++ b/server/notification-providers/signal.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Signal = require("./signal"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Signal(); + expect(notification.name).toBe("signal"); + }); +}); diff --git a/server/notification-providers/slack.spec.js b/server/notification-providers/slack.spec.js new file mode 100644 index 0000000000..f025654098 --- /dev/null +++ b/server/notification-providers/slack.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Slack = require("./slack"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Slack(); + expect(notification.name).toBe("slack"); + }); +}); diff --git a/server/notification-providers/teams.spec.js b/server/notification-providers/teams.spec.js new file mode 100644 index 0000000000..c5f804c212 --- /dev/null +++ b/server/notification-providers/teams.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Teams = require("./teams"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Teams(); + expect(notification.name).toBe("teams"); + }); +}); diff --git a/server/notification-providers/telegram.spec.js b/server/notification-providers/telegram.spec.js new file mode 100644 index 0000000000..285eef8c81 --- /dev/null +++ b/server/notification-providers/telegram.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Telegram = require("./telegram"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Telegram(); + expect(notification.name).toBe("telegram"); + }); +}); diff --git a/server/notification-providers/webhook.spec.js b/server/notification-providers/webhook.spec.js new file mode 100644 index 0000000000..7b2dfb7514 --- /dev/null +++ b/server/notification-providers/webhook.spec.js @@ -0,0 +1,18 @@ +// jest.mock("nodemailer", () => ({ +// createTransport: jest.fn(), +// })); + +// const mockNodeMailer = require("nodemailer"); + +const Webhook = require("./webhook"); + +beforeEach(() => { + // mockNodeMailer.createTransport.mockReset(); +}); + +describe("notification default information", () => { + it("should have the correct name", () => { + let notification = new Webhook(); + expect(notification.name).toBe("webhook"); + }); +}); From bc4f0f94fae0eaac46eed1439a05ceb0ed1146cc Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 18:19:58 -0500 Subject: [PATCH 05/29] Test for calling notification from Notification.send --- server/notification-providers/smtp.spec.js | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/server/notification-providers/smtp.spec.js b/server/notification-providers/smtp.spec.js index 14442350ef..d9165f7069 100644 --- a/server/notification-providers/smtp.spec.js +++ b/server/notification-providers/smtp.spec.js @@ -3,6 +3,7 @@ jest.mock("nodemailer", () => ({ })); const mockNodeMailer = require("nodemailer"); const { UP } = require("../../src/util"); +const NotificationSend = require("../notification"); const SMTP = require("./smtp"); @@ -181,3 +182,66 @@ describe("notification to act properly on error from transport", () => { }); }); + +describe("notification to get proper data from Notification.send", () => { + it("should call sendMail with proper data", async () => { + let sender = jest.fn() + .mockResolvedValue(() => { + return; + }); + mockNodeMailer.createTransport.mockImplementationOnce(() => { + return { sendMail: sender }; + }); + + let notificationConf = { + type: "smtp", + smtpHost: "host", + smtpPort: "port", + smtpSecure: "secure", + smtpUsername: "username", + smtpPassword: "password", + customSubject: "", + smtpFrom: "From", + smtpCC: "CC", + smtpBCC: "BCC", + smtpTo: "To", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "simple message", monitorConf, heartbeatConf); + + expect(res).toBe("Sent Successfully."); + + expect(mockNodeMailer.createTransport).toHaveBeenCalledTimes(1); + expect(mockNodeMailer.createTransport).toHaveBeenCalledWith({ + auth: { + pass: "password", + user: "username", + }, + host: "host", + port: "port", + secure: "secure", + }); + expect(sender).toHaveBeenCalledTimes(1); + expect(sender).toHaveBeenCalledWith({ + bcc: "BCC", + cc: "CC", + from: "From", + subject: "simple message", + text: "simple message\nTime (UTC): undefined", + tls: { + rejectUnauthorized: false, + }, + to: "To", + }); + }); + +}); From 833feaf0737a02ccf5fb629c267a749036d3686a Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 19:29:14 -0500 Subject: [PATCH 06/29] apprise tests --- server/notification-providers/apprise.js | 8 +- server/notification-providers/apprise.spec.js | 104 +++++++++++++++++- .../notification-provider.js | 6 +- server/notification-providers/smtp.js | 2 +- 4 files changed, 108 insertions(+), 12 deletions(-) diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index fdcd8d61be..90cefaca3f 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -1,22 +1,22 @@ const NotificationProvider = require("./notification-provider"); -const child_process = require("child_process"); +const childProcess = require("child_process"); class Apprise extends NotificationProvider { name = "apprise"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let s = child_process.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL]) + let s = childProcess.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL]); let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found"; if (output) { if (! output.includes("ERROR")) { - return "Sent Successfully"; + return this.sendSuccess; } - throw new Error(output) + throw new Error(output); } else { return "No output from apprise"; } diff --git a/server/notification-providers/apprise.spec.js b/server/notification-providers/apprise.spec.js index 6cb5a1f2d8..148521a927 100644 --- a/server/notification-providers/apprise.spec.js +++ b/server/notification-providers/apprise.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("child_process", () => ({ + spawnSync: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const childProcess = require("child_process"); +const { UP } = require("../../src/util"); +const NotificationSend = require("../notification"); const Apprise = require("./apprise"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + childProcess.spawnSync.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,95 @@ describe("notification default information", () => { expect(notification.name).toBe("apprise"); }); }); + +describe("notification to act properly on send", () => { + it("should call apprise with the proper default data", async () => { + + childProcess.spawnSync.mockImplementationOnce(() => { + return { stdout: "response" }; + }); + + let notif = new Apprise(); + let notificationConf = { + appriseURL: "appriseURL", + }; + let msg = "PassedInMessage"; + let res = await notif.send(notificationConf, msg, null, null); + + expect(childProcess.spawnSync).toHaveBeenCalledWith("apprise", ["-vv", "-b", "PassedInMessage", "appriseURL"]); + expect(res).toBe("Sent Successfully."); + }); + + //TODO code under test unreachable. Remove or resolve. + // it("should call output no data when no data", async () => { + + // childProcess.spawnSync.mockImplementationOnce(() => { + // return { stdout: "" }; + // }); + + // let notif = new Apprise(); + // let notificationConf = { + // appriseURL: "appriseURL", + // }; + // let msg = "PassedInMessage"; + // let res = await notif.send(notificationConf, msg, null, null); + + // expect(childProcess.spawnSync).toHaveBeenCalledWith("apprise", ["-vv", "-b", "PassedInMessage", "appriseURL"]); + // expect(res).toBe("No output from apprise"); + // }); + +}); + +describe("notification to act properly on errors from apprise", () => { + it("should call apprise with the proper default data", async () => { + + childProcess.spawnSync.mockImplementationOnce(() => { + return { stdout: "ERROR FROM APPRISE" }; + }); + + let notif = new Apprise(); + let notificationConf = { + appriseURL: "appriseURL", + }; + let msg = "PassedInMessage"; + try { + await notif.send(notificationConf, msg, null, null); + expect("not reached").toBe(false); + } catch (e) { + expect(e.message).toBe("ERROR FROM APPRISE"); + } + + expect(childProcess.spawnSync).toHaveBeenCalledWith("apprise", ["-vv", "-b", "PassedInMessage", "appriseURL"]); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call sendMail with proper data", async () => { + childProcess.spawnSync.mockImplementationOnce(() => { + return { stdout: "response" }; + }); + + let notificationConf = { + type: "apprise", + appriseURL: "appriseURL", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + + expect(res).toBe("Sent Successfully."); + + expect(childProcess.spawnSync).toHaveBeenCalledWith("apprise", ["-vv", "-b", "PassedInMessage", "appriseURL"]); + expect(res).toBe("Sent Successfully."); + }); + +}); diff --git a/server/notification-providers/notification-provider.js b/server/notification-providers/notification-provider.js index 61c6242d7b..3ccff04be0 100644 --- a/server/notification-providers/notification-provider.js +++ b/server/notification-providers/notification-provider.js @@ -6,6 +6,8 @@ class NotificationProvider { */ name = undefined; + sendSuccess = "Sent Successfully."; + /** * @param notification : BeanModel * @param msg : string General Message @@ -25,11 +27,11 @@ class NotificationProvider { if (typeof error.response.data === "string") { msg += error.response.data; } else { - msg += JSON.stringify(error.response.data) + msg += JSON.stringify(error.response.data); } } - throw new Error(msg) + throw new Error(msg); } } diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js index 60068eb773..7f35d1c40e 100644 --- a/server/notification-providers/smtp.js +++ b/server/notification-providers/smtp.js @@ -92,7 +92,7 @@ class SMTP extends NotificationProvider { }, }); - return "Sent Successfully."; + return this.sendSuccess; } } From 965ce6213beb37515202878c70bb398a71f3a8ed Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 21:57:09 -0500 Subject: [PATCH 07/29] dingding tests and minor fix --- server/notification-providers/dingding.js | 9 +- .../notification-providers/dingding.spec.js | 202 +++++++++++++++++- 2 files changed, 204 insertions(+), 7 deletions(-) diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index f099192d87..ea5a258bc3 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -7,7 +7,6 @@ class DingDing extends NotificationProvider { name = "DingDing"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (heartbeatJSON != null) { @@ -18,8 +17,8 @@ class DingDing extends NotificationProvider { text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`, } }; - if (this.sendToDingDing(notification, params)) { - return okMsg; + if (await this.sendToDingDing(notification, params)) { + return this.sendSuccess; } } else { let params = { @@ -28,8 +27,8 @@ class DingDing extends NotificationProvider { content: msg } }; - if (this.sendToDingDing(notification, params)) { - return okMsg; + if (await this.sendToDingDing(notification, params)) { + return this.sendSuccess; } } } catch (error) { diff --git a/server/notification-providers/dingding.spec.js b/server/notification-providers/dingding.spec.js index e90bdbe5db..15275318fe 100644 --- a/server/notification-providers/dingding.spec.js +++ b/server/notification-providers/dingding.spec.js @@ -1,13 +1,22 @@ -// jest.mock("nodemailer", () => ({ +// jest.mock("crypto", () => ({ // createTransport: jest.fn(), +// createHmac: jest.fn(), +// digest: jest.fn(), // })); +jest.mock("axios"); + +const { UP } = require("../../src/util"); +const NotificationSend = require("../notification"); + // const mockNodeMailer = require("nodemailer"); const DingDing = require("./dingding"); +const axios = require("axios"); + beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.mockReset(); }); describe("notification default information", () => { @@ -16,3 +25,192 @@ describe("notification default information", () => { expect(notification.name).toBe("DingDing"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => + new Date("2019-05-14T11:01:58.135Z").valueOf() + ); + + let response = { + data: { + errmsg: "ok" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new DingDing(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios).toHaveBeenCalledWith({ + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + headers: { + "Content-Type": "application/json", + }, + method: "POST", + url: "https://example.com/webhook×tamp=1557831718135&sign=lCTIn3sYpAYFAw3B2LeTLr7BvcOMAcmZu%2F6rb7kC8Io%3D", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when missing heartbeat", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => + new Date("2019-05-14T11:01:58.135Z").valueOf() + ); + + let response = { + data: { + errmsg: "ok" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new DingDing(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let res = await notif.send(notificationConf, msg, monitorConf, null); + + expect(axios).toHaveBeenCalledWith({ + data: "{\"msgtype\":\"text\",\"text\":{\"content\":\"PassedInMessage\"}}", + headers: { + "Content-Type": "application/json", + }, + method: "POST", + url: "https://example.com/webhook×tamp=1557831718135&sign=lCTIn3sYpAYFAw3B2LeTLr7BvcOMAcmZu%2F6rb7kC8Io%3D", + }); + expect(res).toBe("Sent Successfully."); + }); + + //TODO need to get correct response when sendToDingDing fails, but no axios error. + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => + new Date("2019-05-14T11:01:58.135Z").valueOf() + ); + + axios.mockImplementationOnce(() => { + throw new Error("Test Error"); + }); + + let notif = new DingDing(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + try { + await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + console.log("fail"); + expect("Error thrown").toBe(false); + } catch (e) { + //axios general error on catching another error is not the cleanest, but works. + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios).toHaveBeenCalledWith({ + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + headers: { + "Content-Type": "application/json", + }, + method: "POST", + url: "https://example.com/webhook×tamp=1557831718135&sign=lCTIn3sYpAYFAw3B2LeTLr7BvcOMAcmZu%2F6rb7kC8Io%3D", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call sendMail with proper data", async () => { + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => + new Date("2019-05-14T11:01:58.135Z").valueOf() + ); + + let response = { + data: { + errmsg: "ok" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new DingDing(); + let notificationConf = { + type: "DingDing", + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + + expect(res).toBe("Sent Successfully."); + + expect(axios).toHaveBeenCalledWith({ + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + headers: { + "Content-Type": "application/json", + }, + method: "POST", + url: "https://example.com/webhook×tamp=1557831718135&sign=lCTIn3sYpAYFAw3B2LeTLr7BvcOMAcmZu%2F6rb7kC8Io%3D", + + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 2dac1e95a2ea0f21620ddc591b4117becba25ba8 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Thu, 21 Oct 2021 22:45:15 -0500 Subject: [PATCH 08/29] discord tests --- server/notification-providers/discord.js | 23 +- server/notification-providers/discord.spec.js | 252 +++++++++++++++++- 2 files changed, 258 insertions(+), 17 deletions(-) diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index 881ad2113a..06b0273dab 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -7,7 +7,6 @@ class Discord extends NotificationProvider { name = "discord"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { const discordDisplayName = notification.discordUsername || "Uptime Kuma"; @@ -17,9 +16,9 @@ class Discord extends NotificationProvider { let discordtestdata = { username: discordDisplayName, content: msg, - } - await axios.post(notification.discordWebhookUrl, discordtestdata) - return okMsg; + }; + await axios.post(notification.discordWebhookUrl, discordtestdata); + return this.sendSuccess; } let url; @@ -49,7 +48,7 @@ class Discord extends NotificationProvider { }, { name: "Service URL", - value: url, + value: url.startsWith("http") ? "[Visit Service](" + url + ")" : url, }, { name: "Time (UTC)", @@ -61,14 +60,14 @@ class Discord extends NotificationProvider { }, ], }], - } + }; if (notification.discordPrefixMessage) { discorddowndata.content = notification.discordPrefixMessage; } - await axios.post(notification.discordWebhookUrl, discorddowndata) - return okMsg; + await axios.post(notification.discordWebhookUrl, discorddowndata); + return this.sendSuccess; } else if (heartbeatJSON["status"] == UP) { let discordupdata = { @@ -96,17 +95,17 @@ class Discord extends NotificationProvider { }, ], }], - } + }; if (notification.discordPrefixMessage) { discordupdata.content = notification.discordPrefixMessage; } - await axios.post(notification.discordWebhookUrl, discordupdata) - return okMsg; + await axios.post(notification.discordWebhookUrl, discordupdata); + return this.sendSuccess; } } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } diff --git a/server/notification-providers/discord.spec.js b/server/notification-providers/discord.spec.js index 1f9feb0e29..158300566f 100644 --- a/server/notification-providers/discord.spec.js +++ b/server/notification-providers/discord.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Discord = require("./discord"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,243 @@ describe("notification default information", () => { expect(notification.name).toBe("discord"); }); }); + +describe("notification to act properly on send", () => { + + it("should call axios with the proper data when missing heartbeat/monitor", async () => { + + let response = {}; + axios.post.mockResolvedValueOnce(response); + + let notif = new Discord(); + let url = "https://example.com/webhook"; + let notificationConf = { + discordUsername: "username", + discordWebhookUrl: url, + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith(url, { + content: "PassedInMessage", + username: "username" + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when having heartbeat & monitor & service up", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementationOnce(() => + new Date("2019-05-14T11:01:58.135Z").valueOf() + ); + + let response = {}; + axios.post.mockResolvedValueOnce(response); + + let notif = new Discord(); + let url = "https://example.com/webhook"; + let notificationConf = { + discordUsername: "username", + discordWebhookUrl: url, + discordPrefixMessage: "prefix", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing monitor", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + ping: "111" + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith(url, { + content: "prefix", + embeds: [ + { + color: 65280, + fields: [ + { + name: "Service Name", + value: "testing monitor", + }, + { + name: "Service URL", + value: "[Visit Service](https://www.google.com)", + }, + { + name: "Time (UTC)", + value: "example time", + }, + { + name: "Ping", + value: "111ms", + }, + ], + timestamp: "example time", + title: "✅ Your service testing monitor is up! ✅", + }, + ], + username: "username" + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when having heartbeat & monitor & service down", async () => { + + let response = {}; + axios.post.mockResolvedValueOnce(response); + + let notif = new Discord(); + let url = "https://example.com/webhook"; + let notificationConf = { + discordUsername: "username", + discordWebhookUrl: url, + discordPrefixMessage: "prefix", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing monitor", + }; + let heartbeatConf = { + status: DOWN, + msg: "some message", + time: "example time", + ping: "111" + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith(url, { + content: "prefix", + embeds: [ + { + color: 16711680, + fields: [ + { + name: "Service Name", + value: "testing monitor", + }, + { + name: "Service URL", + value: "[Visit Service](https://www.google.com)", + }, + { + name: "Time (UTC)", + value: "example time", + }, + { + name: "Error", + value: "some message", + }, + ], + timestamp: "example time", + title: "❌ Your service testing monitor went down. ❌", + }, + ], + username: "username" + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + + let notif = new Discord(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + discordWebhookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + + try { + await notif.send(notificationConf, msg, null, null); + console.log("fail"); + expect("Error thrown").toBe(false); + } catch (e) { + //axios general error on catching another error is not the cleanest, but works. + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://example.com/webhook", { + content: "PassedInMessage", + username: "Uptime Kuma" + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call sendMail with proper data", async () => { + + let response = {}; + axios.post.mockResolvedValueOnce(response); + + let url = "https://example.com/webhook"; + let notificationConf = { + type: "discord", + discordUsername: "username", + discordWebhookUrl: url, + discordPrefixMessage: "prefix", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing monitor", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + ping: "111" + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith(url, { + content: "prefix", + embeds: [ + { + color: 65280, + fields: [ + { + name: "Service Name", + value: "testing monitor", + }, + { + name: "Service URL", + value: "[Visit Service](https://www.google.com)", + }, + { + name: "Time (UTC)", + value: "example time", + }, + { + name: "Ping", + value: "111ms", + }, + ], + timestamp: "example time", + title: "✅ Your service testing monitor is up! ✅", + }, + ], + username: "username" + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 9a2d47679fdadd072aeba1fe72c3ee55b01811ef Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Fri, 22 Oct 2021 01:28:31 -0500 Subject: [PATCH 09/29] aliyun-sms tests --- server/notification-providers/aliyun-sms.js | 12 +- .../notification-providers/aliyun-sms.spec.js | 235 +++++++++++++++++- .../notification-providers/dingding.spec.js | 8 - 3 files changed, 236 insertions(+), 19 deletions(-) diff --git a/server/notification-providers/aliyun-sms.js b/server/notification-providers/aliyun-sms.js index 6a20632005..952efecd80 100644 --- a/server/notification-providers/aliyun-sms.js +++ b/server/notification-providers/aliyun-sms.js @@ -8,7 +8,6 @@ class AliyunSMS extends NotificationProvider { name = "AliyunSMS"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (heartbeatJSON != null) { @@ -18,8 +17,9 @@ class AliyunSMS extends NotificationProvider { status: this.statusToString(heartbeatJSON["status"]), msg: heartbeatJSON["msg"], }); - if (this.sendSms(notification, msgBody)) { - return okMsg; + if (await this.sendSms(notification, msgBody)) { + return this.sendSuccess; + //TODO account for cases where sendSMS returns false. } } else { let msgBody = JSON.stringify({ @@ -28,8 +28,8 @@ class AliyunSMS extends NotificationProvider { status: "", msg: msg, }); - if (this.sendSms(notification, msgBody)) { - return okMsg; + if (await this.sendSms(notification, msgBody)) { + return this.sendSuccess; } } } catch (error) { @@ -48,7 +48,7 @@ class AliyunSMS extends NotificationProvider { SignatureMethod: "HMAC-SHA1", SignatureVersion: "1.0", SignatureNonce: Math.random().toString(), - Timestamp: new Date().toISOString(), + Timestamp: new Date(Date.now()).toISOString(), Action: "SendSms", Version: "2017-05-25", }; diff --git a/server/notification-providers/aliyun-sms.spec.js b/server/notification-providers/aliyun-sms.spec.js index c8eb9488bb..c58a765ca6 100644 --- a/server/notification-providers/aliyun-sms.spec.js +++ b/server/notification-providers/aliyun-sms.spec.js @@ -1,13 +1,14 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios"); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); + +const { UP } = require("../../src/util"); +const NotificationSend = require("../notification"); const AliyunSMS = require("./aliyun-sms"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.mockReset(); }); describe("notification default information", () => { @@ -16,3 +17,227 @@ describe("notification default information", () => { expect(notification.name).toBe("AliyunSMS"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementation(() => + new Date("2019-05-14T11:01:58.135Z") + ); + + jest.spyOn(global.Math, "random") + .mockImplementation(() => + 0.0000111010100 + ); + + let response = { + data: { + Message: "OK" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new AliyunSMS(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios).toHaveBeenCalledWith({ + data: "TemplateParam=%7B%22name%22%3A%22testing%22%2C%22time%22%3A%22example%20time%22%2C%22status%22%3A%22UP%22%2C%22msg%22%3A%22some%20message%22%7D&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureVersion=1.0&SignatureNonce=0.00001110101&Timestamp=2019-05-14T11%3A01%3A58.135Z&Action=SendSms&Version=2017-05-25&Signature=73QTXvIaPHJIEo%2BCV1bzaZ5rzh4%3D", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + method: "POST", + url: "http://dysmsapi.aliyuncs.com/", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementation(() => + new Date("2019-05-14T11:01:58.135Z") + ); + + jest.spyOn(global.Math, "random") + .mockImplementation(() => + 0.0000111010100 + ); + + let response = { + data: { + Message: "OK" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new AliyunSMS(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios).toHaveBeenCalledWith({ + data: "TemplateParam=%7B%22name%22%3A%22%22%2C%22time%22%3A%22%22%2C%22status%22%3A%22%22%2C%22msg%22%3A%22PassedInMessage%22%7D&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureVersion=1.0&SignatureNonce=0.00001110101&Timestamp=2019-05-14T11%3A01%3A58.135Z&Action=SendSms&Version=2017-05-25&Signature=bXj4C8u60n6Xfiqf3VhtyqtW6Fk%3D", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + method: "POST", + url: "http://dysmsapi.aliyuncs.com/", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + + jest.spyOn(global.Date, "now") + .mockImplementation(() => + new Date("2019-05-14T11:01:58.135Z") + ); + + jest.spyOn(global.Math, "random") + .mockImplementation(() => + 0.0000111010100 + ); + + let response = { + data: { + Message: "OK" + } + }; + axios.mockResolvedValueOnce(response); + + let notif = new AliyunSMS(); + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios).toHaveBeenCalledWith({ + data: "TemplateParam=%7B%22name%22%3A%22%22%2C%22time%22%3A%22%22%2C%22status%22%3A%22%22%2C%22msg%22%3A%22PassedInMessage%22%7D&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureVersion=1.0&SignatureNonce=0.00001110101&Timestamp=2019-05-14T11%3A01%3A58.135Z&Action=SendSms&Version=2017-05-25&Signature=bXj4C8u60n6Xfiqf3VhtyqtW6Fk%3D", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + method: "POST", + url: "http://dysmsapi.aliyuncs.com/", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + jest.spyOn(global.Date, "now") + .mockImplementation(() => + new Date("2019-05-14T11:01:58.135Z") + ); + + jest.spyOn(global.Math, "random") + .mockImplementation(() => + 0.0000111010100 + ); + + axios.mockImplementation(() => { + throw new Error("Test Error"); + }); + + let notificationConf = { + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let msg = "PassedInMessage"; + let notif = new AliyunSMS(); + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + //axios general error on catching another error is not the cleanest, but works. + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios).toHaveBeenCalledWith({ + data: "TemplateParam=%7B%22name%22%3A%22%22%2C%22time%22%3A%22%22%2C%22status%22%3A%22%22%2C%22msg%22%3A%22PassedInMessage%22%7D&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureVersion=1.0&SignatureNonce=0.00001110101&Timestamp=2019-05-14T11%3A01%3A58.135Z&Action=SendSms&Version=2017-05-25&Signature=bXj4C8u60n6Xfiqf3VhtyqtW6Fk%3D", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + method: "POST", + url: "http://dysmsapi.aliyuncs.com/", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call sendMail with proper data", async () => { + jest.spyOn(global.Date, "now") + .mockImplementation(() => + new Date("2019-05-14T11:01:58.135Z") + ); + + jest.spyOn(global.Math, "random") + .mockImplementation(() => + 0.0000111010100 + ); + + let response = { + data: { + Message: "OK" + } + }; + axios.mockResolvedValueOnce(response); + let notificationConf = { + type: "AliyunSMS", + appriseURL: "appriseURL", + secretKey: "abc", + webHookUrl: "https://example.com/webhook", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios).toHaveBeenCalledWith({ + data: "TemplateParam=%7B%22name%22%3A%22testing%22%2C%22time%22%3A%22example%20time%22%2C%22status%22%3A%22UP%22%2C%22msg%22%3A%22some%20message%22%7D&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureVersion=1.0&SignatureNonce=0.00001110101&Timestamp=2019-05-14T11%3A01%3A58.135Z&Action=SendSms&Version=2017-05-25&Signature=73QTXvIaPHJIEo%2BCV1bzaZ5rzh4%3D", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + method: "POST", + url: "http://dysmsapi.aliyuncs.com/", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); diff --git a/server/notification-providers/dingding.spec.js b/server/notification-providers/dingding.spec.js index 15275318fe..6868385921 100644 --- a/server/notification-providers/dingding.spec.js +++ b/server/notification-providers/dingding.spec.js @@ -1,16 +1,8 @@ -// jest.mock("crypto", () => ({ -// createTransport: jest.fn(), -// createHmac: jest.fn(), -// digest: jest.fn(), -// })); - jest.mock("axios"); const { UP } = require("../../src/util"); const NotificationSend = require("../notification"); -// const mockNodeMailer = require("nodemailer"); - const DingDing = require("./dingding"); const axios = require("axios"); From 66f28479372951584a9684032c5076bcc11ee9c2 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sat, 23 Oct 2021 04:55:17 -0500 Subject: [PATCH 10/29] Feishu tests --- server/notification-providers/feishu.js | 7 +- server/notification-providers/feishu.spec.js | 166 ++++++++++++++++++- 2 files changed, 164 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/feishu.js b/server/notification-providers/feishu.js index a3e3403019..5ab8ca7285 100644 --- a/server/notification-providers/feishu.js +++ b/server/notification-providers/feishu.js @@ -6,7 +6,6 @@ class Feishu extends NotificationProvider { name = "Feishu"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; let feishuWebHookUrl = notification.feishuWebHookUrl; try { @@ -18,7 +17,7 @@ class Feishu extends NotificationProvider { }, }; await axios.post(feishuWebHookUrl, testdata); - return okMsg; + return this.sendSuccess; } if (heartbeatJSON["status"] == DOWN) { @@ -45,7 +44,7 @@ class Feishu extends NotificationProvider { }, }; await axios.post(feishuWebHookUrl, downdata); - return okMsg; + return this.sendSuccess; } if (heartbeatJSON["status"] == UP) { @@ -72,7 +71,7 @@ class Feishu extends NotificationProvider { }, }; await axios.post(feishuWebHookUrl, updata); - return okMsg; + return this.sendSuccess; } } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/feishu.spec.js b/server/notification-providers/feishu.spec.js index 5d349068bd..cb152f3335 100644 --- a/server/notification-providers/feishu.spec.js +++ b/server/notification-providers/feishu.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Feishu = require("./feishu"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,157 @@ describe("notification default information", () => { expect(notification.name).toBe("Feishu"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Feishu(); + let notificationConf = { + feishuWebHookUrl: "feishuWebHookUrl" + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("feishuWebHookUrl", { + content: { + post: { + zh_cn: { + content: [ + [ + { + tag: "text", + text: "[Up] some message\nTime (UTC): example time", + }, + ], + ], + title: "UptimeKuma Alert: testing", + }, + }, + }, + msg_type: "post", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Feishu(); + let notificationConf = { + feishuWebHookUrl: "feishuWebHookUrl" + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("feishuWebHookUrl", { + "content": { + "text": "PassedInMessage" + }, + "msg_type": "text" + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + + let notificationConf = { + feishuWebHookUrl: "feishuWebHookUrl" + + }; + let msg = "PassedInMessage"; + let notif = new Feishu(); + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("feishuWebHookUrl", { + content: { + text: "PassedInMessage", + }, + msg_type: "text", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "Feishu", + feishuWebHookUrl: "feishuWebHookUrl" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("feishuWebHookUrl", { + content: { + post: { + zh_cn: { + content: [ + [ + { + tag: "text", + text: "[Up] some message\nTime (UTC): example time", + }, + ], + ], + title: "UptimeKuma Alert: testing", + }, + }, + }, + msg_type: "post", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 266333e4f9a55aeca0ade9642fd89c772ef72e2e Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sat, 23 Oct 2021 06:05:08 -0500 Subject: [PATCH 11/29] gotify tests --- server/notification-providers/gotify.js | 5 +- server/notification-providers/gotify.spec.js | 146 ++++++++++++++++++- 2 files changed, 142 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/gotify.js b/server/notification-providers/gotify.js index 085261897f..dba6dea3e5 100644 --- a/server/notification-providers/gotify.js +++ b/server/notification-providers/gotify.js @@ -6,7 +6,6 @@ class Gotify extends NotificationProvider { name = "gotify"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) { notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1); @@ -15,9 +14,9 @@ class Gotify extends NotificationProvider { "message": msg, "priority": notification.gotifyPriority || 8, "title": "Uptime-Kuma", - }) + }); - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/gotify.spec.js b/server/notification-providers/gotify.spec.js index 02f3c71fc5..c88058da4f 100644 --- a/server/notification-providers/gotify.spec.js +++ b/server/notification-providers/gotify.spec.js @@ -1,18 +1,152 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Gotify = require("./gotify"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); - describe("notification default information", () => { it("should have the correct name", () => { let notification = new Gotify(); expect(notification.name).toBe("gotify"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Gotify(); + let notificationConf = { + gotifyserverurl: "url/", + gotifyPriority: 4, + gotifyapplicationToken: "token" + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("url/message?token=token", { + message: "PassedInMessage", + priority: 4, + title: "Uptime-Kuma", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Gotify(); + let notificationConf = { + gotifyserverurl: "url", + gotifyPriority: 4, + gotifyapplicationToken: "token" + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("url/message?token=token", { + message: "PassedInMessage", + priority: 4, + title: "Uptime-Kuma", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + + let notificationConf = { + gotifyserverurl: "url", + gotifyPriority: 4, + gotifyapplicationToken: "token" + }; + let msg = "PassedInMessage"; + let notif = new Gotify(); + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("url/message?token=token", { + message: "PassedInMessage", + priority: 4, + title: "Uptime-Kuma", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "gotify", + gotifyserverurl: "url", + gotifyPriority: 4, + gotifyapplicationToken: "token" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("url/message?token=token", { + message: "PassedInMessage", + priority: 4, + title: "Uptime-Kuma", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 37f486d4e4ec2f609c946f3fd20b09c85714de9e Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sat, 23 Oct 2021 06:49:41 -0500 Subject: [PATCH 12/29] Line Tests --- server/notification-providers/line.js | 21 +- server/notification-providers/line.spec.js | 224 ++++++++++++++++++++- 2 files changed, 229 insertions(+), 16 deletions(-) diff --git a/server/notification-providers/line.js b/server/notification-providers/line.js index 327696edd7..a9c2f585e7 100644 --- a/server/notification-providers/line.js +++ b/server/notification-providers/line.js @@ -7,7 +7,6 @@ class Line extends NotificationProvider { name = "line"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { let lineAPIUrl = "https://api.line.me/v2/bot/message/push"; let config = { @@ -25,34 +24,34 @@ class Line extends NotificationProvider { "text": "Test Successful!" } ] - } - await axios.post(lineAPIUrl, testMessage, config) + }; + await axios.post(lineAPIUrl, testMessage, config); } else if (heartbeatJSON["status"] == DOWN) { let downMessage = { "to": notification.lineUserID, "messages": [ { "type": "text", - "text": "UptimeKuma Alert: [🔴 Down]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"] + "text": "UptimeKuma Alert: [🔴 Down]\n" + "Name: " + monitorJSON["name"] + "\n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"] } ] - } - await axios.post(lineAPIUrl, downMessage, config) + }; + await axios.post(lineAPIUrl, downMessage, config); } else if (heartbeatJSON["status"] == UP) { let upMessage = { "to": notification.lineUserID, "messages": [ { "type": "text", - "text": "UptimeKuma Alert: [✅ Up]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"] + "text": "UptimeKuma Alert: [✅ Up]\n" + "Name: " + monitorJSON["name"] + "\n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"] } ] - } - await axios.post(lineAPIUrl, upMessage, config) + }; + await axios.post(lineAPIUrl, upMessage, config); } - return okMsg; + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } } diff --git a/server/notification-providers/line.spec.js b/server/notification-providers/line.spec.js index 10aa265409..97b8631cab 100644 --- a/server/notification-providers/line.spec.js +++ b/server/notification-providers/line.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Line = require("./line"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,215 @@ describe("notification default information", () => { expect(notification.name).toBe("line"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Line(); + let notificationConf = { + type: "line", + lineUserID: "1234", + lineChannelAccessToken: "token" + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.line.me/v2/bot/message/push", { + messages: [ + { + text: "UptimeKuma Alert: [✅ Up]\nName: testing\nsome message\nTime (UTC): example time", + type: "text", + }, + ], + to: "1234", + }, { + headers: { + "Authorization": "Bearer token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + it("should call axios with the proper default data when DOWN", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Line(); + let notificationConf = { + type: "line", + lineUserID: "1234", + lineChannelAccessToken: "token" + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: DOWN, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.line.me/v2/bot/message/push", { + messages: [ + { + text: "UptimeKuma Alert: [🔴 Down]\nName: testing\nsome message\nTime (UTC): example time", + type: "text", + }, + ], + to: "1234", + }, { + headers: { + "Authorization": "Bearer token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Line(); + let notificationConf = { + type: "line", + lineUserID: "1234", + lineChannelAccessToken: "token" + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://api.line.me/v2/bot/message/push", { + messages: [ + { + text: "Test Successful!", + type: "text", + }, + ], + to: "1234", + }, { + headers: { + "Authorization": "Bearer token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + + let notificationConf = { + type: "line", + lineUserID: "1234", + lineChannelAccessToken: "token" + }; + let msg = "PassedInMessage"; + let notif = new Line(); + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://api.line.me/v2/bot/message/push", { + messages: [ + { + text: "Test Successful!", + type: "text", + }, + ], + to: "1234", + }, { + headers: { + "Authorization": "Bearer token", + "Content-Type": "application/json", + }, + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "line", + lineUserID: "1234", + lineChannelAccessToken: "token" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://api.line.me/v2/bot/message/push", { + messages: [ + { + text: "UptimeKuma Alert: [✅ Up]\nName: testing\nsome message\nTime (UTC): example time", + type: "text", + }, + ], + to: "1234", + }, { + headers: { + "Authorization": "Bearer token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 4f12e942a72988cfa64682c5e8a8f3d9ecad0f9b Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sun, 24 Oct 2021 01:24:24 -0500 Subject: [PATCH 13/29] lunasea tests --- server/notification-providers/lunasea.js | 23 ++- server/notification-providers/lunasea.spec.js | 168 +++++++++++++++++- 2 files changed, 174 insertions(+), 17 deletions(-) diff --git a/server/notification-providers/lunasea.js b/server/notification-providers/lunasea.js index c41f400e2c..6b7ccb4297 100644 --- a/server/notification-providers/lunasea.js +++ b/server/notification-providers/lunasea.js @@ -7,39 +7,38 @@ class LunaSea extends NotificationProvider { name = "lunasea"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice + let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice; try { if (heartbeatJSON == null) { let testdata = { "title": "Uptime Kuma Alert", "body": "Testing Successful.", - } - await axios.post(lunaseadevice, testdata) - return okMsg; + }; + await axios.post(lunaseadevice, testdata); + return this.sendSuccess; } if (heartbeatJSON["status"] == DOWN) { let downdata = { "title": "UptimeKuma Alert: " + monitorJSON["name"], "body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"], - } - await axios.post(lunaseadevice, downdata) - return okMsg; + }; + await axios.post(lunaseadevice, downdata); + return this.sendSuccess; } if (heartbeatJSON["status"] == UP) { let updata = { "title": "UptimeKuma Alert: " + monitorJSON["name"], "body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"], - } - await axios.post(lunaseadevice, updata) - return okMsg; + }; + await axios.post(lunaseadevice, updata); + return this.sendSuccess; } } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } diff --git a/server/notification-providers/lunasea.spec.js b/server/notification-providers/lunasea.spec.js index 344e79433f..fd9639d1b3 100644 --- a/server/notification-providers/lunasea.spec.js +++ b/server/notification-providers/lunasea.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const LunaSea = require("./lunasea"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,159 @@ describe("notification default information", () => { expect(notification.name).toBe("lunasea"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new LunaSea(); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://notify.lunasea.app/v1/custom/device/1234", { + "body": "[✅ Up] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + }); + expect(res).toBe("Sent Successfully."); + }); + it("should call axios with the proper default data when DOWN", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new LunaSea(); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let msg = "PassedInMessage"; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: DOWN, + msg: "some message", + time: "example time", + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://notify.lunasea.app/v1/custom/device/1234", { + "body": "[🔴 Down] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new LunaSea(); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://notify.lunasea.app/v1/custom/device/1234", { + "body": "Testing Successful.", + "title": "Uptime Kuma Alert", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new LunaSea(); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let msg = "PassedInMessage"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://notify.lunasea.app/v1/custom/device/1234", { + + "body": "Testing Successful.", + "title": "Uptime Kuma Alert" }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://notify.lunasea.app/v1/custom/device/1234", { + "body": "[✅ Up] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From e0d211cbb4df34a0a957f88d35a746f877c58852 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sun, 24 Oct 2021 04:05:36 -0500 Subject: [PATCH 14/29] Matrix tests --- server/notification-providers/matrix.js | 3 +- server/notification-providers/matrix.spec.js | 163 ++++++++++++++++++- 2 files changed, 159 insertions(+), 7 deletions(-) diff --git a/server/notification-providers/matrix.js b/server/notification-providers/matrix.js index c1054fce65..26a85ff664 100644 --- a/server/notification-providers/matrix.js +++ b/server/notification-providers/matrix.js @@ -7,7 +7,6 @@ class Matrix extends NotificationProvider { name = "matrix"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; const size = 20; const randomString = encodeURIComponent( @@ -35,7 +34,7 @@ class Matrix extends NotificationProvider { }; await axios.put(`${notification.homeserverUrl}/_matrix/client/r0/rooms/${roomId}/send/m.room.message/${randomString}`, data, config); - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/matrix.spec.js b/server/notification-providers/matrix.spec.js index 94c84b56af..326d93321a 100644 --- a/server/notification-providers/matrix.spec.js +++ b/server/notification-providers/matrix.spec.js @@ -1,13 +1,20 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + put: jest.fn(), +})); +jest.mock("crypto", () => ({ + randomBytes: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Matrix = require("./matrix"); +const Crypto = require("crypto"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.put.mockReset(); + Crypto.randomBytes.mockReset(); }); describe("notification default information", () => { @@ -16,3 +23,149 @@ describe("notification default information", () => { expect(notification.name).toBe("matrix"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.put.mockResolvedValueOnce(response); + Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + + let notif = new Matrix(); + + let msg = "PassedInMessage"; + let notificationConf = { + type: "matrix", + internalRoomId: "1234", + accessToken: "abcd", + homeserverUrl: "www.example.com", + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.put).toHaveBeenCalledWith("www.example.com/_matrix/client/r0/rooms/1234/send/m.room.message/YWJjZA%3D%3D", { + body: "PassedInMessage", + msgtype: "m.text" + }, { + headers: { + "Authorization": "Bearer abcd" + } + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.put.mockResolvedValueOnce(response); + Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + + let notif = new Matrix(); + let notificationConf = { + type: "matrix", + internalRoomId: "1234", + accessToken: "abcd", + homeserverUrl: "www.example.com", + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.put).toHaveBeenCalledWith("www.example.com/_matrix/client/r0/rooms/1234/send/m.room.message/YWJjZA%3D%3D", { + body: "PassedInMessage", + msgtype: "m.text" + }, { + headers: { + "Authorization": "Bearer abcd" + } + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.put.mockImplementation(() => { + throw new Error("Test Error"); + }); + Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + + let notif = new Matrix(); + let notificationConf = { + type: "matrix", + internalRoomId: "1234", + accessToken: "abcd", + homeserverUrl: "www.example.com", + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.put).toHaveBeenCalledWith("www.example.com/_matrix/client/r0/rooms/1234/send/m.room.message/YWJjZA%3D%3D", { + body: "PassedInMessage", + msgtype: "m.text" + }, { + headers: { + "Authorization": "Bearer abcd" + } + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.put.mockResolvedValueOnce(response); + Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + + let notificationConf = { + type: "matrix", + internalRoomId: "1234", + accessToken: "abcd", + homeserverUrl: "www.example.com", + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.put).toHaveBeenCalledWith("www.example.com/_matrix/client/r0/rooms/1234/send/m.room.message/YWJjZA%3D%3D", { + body: "PassedInMessage", + msgtype: "m.text" + }, { + headers: { + "Authorization": "Bearer abcd" + } + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From ba3fefa7b813715c2831b83ccf079644de1b6aeb Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sun, 24 Oct 2021 04:16:23 -0500 Subject: [PATCH 15/29] mattermost tests --- server/notification-providers/mattermost.js | 15 +- .../notification-providers/mattermost.spec.js | 289 +++++++++++++++++- 2 files changed, 291 insertions(+), 13 deletions(-) diff --git a/server/notification-providers/mattermost.js b/server/notification-providers/mattermost.js index d776284bea..1d2581155f 100644 --- a/server/notification-providers/mattermost.js +++ b/server/notification-providers/mattermost.js @@ -7,7 +7,6 @@ class Mattermost extends NotificationProvider { name = "mattermost"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { const mattermostUserName = notification.mattermostusername || "Uptime Kuma"; // If heartbeatJSON is null, assume we're testing. @@ -15,9 +14,9 @@ class Mattermost extends NotificationProvider { let mattermostTestData = { username: mattermostUserName, text: msg, - } - await axios.post(notification.mattermostWebhookUrl, mattermostTestData) - return okMsg; + }; + await axios.post(notification.mattermostWebhookUrl, mattermostTestData); + return this.sendSuccess; } const mattermostChannel = notification.mattermostchannel; @@ -36,12 +35,12 @@ class Mattermost extends NotificationProvider { fallback: "Your " + monitorJSON["name"] + - " service went down.", + " service went down!", color: "#FF0000", title: "❌ " + monitorJSON["name"] + - " service went down. ❌", + " service went down! ❌", title_link: monitorJSON["url"], fields: [ { @@ -67,7 +66,7 @@ class Mattermost extends NotificationProvider { notification.mattermostWebhookUrl, mattermostdowndata ); - return okMsg; + return this.sendSuccess; } else if (heartbeatJSON["status"] == UP) { let mattermostupdata = { username: mattermostUserName, @@ -111,7 +110,7 @@ class Mattermost extends NotificationProvider { notification.mattermostWebhookUrl, mattermostupdata ); - return okMsg; + return this.sendSuccess; } } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/mattermost.spec.js b/server/notification-providers/mattermost.spec.js index 81d6490070..fa3979ba17 100644 --- a/server/notification-providers/mattermost.spec.js +++ b/server/notification-providers/mattermost.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Mattermost = require("./mattermost"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,280 @@ describe("notification default information", () => { expect(notification.name).toBe("mattermost"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Mattermost(); + let notificationConf = { + type: "mattermost", + mattermostchannel: "1234", + mattermosticonemo: "😀", + mattermosticonurl: "www.testing.com", + mattermostWebhookUrl: "www.example.com/webhook", + mattermostusername: "username", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + ping: "123", + time: "example time", + }; + let msg = "PassedInMessage"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("www.example.com/webhook", { + "attachments": [ + { + "color": "#32CD32", + "fallback": "Your testing service went up!", + "fields": [ + { + "short": true, + "title": "Service Name", + "value": "testing", + }, + { + "short": true, + "title": "Time (UTC)", + "value": "example time", + }, + { + "short": false, + "title": "Ping", + "value": "123ms", + }, + ], + "title": "✅ testing service went up! ✅", + "title_link": "https://www.google.com", + }, + ], + "channel": "1234", + "icon_emoji": "😀", + "icon_url": "www.testing.com", + "text": "Uptime Kuma Alert", + "username": "username", + }); + expect(res).toBe("Sent Successfully."); + }); + it("should call axios with the proper default data when DOWN", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Mattermost(); + let notificationConf = { + type: "mattermost", + mattermostchannel: "1234", + mattermosticonemo: "😀", + mattermosticonurl: "www.testing.com", + mattermostWebhookUrl: "www.example.com/webhook", + mattermostusername: "username", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: DOWN, + msg: "some message", + ping: "123", + time: "example time", + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("www.example.com/webhook", { + "attachments": [ + { + "color": "#FF0000", + "fallback": "Your testing service went down!", + "fields": [ + { + "short": true, + "title": "Service Name", + "value": "testing", + }, + { + "short": true, + "title": "Time (UTC)", + "value": "example time", + }, + { + "short": false, + "title": "Error", + "value": "some message", + }, + ], + "title": "❌ testing service went down! ❌", + "title_link": "https://www.google.com", + }, + ], + "channel": "1234", + "icon_emoji": "😀", + "icon_url": "www.testing.com", + "text": "Uptime Kuma Alert", + "username": "username", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Mattermost(); + let notificationConf = { + type: "mattermost", + mattermostchannel: "1234", + mattermosticonemo: "😀", + mattermosticonurl: "www.testing.com", + mattermostWebhookUrl: "www.example.com/webhook", + mattermostusername: "username", + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("www.example.com/webhook", { + + "text": "PassedInMessage", + "username": "username" + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Mattermost(); + let notificationConf = { + type: "mattermost", + mattermostchannel: "1234", + mattermosticonemo: "😀", + mattermosticonurl: "www.testing.com", + mattermostWebhookUrl: "www.example.com/webhook", + mattermostusername: "username", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + ping: "123", + time: "example time", + }; + let msg = "PassedInMessage"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("www.example.com/webhook", { + + "text": "PassedInMessage", + "username": "username" + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "mattermost", + mattermostchannel: "1234", + mattermosticonemo: "😀", + mattermosticonurl: "www.testing.com", + mattermostWebhookUrl: "www.example.com/webhook", + mattermostusername: "username", + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + ping: "123", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "PassedInMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("www.example.com/webhook", { + "attachments": [ + { + "color": "#32CD32", + "fallback": "Your testing service went up!", + "fields": [ + { + "short": true, + "title": "Service Name", + "value": "testing", + }, + { + "short": true, + "title": "Time (UTC)", + "value": "example time", + }, + { + "short": false, + "title": "Ping", + "value": "123ms", + }, + ], + "title": "✅ testing service went up! ✅", + "title_link": "https://www.google.com", + }, + ], + "channel": "1234", + "icon_emoji": "😀", + "icon_url": "www.testing.com", + "text": "Uptime Kuma Alert", + "username": "username", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 6ce6d034a8d7bdbbbf119a680d2b1503908587ce Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Sun, 24 Oct 2021 04:51:35 -0500 Subject: [PATCH 16/29] octopush tests --- server/notification-providers/octopush.js | 7 +- .../notification-providers/octopush.spec.js | 237 +++++++++++++++++- 2 files changed, 235 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/octopush.js b/server/notification-providers/octopush.js index 9d77aa5b47..6ef8e3905d 100644 --- a/server/notification-providers/octopush.js +++ b/server/notification-providers/octopush.js @@ -6,7 +6,6 @@ class Octopush extends NotificationProvider { name = "octopush"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { // Default - V2 @@ -30,7 +29,7 @@ class Octopush extends NotificationProvider { "purpose": "alert", "sender": notification.octopushSenderName }; - await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config) + await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config); } else if (notification.octopushVersion == 1) { let data = { "user_login": notification.octopushDMLogin, @@ -49,12 +48,12 @@ class Octopush extends NotificationProvider { }, params: data }; - await axios.post("https://www.octopush-dm.com/api/sms/json", {}, config) + await axios.post("https://www.octopush-dm.com/api/sms/json", {}, config); } else { throw new Error("Unknown Octopush version!"); } - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/octopush.spec.js b/server/notification-providers/octopush.spec.js index 3c16c3a5e6..75ac66763a 100644 --- a/server/notification-providers/octopush.spec.js +++ b/server/notification-providers/octopush.spec.js @@ -1,13 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); const Octopush = require("./octopush"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); describe("notification default information", () => { @@ -16,3 +18,228 @@ describe("notification default information", () => { expect(notification.name).toBe("octopush"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when version 2", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Octopush(); + let notificationConf = { + type: "octopush", + octopushVersion: 2, + octopushAPIKey: "key", + octopushLogin: "login", + octopushPhoneNumber: "number", + octopushSMSType: "type", + octopushSenderName: "sender" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.octopush.com/v1/public/sms-campaign/send", { + "purpose": "alert", + "recipients": [{ "phone_number": "number" }], + "sender": "sender", + "text": "PassedInMessage", + "type": "type" + }, { + "headers": { + "api-key": "key", + "api-login": "login", + "cache-control": "no-cache" + } + }); + expect(res).toBe("Sent Successfully."); + }); + it("should call axios with the proper default data when version 1", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Octopush(); + let notificationConf = { + type: "octopush", + octopushVersion: 1, + octopushDMAPIKey: "key", + octopushDMLogin: "login", + octopushDMPhoneNumber: "number", + octopushDMSMSType: "sms_premium", + octopushDMSenderName: "sender" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://www.octopush-dm.com/api/sms/json", { + + }, { + "headers": { + "cache-control": "no-cache" + }, + "params": { + "api_key": "key", + "sms_recipients": "number", + "sms_sender": "sender", + "sms_text": "PassedInMessage", + "sms_type": "FR", + "transactional": "1", + "user_login": "login" + } + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Octopush(); + let notificationConf = { + type: "lunasea", + lunaseaDevice: "1234", + }; + let msg = "PassedInMessage"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://api.octopush.com/v1/public/sms-campaign/send", { + "purpose": "alert", + "recipients": [{ "phone_number": undefined }], + "sender": undefined, + "text": "PassedInMessage", + "type": undefined + }, { + "headers": { + "api-key": undefined, + "api-login": undefined, + "cache-control": "no-cache" + } + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Octopush(); + let notificationConf = { + type: "octopush", + octopushVersion: 2, + octopushAPIKey: "key", + octopushLogin: "login", + octopushPhoneNumber: "number", + octopushSMSType: "type", + octopushSenderName: "sender" + }; + let msg = "PassedInMessage"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://api.octopush.com/v1/public/sms-campaign/send", { + "purpose": "alert", + "recipients": [{ "phone_number": "number" }], + "sender": "sender", + "text": "PassedInMessage", + "type": "type" + }, { + "headers": { + "api-key": "key", + "api-login": "login", + "cache-control": "no-cache" + } + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "octopush", + octopushVersion: 2, + octopushAPIKey: "key", + octopushLogin: "login", + octopushPhoneNumber: "number", + octopushSMSType: "type", + octopushSenderName: "sender" + }; + let monitorConf = { + type: "http", + url: "https://www.google.com", + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, "Passed😀InMessage", monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://api.octopush.com/v1/public/sms-campaign/send", { + "purpose": "alert", + "recipients": [{ "phone_number": "number" }], + "sender": "sender", + "text": "PassedInMessage", + "type": "type" + }, { + "headers": { + "api-key": "key", + "api-login": "login", + "cache-control": "no-cache" + } + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From d818ce866db18998100586a1c1da8ae2cf5bffdb Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 02:37:31 -0500 Subject: [PATCH 17/29] promosms tests --- server/notification-providers/promosms.js | 7 +- .../notification-providers/promosms.spec.js | 189 +++++++++++++++++- 2 files changed, 185 insertions(+), 11 deletions(-) diff --git a/server/notification-providers/promosms.js b/server/notification-providers/promosms.js index 362ef714ad..4f0e526ce3 100644 --- a/server/notification-providers/promosms.js +++ b/server/notification-providers/promosms.js @@ -6,13 +6,12 @@ class PromoSMS extends NotificationProvider { name = "promosms"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { let config = { headers: { "Content-Type": "application/json", - "Authorization": "Basic " + Buffer.from(notification.promosmsLogin + ":" + notification.promosmsPassword).toString('base64'), + "Authorization": "Basic " + Buffer.from(notification.promosmsLogin + ":" + notification.promosmsPassword).toString("base64"), "Accept": "text/json", } }; @@ -30,8 +29,8 @@ class PromoSMS extends NotificationProvider { let error = "Something gone wrong. Api returned " + resp.data.response.status + "."; this.throwGeneralAxiosError(error); } - - return okMsg; + + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/promosms.spec.js b/server/notification-providers/promosms.spec.js index 3d9dde7f27..6802341743 100644 --- a/server/notification-providers/promosms.spec.js +++ b/server/notification-providers/promosms.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const PromoSMS = require("./promosms"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const PromoSMS = require("./promosms"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,177 @@ describe("notification default information", () => { expect(notification.name).toBe("promosms"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + response: { + status: 0 + }, + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new PromoSMS(); + let notificationConf = { + type: "promosms", + promosmsLogin: "login", + promosmsPassword: "password", + promosmsPhoneNumber: "number", + promosmsSMSType: 1, + promosmsSenderName: "sender" + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://promosms.com/api/rest/v3_2/sms", { + "recipients": [ + "number", + ], + "sender": "sender", + "text": "PassedInMessage", + "type": 1, + }, { + "headers": { + "Accept": "text/json", + "Authorization": "Basic bG9naW46cGFzc3dvcmQ=", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + response: { + status: 0 + }, + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new PromoSMS(); + let notificationConf = { + type: "promosms", + promosmsLogin: "login", + promosmsPassword: "password", + promosmsPhoneNumber: "number", + promosmsSMSType: 1, + promosmsSenderName: "sender" + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://promosms.com/api/rest/v3_2/sms", { + "recipients": [ + "number", + ], + "sender": "sender", + "text": "PassedInMessage", + "type": 1, + }, { + "headers": { + "Accept": "text/json", + "Authorization": "Basic bG9naW46cGFzc3dvcmQ=", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new PromoSMS(); + let notificationConf = { + type: "promosms", + promosmsLogin: "login", + promosmsPassword: "password", + promosmsPhoneNumber: "number", + promosmsSMSType: 1, + promosmsSenderName: "sender" + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://promosms.com/api/rest/v3_2/sms", { + "recipients": [ + "number", + ], + "sender": "sender", + "text": "PassedInMessage", + "type": 1, + }, { + "headers": { + "Accept": "text/json", + "Authorization": "Basic bG9naW46cGFzc3dvcmQ=", + "Content-Type": "application/json", + }, + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + response: { + status: 0 + }, + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "promosms", + promosmsLogin: "login", + promosmsPassword: "password", + promosmsPhoneNumber: "number", + promosmsSMSType: 1, + promosmsSenderName: "sender" + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://promosms.com/api/rest/v3_2/sms", { + "recipients": [ + "number", + ], + "sender": "sender", + "text": "PassedInMessage", + "type": 1, + }, { + "headers": { + "Accept": "text/json", + "Authorization": "Basic bG9naW46cGFzc3dvcmQ=", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From b229f36ea19a4adbf19083bde8a4c69258737152 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 02:44:22 -0500 Subject: [PATCH 18/29] pushbullet test --- server/notification-providers/pushbullet.js | 17 +- .../notification-providers/pushbullet.spec.js | 197 +++++++++++++++++- server/notification-providers/pushover.js | 17 +- .../notification-providers/pushover.spec.js | 137 +++++++++++- 4 files changed, 336 insertions(+), 32 deletions(-) diff --git a/server/notification-providers/pushbullet.js b/server/notification-providers/pushbullet.js index c7b824a2c6..9de5b61fef 100644 --- a/server/notification-providers/pushbullet.js +++ b/server/notification-providers/pushbullet.js @@ -8,7 +8,6 @@ class Pushbullet extends NotificationProvider { name = "pushbullet"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { let pushbulletUrl = "https://api.pushbullet.com/v2/pushes"; @@ -23,26 +22,26 @@ class Pushbullet extends NotificationProvider { "type": "note", "title": "Uptime Kuma Alert", "body": "Testing Successful.", - } - await axios.post(pushbulletUrl, testdata, config) + }; + await axios.post(pushbulletUrl, testdata, config); } else if (heartbeatJSON["status"] == DOWN) { let downdata = { "type": "note", "title": "UptimeKuma Alert: " + monitorJSON["name"], "body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"], - } - await axios.post(pushbulletUrl, downdata, config) + }; + await axios.post(pushbulletUrl, downdata, config); } else if (heartbeatJSON["status"] == UP) { let updata = { "type": "note", "title": "UptimeKuma Alert: " + monitorJSON["name"], "body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"], - } - await axios.post(pushbulletUrl, updata, config) + }; + await axios.post(pushbulletUrl, updata, config); } - return okMsg; + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } } diff --git a/server/notification-providers/pushbullet.spec.js b/server/notification-providers/pushbullet.spec.js index 1cad877994..8958b5e79f 100644 --- a/server/notification-providers/pushbullet.spec.js +++ b/server/notification-providers/pushbullet.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Pushbullet = require("./pushbullet"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Pushbullet = require("./pushbullet"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,185 @@ describe("notification default information", () => { expect(notification.name).toBe("pushbullet"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushbullet(); + let notificationConf = { + type: "pushbullet", + pushbulletAccessToken: "token", + }; + let monitorConf = { + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushbullet.com/v2/pushes", { + "body": "[✅ Up] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + "type": "note", + }, { + "headers": { + "Access-Token": "token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushbullet(); + let notificationConf = { + type: "pushbullet", + pushbulletAccessToken: "token", + }; + let monitorConf = { + name: "testing", + }; + let heartbeatConf = { + status: DOWN, + msg: "some message", + time: "example time", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushbullet.com/v2/pushes", { + "body": "[🔴 Down] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + "type": "note", + }, { + "headers": { + "Access-Token": "token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushbullet(); + let notificationConf = { + type: "pushbullet", + pushbulletAccessToken: "token", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushbullet.com/v2/pushes", { + "body": "Testing Successful.", + "title": "Uptime Kuma Alert", + "type": "note", + }, { + "headers": { + "Access-Token": "token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Pushbullet(); + let notificationConf = { + type: "pushbullet", + pushbulletAccessToken: "token", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://api.pushbullet.com/v2/pushes", { + "body": "Testing Successful.", + "title": "Uptime Kuma Alert", + "type": "note", + }, { + "headers": { + "Access-Token": "token", + "Content-Type": "application/json", + }, + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "pushbullet", + pushbulletAccessToken: "token", + }; + let monitorConf = { + name: "testing", + }; + let heartbeatConf = { + status: UP, + msg: "some message", + time: "example time", + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://api.pushbullet.com/v2/pushes", { + "body": "[✅ Up] some message\nTime (UTC): example time", + "title": "UptimeKuma Alert: testing", + "type": "note", + }, { + "headers": { + "Access-Token": "token", + "Content-Type": "application/json", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); diff --git a/server/notification-providers/pushover.js b/server/notification-providers/pushover.js index 77ef1a3f0a..76aa059c02 100644 --- a/server/notification-providers/pushover.js +++ b/server/notification-providers/pushover.js @@ -6,8 +6,7 @@ class Pushover extends NotificationProvider { name = "pushover"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let pushoverlink = "https://api.pushover.net/1/messages.json" + let pushoverlink = "https://api.pushover.net/1/messages.json"; try { if (heartbeatJSON == null) { @@ -21,9 +20,9 @@ class Pushover extends NotificationProvider { "retry": "30", "expire": "3600", "html": 1, - } - await axios.post(pushoverlink, data) - return okMsg; + }; + await axios.post(pushoverlink, data); + return this.sendSuccess; } let data = { @@ -36,11 +35,11 @@ class Pushover extends NotificationProvider { "retry": "30", "expire": "3600", "html": 1, - } - await axios.post(pushoverlink, data) - return okMsg; + }; + await axios.post(pushoverlink, data); + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } diff --git a/server/notification-providers/pushover.spec.js b/server/notification-providers/pushover.spec.js index dcc3adc037..d86676b5db 100644 --- a/server/notification-providers/pushover.spec.js +++ b/server/notification-providers/pushover.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Pushover = require("./pushover"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Pushover = require("./pushover"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,125 @@ describe("notification default information", () => { expect(notification.name).toBe("pushover"); }); }); + +// describe("notification to act properly on send", () => { +// it("should call axios with the proper default data", async () => { + +// let response = { +// data: { +// Message: "OK" +// } +// }; +// axios.post.mockResolvedValueOnce(response); + +// let notif = new Pushover(); +// let notificationConf = { +// type: "octopush", +// pushoveruserkey: "123", +// pushoverapptoken: "token", +// pushoversounds: "ding", +// pushoverpriority: "6", +// pushovertitle: "Important Title!", +// }; +// let monitorConf = { +// }; +// let heartbeatConf = { +// time: "example time", +// }; +// let msg = "PassedInMessage😀"; +// let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + +// expect(axios.post).toHaveBeenCalledWith("", { +// }); +// expect(res).toBe("Sent Successfully."); +// }); + +// it("should call axios with the proper data when monitor nil", async () => { +// let response = { +// data: { +// Message: "OK" +// } +// }; +// axios.post.mockResolvedValueOnce(response); + +// let notif = new Pushover(); +// let notificationConf = { +// type: "octopush", +// pushoveruserkey: "123", +// pushoverapptoken: "token", +// pushoversounds: "ding", +// pushoverpriority: "6", +// pushovertitle: "Important Title!", +// }; +// let msg = "PassedInMessage😀"; + +// let res = await notif.send(notificationConf, msg, null, null); + +// expect(axios.post).toHaveBeenCalledWith("", { +// }); +// expect(res).toBe("Sent Successfully."); +// }); + +// }); + +// describe("notification to act properly on error", () => { +// it("should respond with an axios error on error", async () => { + +// axios.post.mockImplementation(() => { +// throw new Error("Test Error"); +// }); +// let notif = new Pushover(); +// let notificationConf = { +// type: "octopush", +// pushoveruserkey: "123", +// pushoverapptoken: "token", +// pushoversounds: "ding", +// pushoverpriority: "6", +// pushovertitle: "Important Title!", +// }; +// let msg = "PassedInMessage😀"; + +// try { +// await notif.send(notificationConf, msg, null, null); +// expect("Error thrown").toBe(false); +// } catch (e) { +// expect(e.message).toBe("Error: Error: Test Error "); +// } + +// expect(axios.post).toHaveBeenCalledWith("", { +// }); +// }); + +// }); + +// describe("notification to get proper data from Notification.send", () => { +// it("should call axios with proper data", async () => { +// let response = { +// data: { +// Message: "OK" +// } +// }; +// axios.post.mockResolvedValueOnce(response); +// let notificationConf = { +// type: "octopush", +// pushoveruserkey: "123", +// pushoverapptoken: "token", +// pushoversounds: "ding", +// pushoverpriority: "6", +// pushovertitle: "Important Title!", +// }; +// let monitorConf = { +// }; +// let heartbeatConf = { +// time: "example time", +// }; +// let msg = "PassedInMessage😀"; + +// NotificationSend.Notification.init(); +// let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); +// expect(axios.post).toHaveBeenCalledWith("", { +// }); +// expect(res).toBe("Sent Successfully."); +// }); + +// }); From a6f14f57cf02fe60045b42a6f38a21ffe948b5dd Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 02:56:22 -0500 Subject: [PATCH 19/29] pushover tests --- server/notification-providers/matrix.spec.js | 8 +- .../notification-providers/pushover.spec.js | 278 ++++++++++-------- 2 files changed, 161 insertions(+), 125 deletions(-) diff --git a/server/notification-providers/matrix.spec.js b/server/notification-providers/matrix.spec.js index 326d93321a..b70c56930d 100644 --- a/server/notification-providers/matrix.spec.js +++ b/server/notification-providers/matrix.spec.js @@ -33,7 +33,7 @@ describe("notification to act properly on send", () => { } }; axios.put.mockResolvedValueOnce(response); - Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + Crypto.randomBytes.mockReturnValueOnce(Buffer.from("abcd")); let notif = new Matrix(); @@ -68,7 +68,7 @@ describe("notification to act properly on send", () => { } }; axios.put.mockResolvedValueOnce(response); - Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + Crypto.randomBytes.mockReturnValueOnce(Buffer.from("abcd")); let notif = new Matrix(); let notificationConf = { @@ -100,7 +100,7 @@ describe("notification to act properly on error", () => { axios.put.mockImplementation(() => { throw new Error("Test Error"); }); - Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + Crypto.randomBytes.mockReturnValueOnce(Buffer.from("abcd")); let notif = new Matrix(); let notificationConf = { @@ -142,7 +142,7 @@ describe("notification to get proper data from Notification.send", () => { } }; axios.put.mockResolvedValueOnce(response); - Crypto.randomBytes.mockReturnValueOnce(new Buffer("abcd")); + Crypto.randomBytes.mockReturnValueOnce(Buffer.from("abcd")); let notificationConf = { type: "matrix", diff --git a/server/notification-providers/pushover.spec.js b/server/notification-providers/pushover.spec.js index d86676b5db..d6ee4f736e 100644 --- a/server/notification-providers/pushover.spec.js +++ b/server/notification-providers/pushover.spec.js @@ -18,124 +18,160 @@ describe("notification default information", () => { }); }); -// describe("notification to act properly on send", () => { -// it("should call axios with the proper default data", async () => { - -// let response = { -// data: { -// Message: "OK" -// } -// }; -// axios.post.mockResolvedValueOnce(response); - -// let notif = new Pushover(); -// let notificationConf = { -// type: "octopush", -// pushoveruserkey: "123", -// pushoverapptoken: "token", -// pushoversounds: "ding", -// pushoverpriority: "6", -// pushovertitle: "Important Title!", -// }; -// let monitorConf = { -// }; -// let heartbeatConf = { -// time: "example time", -// }; -// let msg = "PassedInMessage😀"; -// let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); - -// expect(axios.post).toHaveBeenCalledWith("", { -// }); -// expect(res).toBe("Sent Successfully."); -// }); - -// it("should call axios with the proper data when monitor nil", async () => { -// let response = { -// data: { -// Message: "OK" -// } -// }; -// axios.post.mockResolvedValueOnce(response); - -// let notif = new Pushover(); -// let notificationConf = { -// type: "octopush", -// pushoveruserkey: "123", -// pushoverapptoken: "token", -// pushoversounds: "ding", -// pushoverpriority: "6", -// pushovertitle: "Important Title!", -// }; -// let msg = "PassedInMessage😀"; - -// let res = await notif.send(notificationConf, msg, null, null); - -// expect(axios.post).toHaveBeenCalledWith("", { -// }); -// expect(res).toBe("Sent Successfully."); -// }); - -// }); - -// describe("notification to act properly on error", () => { -// it("should respond with an axios error on error", async () => { - -// axios.post.mockImplementation(() => { -// throw new Error("Test Error"); -// }); -// let notif = new Pushover(); -// let notificationConf = { -// type: "octopush", -// pushoveruserkey: "123", -// pushoverapptoken: "token", -// pushoversounds: "ding", -// pushoverpriority: "6", -// pushovertitle: "Important Title!", -// }; -// let msg = "PassedInMessage😀"; - -// try { -// await notif.send(notificationConf, msg, null, null); -// expect("Error thrown").toBe(false); -// } catch (e) { -// expect(e.message).toBe("Error: Error: Test Error "); -// } - -// expect(axios.post).toHaveBeenCalledWith("", { -// }); -// }); - -// }); - -// describe("notification to get proper data from Notification.send", () => { -// it("should call axios with proper data", async () => { -// let response = { -// data: { -// Message: "OK" -// } -// }; -// axios.post.mockResolvedValueOnce(response); -// let notificationConf = { -// type: "octopush", -// pushoveruserkey: "123", -// pushoverapptoken: "token", -// pushoversounds: "ding", -// pushoverpriority: "6", -// pushovertitle: "Important Title!", -// }; -// let monitorConf = { -// }; -// let heartbeatConf = { -// time: "example time", -// }; -// let msg = "PassedInMessage😀"; - -// NotificationSend.Notification.init(); -// let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); -// expect(axios.post).toHaveBeenCalledWith("", { -// }); -// expect(res).toBe("Sent Successfully."); -// }); - -// }); +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushover(); + let notificationConf = { + type: "octopush", + pushoveruserkey: "123", + pushoverapptoken: "token", + pushoversounds: "ding", + pushoverpriority: "6", + pushovertitle: "Important Title!", + }; + let monitorConf = { + }; + let heartbeatConf = { + time: "example time", + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushover.net/1/messages.json", { + "expire": "3600", + "html": 1, + "message": "Uptime Kuma Alert\n\nMessage:PassedInMessage😀\nTime (UTC):example time", + "priority": "6", + "retry": "30", + "sound": "ding", + "title": "Important Title!", + "token": "token", + "user": "123", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushover(); + let notificationConf = { + type: "octopush", + pushoveruserkey: "123", + pushoverapptoken: "token", + pushoversounds: "ding", + pushoverpriority: "6", + pushovertitle: "Important Title!", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushover.net/1/messages.json", { + "expire": "3600", + "html": 1, + "message": "Uptime Kuma Pushover testing successful.", + "priority": "6", + "retry": "30", + "sound": "ding", + "title": "Important Title!", + "token": "token", + "user": "123", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Pushover(); + let notificationConf = { + type: "octopush", + pushoveruserkey: "123", + pushoverapptoken: "token", + pushoversounds: "ding", + pushoverpriority: "6", + pushovertitle: "Important Title!", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://api.pushover.net/1/messages.json", { + "expire": "3600", + "html": 1, + "message": "Uptime Kuma Pushover testing successful.", + "priority": "6", + "retry": "30", + "sound": "ding", + "title": "Important Title!", + "token": "token", + "user": "123", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "pushover", + pushoveruserkey: "123", + pushoverapptoken: "token", + pushoversounds: "ding", + pushoverpriority: "6", + pushovertitle: "Important Title!", + }; + let monitorConf = { + }; + let heartbeatConf = { + time: "example time", + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://api.pushover.net/1/messages.json", { + "expire": "3600", + "html": 1, + "message": "Uptime Kuma Alert\n\nMessage:PassedInMessage😀\nTime (UTC):example time", + "priority": "6", + "retry": "30", + "sound": "ding", + "title": "Important Title!", + "token": "token", + "user": "123", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 60ad28592dd7c32c2eec5bda6b528cfdede16946 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 20:27:06 -0500 Subject: [PATCH 20/29] pushy tests --- server/notification-providers/pushy.js | 7 +- server/notification-providers/pushy.spec.js | 157 +++++++++++++++++++- 2 files changed, 153 insertions(+), 11 deletions(-) diff --git a/server/notification-providers/pushy.js b/server/notification-providers/pushy.js index 2bb899349b..f18c915c45 100644 --- a/server/notification-providers/pushy.js +++ b/server/notification-providers/pushy.js @@ -6,7 +6,6 @@ class Pushy extends NotificationProvider { name = "pushy"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, { @@ -19,10 +18,10 @@ class Pushy extends NotificationProvider { "badge": 1, "sound": "ping.aiff" } - }) - return okMsg; + }); + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } } diff --git a/server/notification-providers/pushy.spec.js b/server/notification-providers/pushy.spec.js index 477e2cee77..4fada3dbe3 100644 --- a/server/notification-providers/pushy.spec.js +++ b/server/notification-providers/pushy.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Pushy = require("./pushy"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Pushy = require("./pushy"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,145 @@ describe("notification default information", () => { expect(notification.name).toBe("pushy"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushy(); + let notificationConf = { + pushyAPIKey: "key", + pushyToken: "token" + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushy.me/push?api_key=key", { + "data": { + "message": "Uptime-Kuma", + }, + "notification": { + "badge": 1, + "body": "PassedInMessage😀", + "sound": "ping.aiff", + }, + "to": "token", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Pushy(); + let notificationConf = { + pushyAPIKey: "key", + pushyToken: "token" + }; + + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://api.pushy.me/push?api_key=key", { + "data": { + "message": "Uptime-Kuma", + }, + "notification": { + "badge": 1, + "body": "PassedInMessage😀", + "sound": "ping.aiff", + }, + "to": "token", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Pushy(); + let notificationConf = { + pushyAPIKey: "key", + pushyToken: "token" + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://api.pushy.me/push?api_key=key", { + "data": { + "message": "Uptime-Kuma", + }, + "notification": { + "badge": 1, + "body": "PassedInMessage😀", + "sound": "ping.aiff", + }, + "to": "token", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "pushy", + pushyAPIKey: "key", + pushyToken: "token" + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://api.pushy.me/push?api_key=key", { + "data": { + "message": "Uptime-Kuma", + }, + "notification": { + "badge": 1, + "body": "PassedInMessage😀", + "sound": "ping.aiff", + }, + "to": "token", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 8b0116b9f2d6fa9b349390cfaacc140c48bc57f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 20:47:22 -0500 Subject: [PATCH 21/29] rocket chat tests --- server/notification-providers/rocket-chat.js | 5 +- .../rocket-chat.spec.js | 215 +++++++++++++++++- 2 files changed, 211 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/rocket-chat.js b/server/notification-providers/rocket-chat.js index 25b0b945f7..28327b0703 100644 --- a/server/notification-providers/rocket-chat.js +++ b/server/notification-providers/rocket-chat.js @@ -9,7 +9,6 @@ class RocketChat extends NotificationProvider { name = "rocket.chat"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { let data = { @@ -19,7 +18,7 @@ class RocketChat extends NotificationProvider { "icon_emoji": notification.rocketiconemo, }; await axios.post(notification.rocketwebhookURL, data); - return okMsg; + return this.sendSuccess; } const time = heartbeatJSON["time"]; @@ -55,7 +54,7 @@ class RocketChat extends NotificationProvider { } await axios.post(notification.rocketwebhookURL, data); - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/rocket-chat.spec.js b/server/notification-providers/rocket-chat.spec.js index a34cc89647..a039571026 100644 --- a/server/notification-providers/rocket-chat.spec.js +++ b/server/notification-providers/rocket-chat.spec.js @@ -1,14 +1,19 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +jest.mock("../util-server"); -const RocketChat = require("./rocket-chat"); +const axios = require("axios"); +const { setting } = require("../util-server"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); + setting.mockReset(); }); +const RocketChat = require("./rocket-chat"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +21,201 @@ describe("notification default information", () => { expect(notification.name).toBe("rocket.chat"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when UP", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + setting.mockResolvedValueOnce("base.com"); + let notif = new RocketChat(); + let notificationConf = { + rocketchannel: "channel", + rocketusername: "user", + rocketiconemo: "😀", + rocketwebhookURL: "example.com", + }; + let monitorConf = { + id: "123" + }; + let heartbeatConf = { + status: UP, + time: "some time" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("example.com", { + "attachments": [ + { + "color": "#32cd32", + "text": "*Message*\nPassedInMessage😀", + "title": "Uptime Kuma Alert *Time (UTC)*\nsome time", + "title_link": "base.com/dashboard/123", + }, + ], + "channel": "channel", + "icon_emoji": "😀", + "text": "Uptime Kuma Alert", + "username": "user", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper default data when DOWN", async () => { + + let response = { + data: { + Message: "OK" + } + }; + setting.mockResolvedValueOnce("base.com"); + axios.post.mockResolvedValueOnce(response); + + let notif = new RocketChat(); + let notificationConf = { + rocketchannel: "channel", + rocketusername: "user", + rocketiconemo: "😀", + rocketwebhookURL: "example.com", + }; + let monitorConf = { + id: "123" + }; + let heartbeatConf = { + status: DOWN, + time: "some time" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("example.com", { + "attachments": [ + { + "color": "#ff0000", + "text": "*Message*\nPassedInMessage😀", + "title": "Uptime Kuma Alert *Time (UTC)*\nsome time", + "title_link": "base.com/dashboard/123", + }, + ], + "channel": "channel", + "icon_emoji": "😀", + "text": "Uptime Kuma Alert", + "username": "user", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + setting.mockResolvedValueOnce("base.com"); + axios.post.mockResolvedValueOnce(response); + + let notif = new RocketChat(); + let notificationConf = { + rocketchannel: "channel", + rocketusername: "user", + rocketiconemo: "😀", + rocketwebhookURL: "example.com", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("example.com", { + "channel": "channel", + "icon_emoji": "😀", + "text": "PassedInMessage😀", + "username": "user", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + setting.mockResolvedValueOnce("base.com"); + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new RocketChat(); + let notificationConf = { + rocketchannel: "channel", + rocketusername: "user", + rocketiconemo: "😀", + rocketwebhookURL: "example.com", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("example.com", { + "channel": "channel", + "icon_emoji": "😀", + "text": "PassedInMessage😀", + "username": "user", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + setting.mockResolvedValueOnce("base.com"); + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "rocket.chat", + rocketchannel: "channel", + rocketusername: "user", + rocketiconemo: "😀", + rocketwebhookURL: "example.com", + }; + let monitorConf = { + id: "123" + }; + let heartbeatConf = { + status: UP, + time: "some time" + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("example.com", { + "attachments": [ + { + "color": "#32cd32", + "text": "*Message*\nPassedInMessage😀", + "title": "Uptime Kuma Alert *Time (UTC)*\nsome time", + "title_link": "base.com/dashboard/123", + }, + ], + "channel": "channel", + "icon_emoji": "😀", + "text": "Uptime Kuma Alert", + "username": "user", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From fb67dc71cd1c263dc49b3d2d6e007483bf33265d Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 22:56:35 -0500 Subject: [PATCH 22/29] signal tests --- server/notification-providers/signal.js | 7 +- server/notification-providers/signal.spec.js | 171 ++++++++++++++++++- 2 files changed, 167 insertions(+), 11 deletions(-) diff --git a/server/notification-providers/signal.js b/server/notification-providers/signal.js index fee65754e7..eb58eb23a9 100644 --- a/server/notification-providers/signal.js +++ b/server/notification-providers/signal.js @@ -6,7 +6,6 @@ class Signal extends NotificationProvider { name = "signal"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { let data = { @@ -16,10 +15,10 @@ class Signal extends NotificationProvider { }; let config = {}; - await axios.post(notification.signalURL, data, config) - return okMsg; + await axios.post(notification.signalURL, data, config); + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } } diff --git a/server/notification-providers/signal.spec.js b/server/notification-providers/signal.spec.js index dc3403a2ad..6b8fd71025 100644 --- a/server/notification-providers/signal.spec.js +++ b/server/notification-providers/signal.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Signal = require("./signal"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Signal = require("./signal"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,159 @@ describe("notification default information", () => { expect(notification.name).toBe("signal"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Signal(); + let notificationConf = { + type: "signal", + signalNumber: "appriseURL", + signalRecipients: "asd asd, age, ge, wrh werh ,werh ,er h,as", + signalURL: "https://example.com/webhook", + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("https://example.com/webhook", { + "message": "PassedInMessage😀", + "number": "appriseURL", + "recipients": [ + "asdasd", + "age", + "ge", + "wrhwerh", + "werh", + "erh", + "as", + ], + }, {}); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Signal(); + let notificationConf = { + type: "signal", + signalNumber: "appriseURL", + signalRecipients: "asd asd, age, ge, wrh werh ,werh ,er h,as", + signalURL: "https://example.com/webhook", + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("https://example.com/webhook", { + "message": "PassedInMessage😀", + "number": "appriseURL", + "recipients": [ + "asdasd", + "age", + "ge", + "wrhwerh", + "werh", + "erh", + "as", + ], + }, {}); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Signal(); + let notificationConf = { + type: "signal", + signalNumber: "appriseURL", + signalRecipients: "asd asd, age, ge, wrh werh ,werh ,er h,as", + signalURL: "https://example.com/webhook", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("https://example.com/webhook", { + "message": "PassedInMessage😀", + "number": "appriseURL", + "recipients": [ + "asdasd", + "age", + "ge", + "wrhwerh", + "werh", + "erh", + "as", + ], + }, {}); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "signal", + signalNumber: "appriseURL", + signalRecipients: "asd asd, age, ge, wrh werh ,werh ,er h,as", + signalURL: "https://example.com/webhook", + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("https://example.com/webhook", { + "message": "PassedInMessage😀", + "number": "appriseURL", + "recipients": [ + "asdasd", + "age", + "ge", + "wrhwerh", + "werh", + "erh", + "as", + ], + }, {}); + expect(res).toBe("Sent Successfully."); + }); + +}); From 96740bc615253afc1123fcc1c845c0b7d332c8dd Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 23:08:52 -0500 Subject: [PATCH 23/29] slack tests --- server/notification-providers/slack.js | 5 +- server/notification-providers/slack.spec.js | 246 +++++++++++++++++++- 2 files changed, 242 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index b4dad6fe36..d7ef7215ed 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -25,7 +25,6 @@ class Slack extends NotificationProvider { } async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { let data = { @@ -35,7 +34,7 @@ class Slack extends NotificationProvider { "icon_emoji": notification.slackiconemo, }; await axios.post(notification.slackwebhookURL, data); - return okMsg; + return this.sendSuccess; } const time = heartbeatJSON["time"]; @@ -88,7 +87,7 @@ class Slack extends NotificationProvider { } await axios.post(notification.slackwebhookURL, data); - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/slack.spec.js b/server/notification-providers/slack.spec.js index f025654098..a36070478a 100644 --- a/server/notification-providers/slack.spec.js +++ b/server/notification-providers/slack.spec.js @@ -1,14 +1,19 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); +jest.mock("../util-server"); +const { setting } = require("../util-server"); -const Slack = require("./slack"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + setting.mockReset(); + axios.post.mockReset(); }); +const Slack = require("./slack"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +21,232 @@ describe("notification default information", () => { expect(notification.name).toBe("slack"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + setting.mockResolvedValueOnce("base.com"); + + let notif = new Slack(); + + let notificationConf = { + type: "slack", + slackchannel: "chan", + slackusername: "name", + slackiconemo: "😀", + slackwebhookURL: "www.slack.com/webhook" + }; + let monitorConf = { + name: "testing monitor", + id: "123", + }; + let heartbeatConf = { + time: "test time" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("www.slack.com/webhook", { + + "blocks": [ + { + "text": { + "text": "Uptime Kuma Alert", + "type": "plain_text", + }, + "type": "header", + }, + { + "fields": [ + { + "text": "*Message*\nPassedInMessage😀", + "type": "mrkdwn", + }, + { + "text": "*Time (UTC)*\ntest time", + "type": "mrkdwn", + }, + ], + "type": "section", + }, + { + "elements": [ + { + "text": { + "text": "Visit Uptime Kuma", + "type": "plain_text", + }, + "type": "button", + "url": "base.com/dashboard/123", + "value": "Uptime-Kuma", + }, + ], + "type": "actions", + }, + ], + "channel": "chan", + "icon_emoji": "😀", + "text": "Uptime Kuma Alert: testing monitor", + "username": "name", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + setting.mockResolvedValueOnce("base.com"); + + let notif = new Slack(); + + let notificationConf = { + type: "slack", + slackchannel: "chan", + slackusername: "name", + slackiconemo: "😀", + slackwebhookURL: "www.slack.com/webhook" + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("www.slack.com/webhook", { + + "channel": "chan", + "icon_emoji": "😀", + "text": "PassedInMessage😀", + "username": "name", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + setting.mockResolvedValueOnce("base.com"); + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Slack(); + + let notificationConf = { + type: "slack", + slackchannel: "chan", + slackusername: "name", + slackiconemo: "😀", + slackwebhookURL: "www.slack.com/webhook" + }; + let monitorConf = { + name: "testing monitor", + id: "123", + }; + let heartbeatConf = { + time: "test time" + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("www.slack.com/webhook", { + + "channel": "chan", + "icon_emoji": "😀", + "text": "PassedInMessage😀", + "username": "name", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + setting.mockResolvedValueOnce("base.com"); + + let notificationConf = { + type: "slack", + slackchannel: "chan", + slackusername: "name", + slackiconemo: "😀", + slackwebhookURL: "www.slack.com/webhook" + }; + let monitorConf = { + name: "testing monitor", + id: "123", + }; + let heartbeatConf = { + time: "test time" + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("www.slack.com/webhook", { + + "blocks": [ + { + "text": { + "text": "Uptime Kuma Alert", + "type": "plain_text", + }, + "type": "header", + }, + { + "fields": [ + { + "text": "*Message*\nPassedInMessage😀", + "type": "mrkdwn", + }, + { + "text": "*Time (UTC)*\ntest time", + "type": "mrkdwn", + }, + ], + "type": "section", + }, + { + "elements": [ + { + "text": { + "text": "Visit Uptime Kuma", + "type": "plain_text", + }, + "type": "button", + "url": "base.com/dashboard/123", + "value": "Uptime-Kuma", + }, + ], + "type": "actions", + }, + ], + "channel": "chan", + "icon_emoji": "😀", + "text": "Uptime Kuma Alert: testing monitor", + "username": "name", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 171069fc7ce4467b3a3ef08b3bc8298463e2f6df Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 23:19:49 -0500 Subject: [PATCH 24/29] teams tests --- server/notification-providers/teams.js | 5 +- server/notification-providers/teams.spec.js | 279 +++++++++++++++++++- 2 files changed, 274 insertions(+), 10 deletions(-) diff --git a/server/notification-providers/teams.js b/server/notification-providers/teams.js index 859af569c8..edaa60504e 100644 --- a/server/notification-providers/teams.js +++ b/server/notification-providers/teams.js @@ -87,12 +87,11 @@ class Teams extends NotificationProvider { }; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { await this._handleGeneralNotification(notification.webhookUrl, msg); - return okMsg; + return this.sendSuccess; } let url; @@ -114,7 +113,7 @@ class Teams extends NotificationProvider { }); await this._sendNotification(notification.webhookUrl, payload); - return okMsg; + return this.sendSuccess; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/teams.spec.js b/server/notification-providers/teams.spec.js index c5f804c212..2f39ec9e7f 100644 --- a/server/notification-providers/teams.spec.js +++ b/server/notification-providers/teams.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Teams = require("./teams"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Teams = require("./teams"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,267 @@ describe("notification default information", () => { expect(notification.name).toBe("teams"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data when up", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Teams(); + let notificationConf = { + webhookUrl: "teams.com/webhook" + }; + let monitorConf = { + type: "port", + hostname: "abc.com", + port: "1234", + url: "https://www.abc.com", + name: "name", + }; + let heartbeatConf = { + status: UP, + msg: "heart beating" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("teams.com/webhook", { + "@context": "https://schema.org/extensions", + "@type": "MessageCard", + "sections": [ + { + "activityImage": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "activityTitle": "**Uptime Kuma**", + }, + { + "activityTitle": "✅ Application [name] is back online", + }, + { + "activityTitle": "**Description**", + "facts": [ + { + "name": "Monitor", + "value": "name" + }, + { + "name": "URL", + "value": "abc.com:1234", + }, + ], + "text": "heart beating", + }, + ], + "summary": "✅ Application [name] is back online", + "themeColor": "00e804", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper default data when DOWN", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Teams(); + let notificationConf = { + webhookUrl: "teams.com/webhook" + }; + let monitorConf = { + type: "port", + hostname: "abc.com", + port: "1234", + url: "https://www.abc.com", + name: "name", + }; + let heartbeatConf = { + status: DOWN, + msg: "heart beating" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("teams.com/webhook", { + "@context": "https://schema.org/extensions", + "@type": "MessageCard", + "sections": [ + { + "activityImage": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "activityTitle": "**Uptime Kuma**", + }, + { + "activityTitle": "🔴 Application [name] went down", + }, + { + "activityTitle": "**Description**", + "facts": [ + { + "name": "Monitor", + "value": "name" + }, + { + "name": "URL", + "value": "abc.com:1234", + }, + ], + "text": "heart beating", + }, + ], + "summary": "🔴 Application [name] went down", + "themeColor": "ff0000", + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Teams(); + let notificationConf = { + webhookUrl: "teams.com/webhook" + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("teams.com/webhook", { + "@context": "https://schema.org/extensions", + "@type": "MessageCard", + "sections": [ + { + "activityImage": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "activityTitle": "**Uptime Kuma**", + }, + { + "activityTitle": "Notification", + }, + { + "activityTitle": "**Description**", + "facts": [ ], + "text": "PassedInMessage😀", + }, + ], + "summary": "Notification", + "themeColor": "008cff", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Teams(); + let notificationConf = { + webhookUrl: "teams.com/webhook" + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("teams.com/webhook", { + "@context": "https://schema.org/extensions", + "@type": "MessageCard", + "sections": [ + { + "activityImage": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "activityTitle": "**Uptime Kuma**", + }, + { + "activityTitle": "Notification", + }, + { + "activityTitle": "**Description**", + "facts": [ ], + "text": "PassedInMessage😀", + }, + ], + "summary": "Notification", + "themeColor": "008cff", + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "teams", + webhookUrl: "teams.com/webhook" + }; + let monitorConf = { + type: "port", + hostname: "abc.com", + port: "1234", + url: "https://www.abc.com", + name: "name", + }; + let heartbeatConf = { + status: DOWN, + msg: "heart beating" + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("teams.com/webhook", { + "@context": "https://schema.org/extensions", + "@type": "MessageCard", + "sections": [ + { + "activityImage": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "activityTitle": "**Uptime Kuma**", + }, + { + "activityTitle": "🔴 Application [name] went down", + }, + { + "activityTitle": "**Description**", + "facts": [ + { + "name": "Monitor", + "value": "name" + }, + { + "name": "URL", + "value": "abc.com:1234", + }, + ], + "text": "heart beating", + }, + ], + "summary": "🔴 Application [name] went down", + "themeColor": "ff0000", + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From 9ea0a9c82e7a3818f0a635bd1140da52d9769f2b Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 23:32:43 -0500 Subject: [PATCH 25/29] telegram tests --- server/notification-providers/telegram.js | 10 +- .../notification-providers/telegram.spec.js | 151 +++++++++++++++++- 2 files changed, 148 insertions(+), 13 deletions(-) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 54d33bfbda..4caef56812 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -6,7 +6,6 @@ class Telegram extends NotificationProvider { name = "telegram"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, { @@ -14,12 +13,11 @@ class Telegram extends NotificationProvider { chat_id: notification.telegramChatID, text: msg, }, - }) - return okMsg; - + }); + return this.sendSuccess; } catch (error) { - let msg = (error.response.data.description) ? error.response.data.description : "Error without description" - throw new Error(msg) + let msg = (error.response.data.description) ? error.response.data.description : "Error without description"; + throw new Error(msg); } } } diff --git a/server/notification-providers/telegram.spec.js b/server/notification-providers/telegram.spec.js index 285eef8c81..ef6e14dd94 100644 --- a/server/notification-providers/telegram.spec.js +++ b/server/notification-providers/telegram.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + get: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Telegram = require("./telegram"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.get.mockReset(); }); +const Telegram = require("./telegram"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,139 @@ describe("notification default information", () => { expect(notification.name).toBe("telegram"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.get.mockResolvedValueOnce(response); + + let notif = new Telegram(); + let notificationConf = { + type: "telegram", + telegramBotToken: "abc", + telegramChatID: "123", + + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.get).toHaveBeenCalledWith("https://api.telegram.org/botabc/sendMessage", { + "params": { + "chat_id": "123", + "text": "PassedInMessage😀", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.get.mockResolvedValueOnce(response); + + let notif = new Telegram(); + let notificationConf = { + type: "telegram", + telegramBotToken: "abc", + telegramChatID: "123", + + }; + + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.get).toHaveBeenCalledWith("https://api.telegram.org/botabc/sendMessage", { + "params": { + "chat_id": "123", + "text": "PassedInMessage😀", + }, + }); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.get.mockImplementation(() => { + throw { + response: { + data: { + description: "Error Description" + } + } + }; + }); + let notif = new Telegram(); + let notificationConf = { + type: "telegram", + telegramBotToken: "abc", + telegramChatID: "123", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error Description"); + } + + expect(axios.get).toHaveBeenCalledWith("https://api.telegram.org/botabc/sendMessage", { + "params": { + "chat_id": "123", + "text": "PassedInMessage😀", + }, + }); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.get.mockResolvedValueOnce(response); + let notificationConf = { + type: "telegram", + telegramBotToken: "abc", + telegramChatID: "123", + + }; + let monitorConf = { + }; + let heartbeatConf = { + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.get).toHaveBeenCalledWith("https://api.telegram.org/botabc/sendMessage", { + + "params": { + "chat_id": "123", + "text": "PassedInMessage😀", + }, + + }); + expect(res).toBe("Sent Successfully."); + }); + +}); From c86e80d1b9033638350ba17f3f6ae16d65f8884a Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 23:46:43 -0500 Subject: [PATCH 26/29] webhook tests --- server/notification-providers/webhook.js | 10 +- server/notification-providers/webhook.spec.js | 203 +++++++++++++++++- 2 files changed, 200 insertions(+), 13 deletions(-) diff --git a/server/notification-providers/webhook.js b/server/notification-providers/webhook.js index 9cb361f303..1f7e36818a 100644 --- a/server/notification-providers/webhook.js +++ b/server/notification-providers/webhook.js @@ -7,7 +7,6 @@ class Webhook extends NotificationProvider { name = "webhook"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; try { let data = { @@ -24,17 +23,16 @@ class Webhook extends NotificationProvider { config = { headers: finalData.getHeaders(), - } + }; } else { finalData = data; } - await axios.post(notification.webhookURL, finalData, config) - return okMsg; - + await axios.post(notification.webhookURL, finalData, config); + return this.sendSuccess; } catch (error) { - this.throwGeneralAxiosError(error) + this.throwGeneralAxiosError(error); } } diff --git a/server/notification-providers/webhook.spec.js b/server/notification-providers/webhook.spec.js index 7b2dfb7514..232c43642e 100644 --- a/server/notification-providers/webhook.spec.js +++ b/server/notification-providers/webhook.spec.js @@ -1,14 +1,15 @@ -// jest.mock("nodemailer", () => ({ -// createTransport: jest.fn(), -// })); +jest.mock("axios", () => ({ + post: jest.fn(), +})); -// const mockNodeMailer = require("nodemailer"); - -const Webhook = require("./webhook"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); +const NotificationSend = require("../notification"); beforeEach(() => { - // mockNodeMailer.createTransport.mockReset(); + axios.post.mockReset(); }); +const Webhook = require("./webhook"); describe("notification default information", () => { it("should have the correct name", () => { @@ -16,3 +17,191 @@ describe("notification default information", () => { expect(notification.name).toBe("webhook"); }); }); + +describe("notification to act properly on send", () => { + it("should call axios with the proper default data as not form-data", async () => { + + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Webhook(); + let notificationConf = { + type: "webhook", + webhookURL: "abc.com/webhook", + webhookContentType: "JSON" + }; + let monitorConf = { + type: "port", + hostname: "abc.com", + port: "1234", + url: "https://www.abc.com", + name: "name", + }; + let heartbeatConf = { + status: DOWN, + msg: "heart beating" + }; + let msg = "PassedInMessage😀"; + let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + expect(axios.post).toHaveBeenCalledWith("abc.com/webhook", { + "heartbeat": { + "msg": "heart beating", + "status": 0, + }, + "monitor": { + "hostname": "abc.com", + "name": "name", + "port": "1234", + "type": "port", + "url": "https://www.abc.com", + }, + "msg": "PassedInMessage😀", + }, {}); + expect(res).toBe("Sent Successfully."); + }); + + //TODO finish headers test. + // it("should call axios with the proper default data as form-data", async () => { + + // let response = { + // data: { + // Message: "OK" + // } + // }; + // axios.post.mockResolvedValueOnce(response); + + // let notif = new Webhook(); + // let notificationConf = { + // type: "webhook", + // webhookURL: "abc.com/webhook", + // webhookContentType: "form-data" + // }; + // let monitorConf = { + // type: "port", + // hostname: "abc.com", + // port: "1234", + // url: "https://www.abc.com", + // name: "name", + // }; + // let heartbeatConf = { + // status: DOWN, + // msg: "heart beating" + // }; + // let msg = "PassedInMessage😀"; + // let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); + + // expect(axios.post).toHaveBeenCalledWith("abc.com/webhook", {}, { + // "headers": { + // "content-type": "multipart/form-data; boundary=--------------------------219451039202311711580332", + // }, + // }); + // expect(res).toBe("Sent Successfully."); + // }); + + it("should call axios with the proper data when monitor nil", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + + let notif = new Webhook(); + let notificationConf = { + type: "webhook", + webhookURL: "abc.com/webhook" + }; + let msg = "PassedInMessage😀"; + + let res = await notif.send(notificationConf, msg, null, null); + + expect(axios.post).toHaveBeenCalledWith("abc.com/webhook", { + "heartbeat": null, + "monitor": null, + + "msg": "PassedInMessage😀", + }, {}); + expect(res).toBe("Sent Successfully."); + }); + +}); + +describe("notification to act properly on error", () => { + it("should respond with an axios error on error", async () => { + + axios.post.mockImplementation(() => { + throw new Error("Test Error"); + }); + let notif = new Webhook(); + let notificationConf = { + type: "webhook", + webhookURL: "abc.com/webhook" + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Error: Error: Test Error "); + } + + expect(axios.post).toHaveBeenCalledWith("abc.com/webhook", { + "heartbeat": null, + "monitor": null, + "msg": "PassedInMessage😀", + }, {}); + }); + +}); + +describe("notification to get proper data from Notification.send", () => { + it("should call axios with proper data", async () => { + let response = { + data: { + Message: "OK" + } + }; + axios.post.mockResolvedValueOnce(response); + let notificationConf = { + type: "webhook", + webhookURL: "abc.com/webhook" + }; + let monitorConf = { + type: "port", + hostname: "abc.com", + port: "1234", + url: "https://www.abc.com", + name: "name", + }; + let heartbeatConf = { + status: DOWN, + msg: "heart beating" + }; + let msg = "PassedInMessage😀"; + + NotificationSend.Notification.init(); + let res = await NotificationSend.Notification.send(notificationConf, msg, monitorConf, heartbeatConf); + expect(axios.post).toHaveBeenCalledWith("abc.com/webhook", { + "heartbeat": { + "msg": "heart beating", + "status": 0, + }, + "monitor": { + "hostname": "abc.com", + "name": "name", + "port": "1234", + "type": "port", + "url": "https://www.abc.com", + }, + "msg": "PassedInMessage😀", + }, {}); + expect(res).toBe("Sent Successfully."); + }); + +}); From 76eea7bdfdcb5387f29301203cfb4570f56fb11a Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Mon, 25 Oct 2021 23:49:27 -0500 Subject: [PATCH 27/29] NotificationProvider tests --- .../notification-provider.spec.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/server/notification-providers/notification-provider.spec.js b/server/notification-providers/notification-provider.spec.js index 56d929b055..1f6f0376a6 100644 --- a/server/notification-providers/notification-provider.spec.js +++ b/server/notification-providers/notification-provider.spec.js @@ -16,3 +16,25 @@ describe("notification default information", () => { expect(notification.name).toBe(undefined); }); }); + +describe("notification to error if blank notification called", () => { + it("should respond with an error if just called.", async () => { + + let notif = new NotificationProvider(); + let notificationConf = { + type: "telegram", + telegramBotToken: "abc", + telegramChatID: "123", + }; + let msg = "PassedInMessage😀"; + + try { + await notif.send(notificationConf, msg, null, null); + expect("Error thrown").toBe(false); + } catch (e) { + expect(e.message).toBe("Have to override Notification.send(...)"); + } + + }); + +}); From 782c943f937fec27e44558c43bd1a4e93dad2bbb Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Wed, 3 Nov 2021 01:12:19 -0500 Subject: [PATCH 28/29] fix #859 and update tests to match --- server/notification-providers/dingding.js | 2 +- server/notification-providers/dingding.spec.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index ea5a258bc3..db52b0a6e0 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -14,7 +14,7 @@ class DingDing extends NotificationProvider { msgtype: "markdown", markdown: { title: monitorJSON["name"], - text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`, + text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]}\n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`, } }; if (await this.sendToDingDing(notification, params)) { diff --git a/server/notification-providers/dingding.spec.js b/server/notification-providers/dingding.spec.js index 6868385921..b6307aca72 100644 --- a/server/notification-providers/dingding.spec.js +++ b/server/notification-providers/dingding.spec.js @@ -53,7 +53,7 @@ describe("notification to act properly on send", () => { let res = await notif.send(notificationConf, msg, monitorConf, heartbeatConf); expect(axios).toHaveBeenCalledWith({ - data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] testing\\n > some message \\n > Time(UTC):example time\"}}", headers: { "Content-Type": "application/json", }, @@ -146,7 +146,7 @@ describe("notification to act properly on error", () => { } expect(axios).toHaveBeenCalledWith({ - data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] testing\\n > some message \\n > Time(UTC):example time\"}}", headers: { "Content-Type": "application/json", }, @@ -194,7 +194,7 @@ describe("notification to get proper data from Notification.send", () => { expect(res).toBe("Sent Successfully."); expect(axios).toHaveBeenCalledWith({ - data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] \\n > some message \\n > Time(UTC):example time\"}}", + data: "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"testing\",\"text\":\"## [UP] testing\\n > some message \\n > Time(UTC):example time\"}}", headers: { "Content-Type": "application/json", }, From d7edafb81f7989b63218f76f2b14f3cf239da731 Mon Sep 17 00:00:00 2001 From: Jeffrey Koehler Date: Wed, 3 Nov 2021 01:27:33 -0500 Subject: [PATCH 29/29] Fix tests to account for addition of tls.rejectUnauthorized in SMTP --- server/notification-providers/smtp.spec.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/smtp.spec.js b/server/notification-providers/smtp.spec.js index d9165f7069..b3ffb428d0 100644 --- a/server/notification-providers/smtp.spec.js +++ b/server/notification-providers/smtp.spec.js @@ -54,6 +54,9 @@ describe("notification to act properly on send", () => { host: "host", port: "port", secure: "secure", + tls: { + "rejectUnauthorized": false, + } }); expect(res).toBe("Sent Successfully."); expect(sender).toHaveBeenCalledWith({ @@ -62,10 +65,9 @@ describe("notification to act properly on send", () => { from: "From", subject: "PassedInMessage", text: "PassedInMessage\nTime (UTC): undefined", - tls: { - rejectUnauthorized: false, - }, + to: "To", + }); }); @@ -111,6 +113,9 @@ describe("notification to act properly on send", () => { host: "host", port: "port", secure: "secure", + tls: { + "rejectUnauthorized": false, + } }); expect(res).toBe("Sent Successfully."); expect(sender).toHaveBeenCalledWith({ @@ -119,9 +124,6 @@ describe("notification to act properly on send", () => { from: "From", subject: "Name: testing | Status: ✅ Up | Hostname: https://www.google.com", text: "PassedInMessage\nTime (UTC): undefined", - tls: { - rejectUnauthorized: false, - }, to: "To", }); }); @@ -205,6 +207,7 @@ describe("notification to get proper data from Notification.send", () => { smtpCC: "CC", smtpBCC: "BCC", smtpTo: "To", + smtpIgnoreTLSError: true, }; let monitorConf = { type: "http", @@ -229,6 +232,9 @@ describe("notification to get proper data from Notification.send", () => { host: "host", port: "port", secure: "secure", + tls: { + "rejectUnauthorized": true, + } }); expect(sender).toHaveBeenCalledTimes(1); expect(sender).toHaveBeenCalledWith({ @@ -237,9 +243,6 @@ describe("notification to get proper data from Notification.send", () => { from: "From", subject: "simple message", text: "simple message\nTime (UTC): undefined", - tls: { - rejectUnauthorized: false, - }, to: "To", }); });