Notification tests #760

Open
deefdragon wants to merge 30 commits from deefdragon/notif-tests into master
  1. 2
      config/jest-backend.config.js
  2. 12
      server/notification-providers/aliyun-sms.js
  3. 243
      server/notification-providers/aliyun-sms.spec.js
  4. 8
      server/notification-providers/apprise.js
  5. 112
      server/notification-providers/apprise.spec.js
  6. 11
      server/notification-providers/dingding.js
  7. 208
      server/notification-providers/dingding.spec.js
  8. 23
      server/notification-providers/discord.js
  9. 260
      server/notification-providers/discord.spec.js
  10. 7
      server/notification-providers/feishu.js
  11. 174
      server/notification-providers/feishu.spec.js
  12. 5
      server/notification-providers/gotify.js
  13. 152
      server/notification-providers/gotify.spec.js
  14. 21
      server/notification-providers/line.js
  15. 232
      server/notification-providers/line.spec.js
  16. 23
      server/notification-providers/lunasea.js
  17. 176
      server/notification-providers/lunasea.spec.js
  18. 3
      server/notification-providers/matrix.js
  19. 171
      server/notification-providers/matrix.spec.js
  20. 15
      server/notification-providers/mattermost.js
  21. 297
      server/notification-providers/mattermost.spec.js
  22. 6
      server/notification-providers/notification-provider.js
  23. 40
      server/notification-providers/notification-provider.spec.js
  24. 7
      server/notification-providers/octopush.js
  25. 245
      server/notification-providers/octopush.spec.js
  26. 7
      server/notification-providers/promosms.js
  27. 193
      server/notification-providers/promosms.spec.js
  28. 17
      server/notification-providers/pushbullet.js
  29. 201
      server/notification-providers/pushbullet.spec.js
  30. 17
      server/notification-providers/pushover.js
  31. 177
      server/notification-providers/pushover.spec.js
  32. 7
      server/notification-providers/pushy.js
  33. 161
      server/notification-providers/pushy.spec.js
  34. 5
      server/notification-providers/rocket-chat.js
  35. 221
      server/notification-providers/rocket-chat.spec.js
  36. 7
      server/notification-providers/signal.js
  37. 175
      server/notification-providers/signal.spec.js
  38. 5
      server/notification-providers/slack.js
  39. 252
      server/notification-providers/slack.spec.js
  40. 2
      server/notification-providers/smtp.js
  41. 250
      server/notification-providers/smtp.spec.js
  42. 5
      server/notification-providers/teams.js
  43. 283
      server/notification-providers/teams.spec.js
  44. 10
      server/notification-providers/telegram.js
  45. 155
      server/notification-providers/telegram.spec.js
  46. 10
      server/notification-providers/webhook.js
  47. 207
      server/notification-providers/webhook.spec.js

2
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"],
};

12
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",
};

243
server/notification-providers/aliyun-sms.spec.js

@ -0,0 +1,243 @@
jest.mock("axios");
const axios = require("axios");
const { UP } = require("../../src/util");
const NotificationSend = require("../notification");
const AliyunSMS = require("./aliyun-sms");
beforeEach(() => {
axios.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new AliyunSMS();
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.");
});
});

8
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";
}

112
server/notification-providers/apprise.spec.js

@ -0,0 +1,112 @@
jest.mock("child_process", () => ({
spawnSync: jest.fn(),
}));
const childProcess = require("child_process");
const { UP } = require("../../src/util");
const NotificationSend = require("../notification");
const Apprise = require("./apprise");
beforeEach(() => {
childProcess.spawnSync.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Apprise();
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.");
});
});

11
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) {
@ -15,11 +14,11 @@ 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 (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) {

208
server/notification-providers/dingding.spec.js

@ -0,0 +1,208 @@
jest.mock("axios");
const { UP } = require("../../src/util");
const NotificationSend = require("../notification");
const DingDing = require("./dingding");
const axios = require("axios");
beforeEach(() => {
axios.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new DingDing();
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] testing\\n > some message \\n > Time(UTC):example time\"}}",
headers: {
"Content-Type": "application/json",
},
method: "POST",
url: "https://example.com/webhook&timestamp=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&timestamp=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] testing\\n > some message \\n > Time(UTC):example time\"}}",
headers: {
"Content-Type": "application/json",
},
method: "POST",
url: "https://example.com/webhook&timestamp=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] testing\\n > some message \\n > Time(UTC):example time\"}}",
headers: {
"Content-Type": "application/json",
},
method: "POST",
url: "https://example.com/webhook&timestamp=1557831718135&sign=lCTIn3sYpAYFAw3B2LeTLr7BvcOMAcmZu%2F6rb7kC8Io%3D",
});
expect(res).toBe("Sent Successfully.");
});
});

23
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);
}
}

260
server/notification-providers/discord.spec.js

@ -0,0 +1,260 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Discord = require("./discord");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Discord();
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.");
});
});

7
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);

174
server/notification-providers/feishu.spec.js

@ -0,0 +1,174 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Feishu = require("./feishu");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Feishu();
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.");
});
});

5
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);

152
server/notification-providers/gotify.spec.js

@ -0,0 +1,152 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Gotify = require("./gotify");
beforeEach(() => {
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.");
});
});

21
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);
}
}
}

232
server/notification-providers/line.spec.js

@ -0,0 +1,232 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Line = require("./line");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Line();
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.");
});
});

23
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);
}
}

176
server/notification-providers/lunasea.spec.js

@ -0,0 +1,176 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const LunaSea = require("./lunasea");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new LunaSea();
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.");
});
});

3
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);
}

171
server/notification-providers/matrix.spec.js

@ -0,0 +1,171 @@
jest.mock("axios", () => ({
put: jest.fn(),
}));
jest.mock("crypto", () => ({
randomBytes: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Matrix = require("./matrix");
const Crypto = require("crypto");
beforeEach(() => {
axios.put.mockReset();
Crypto.randomBytes.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Matrix();
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(Buffer.from("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(Buffer.from("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(Buffer.from("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(Buffer.from("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.");
});
});

15
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);

297
server/notification-providers/mattermost.spec.js

@ -0,0 +1,297 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Mattermost = require("./mattermost");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Mattermost();
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.");
});
});

6
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);
}
}

40
server/notification-providers/notification-provider.spec.js

@ -0,0 +1,40 @@
// 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);
});
});
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(...)");
}
});
});

7
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);
}

245
server/notification-providers/octopush.spec.js

@ -0,0 +1,245 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
const Octopush = require("./octopush");
beforeEach(() => {
axios.post.mockReset();
});
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Octopush();
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.");
});
});

7
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);
}

193
server/notification-providers/promosms.spec.js

@ -0,0 +1,193 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const PromoSMS = require("./promosms");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new PromoSMS();
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.");
});
});

17
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);
}
}
}

201
server/notification-providers/pushbullet.spec.js

@ -0,0 +1,201 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Pushbullet = require("./pushbullet");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Pushbullet();
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.");
});
});

17
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);
}
}

177
server/notification-providers/pushover.spec.js

@ -0,0 +1,177 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Pushover = require("./pushover");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Pushover();
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("https://api.pushover.net/1/messages.json", {
"expire": "3600",
"html": 1,
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:PassedInMessage😀\n<b>Time (UTC)</b>: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": "<b>Uptime Kuma Pushover testing successful.</b>",
"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": "<b>Uptime Kuma Pushover testing successful.</b>",
"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": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:PassedInMessage😀\n<b>Time (UTC)</b>:example time",
"priority": "6",
"retry": "30",
"sound": "ding",
"title": "Important Title!",
"token": "token",
"user": "123",
});
expect(res).toBe("Sent Successfully.");
});
});

7
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);
}
}
}

161
server/notification-providers/pushy.spec.js

@ -0,0 +1,161 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Pushy = require("./pushy");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Pushy();
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.");
});
});

5
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);
}

221
server/notification-providers/rocket-chat.spec.js

@ -0,0 +1,221 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
jest.mock("../util-server");
const axios = require("axios");
const { setting } = require("../util-server");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
setting.mockReset();
});
const RocketChat = require("./rocket-chat");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new RocketChat();
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.");
});
});

7
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);
}
}
}

175
server/notification-providers/signal.spec.js

@ -0,0 +1,175 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Signal = require("./signal");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Signal();
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.");
});
});

5
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);
}

252
server/notification-providers/slack.spec.js

@ -0,0 +1,252 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
jest.mock("../util-server");
const { setting } = require("../util-server");
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
setting.mockReset();
axios.post.mockReset();
});
const Slack = require("./slack");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Slack();
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.");
});
});

2
server/notification-providers/smtp.js

@ -92,7 +92,7 @@ class SMTP extends NotificationProvider {
text: bodyTextContent,
});
return "Sent Successfully.";
return this.sendSuccess;
}
}

250
server/notification-providers/smtp.spec.js

@ -0,0 +1,250 @@
jest.mock("nodemailer", () => ({
createTransport: jest.fn(),
}));
const mockNodeMailer = require("nodemailer");
const { UP } = require("../../src/util");
const NotificationSend = require("../notification");
const SMTP = require("./smtp");
beforeEach(() => {
mockNodeMailer.createTransport.mockReset();
});
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: "",
smtpFrom: "From",
smtpCC: "CC",
smtpBCC: "BCC",
smtpTo: "To",
};
let msg = "PassedInMessage";
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",
tls: {
"rejectUnauthorized": false,
}
});
expect(res).toBe("Sent Successfully.");
expect(sender).toHaveBeenCalledWith({
bcc: "BCC",
cc: "CC",
from: "From",
subject: "PassedInMessage",
text: "PassedInMessage\nTime (UTC): 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",
tls: {
"rejectUnauthorized": false,
}
});
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",
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);
});
});
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",
smtpIgnoreTLSError: true,
};
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",
tls: {
"rejectUnauthorized": true,
}
});
expect(sender).toHaveBeenCalledTimes(1);
expect(sender).toHaveBeenCalledWith({
bcc: "BCC",
cc: "CC",
from: "From",
subject: "simple message",
text: "simple message\nTime (UTC): undefined",
to: "To",
});
});
});

5
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);
}

283
server/notification-providers/teams.spec.js

@ -0,0 +1,283 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Teams = require("./teams");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Teams();
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.");
});
});

10
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);
}
}
}

155
server/notification-providers/telegram.spec.js

@ -0,0 +1,155 @@
jest.mock("axios", () => ({
get: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.get.mockReset();
});
const Telegram = require("./telegram");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Telegram();
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.");
});
});

10
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);
}
}

207
server/notification-providers/webhook.spec.js

@ -0,0 +1,207 @@
jest.mock("axios", () => ({
post: jest.fn(),
}));
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
const NotificationSend = require("../notification");
beforeEach(() => {
axios.post.mockReset();
});
const Webhook = require("./webhook");
describe("notification default information", () => {
it("should have the correct name", () => {
let notification = new Webhook();
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.");
});
});
Loading…
Cancel
Save