Files
Checkmate/server/test/unit/providers/notifications/rocketChatProvider.test.ts
T

166 lines
5.4 KiB
TypeScript

import { describe, expect, it, jest } from "@jest/globals";
import type { NotificationSeverity } from "../../../../src/domain/notifications/notification.type.ts";
import { createMockLogger } from "../../../helpers/createMockLogger.ts";
import { makeMessage, makeNotification } from "../../../helpers/notificationMessage.ts";
import { testNotificationProviderContract } from "../../../helpers/notificationProviderContract.ts";
const mockGotPost = jest.fn().mockResolvedValue({});
jest.unstable_mockModule("got", () => ({ default: { post: mockGotPost } }));
const { RocketChatProvider } = await import("../../../../src/domain/notifications/providers/rocketChat.ts");
const createProvider = () => {
const logger = createMockLogger();
const provider = new RocketChatProvider(logger as any);
return { provider, logger };
};
testNotificationProviderContract("RocketChatProvider", {
create: () => {
mockGotPost.mockResolvedValue({});
return createProvider().provider;
},
makeNotification: () => makeNotification({ type: "rocket_chat" }),
});
describe("RocketChatProvider", () => {
beforeEach(() => mockGotPost.mockReset().mockResolvedValue({}));
it("sends a rich test alert without webhook overrides", async () => {
const { provider } = createProvider();
const result = await provider.sendTestAlert(makeNotification({ type: "rocket_chat" }));
expect(result).toBe(true);
expect(mockGotPost).toHaveBeenCalledWith(
"https://hooks.example.com/webhook",
expect.objectContaining({
json: {
text: "This is a test notification from Checkmate",
attachments: [
{
color: "#0000FF",
title: "Checkmate test notification",
fields: [
{ title: "Channel", value: "Rocket.Chat", short: true },
{ title: "Status", value: "Test notification", short: true },
],
},
],
},
timeout: { request: 30000 },
retry: { limit: 0 },
})
);
const payload = mockGotPost.mock.calls[0][1].json;
expect(payload).not.toHaveProperty("alias");
expect(payload).not.toHaveProperty("avatar");
expect(payload).not.toHaveProperty("emoji");
expect(payload).not.toHaveProperty("channel");
});
it("returns false when the test webhook URL is missing", async () => {
const { provider } = createProvider();
const result = await provider.sendTestAlert(makeNotification({ type: "rocket_chat", address: "" }));
expect(result).toBe(false);
expect(mockGotPost).not.toHaveBeenCalled();
});
it("returns false and logs when test delivery fails", async () => {
mockGotPost.mockRejectedValue(new Error("network failure"));
const { provider, logger } = createProvider();
const result = await provider.sendTestAlert(makeNotification({ type: "rocket_chat" }));
expect(result).toBe(false);
expect(logger.warn).toHaveBeenCalledWith(
expect.objectContaining({
message: "Rocket.Chat test alert failed",
service: "RocketChatProvider",
method: "sendTestAlert",
})
);
});
it("sends a rich monitor attachment without webhook overrides", async () => {
const { provider } = createProvider();
const result = await provider.sendMessage(makeNotification({ type: "rocket_chat" }), makeMessage());
expect(result).toBe(true);
expect(mockGotPost).toHaveBeenCalledWith(
"https://hooks.example.com/webhook",
expect.objectContaining({
timeout: { request: 30000 },
retry: { limit: 0 },
json: {
text: 'Monitor "Test Monitor" is currently down.',
attachments: [
{
color: "#FF0000",
title: "Monitor Down: Test Monitor",
title_link: "https://app.example.com/infrastructure/mon-1",
fields: [
{ title: "Monitor", value: "Test Monitor", short: true },
{ title: "Type", value: "http", short: true },
{ title: "Status", value: "down", short: true },
{ title: "URL", value: "https://example.com", short: false },
],
ts: "2025-01-01T00:00:00.000Z",
},
],
},
})
);
const payload = mockGotPost.mock.calls[0][1].json;
expect(payload).not.toHaveProperty("alias");
expect(payload).not.toHaveProperty("avatar");
expect(payload).not.toHaveProperty("emoji");
expect(payload).not.toHaveProperty("channel");
});
it.each([
["critical", "#FF0000"],
["warning", "#FFA500"],
["success", "#00FF00"],
["info", "#0000FF"],
["unknown", "#808080"],
])("maps %s severity to %s", async (severity, color) => {
const { provider } = createProvider();
await provider.sendMessage(makeNotification({ type: "rocket_chat" }), makeMessage({ severity: severity as NotificationSeverity }));
const payload = mockGotPost.mock.calls[0][1].json;
expect(payload.attachments[0].color).toBe(color);
});
it("returns false when the message webhook URL is missing", async () => {
const { provider } = createProvider();
const result = await provider.sendMessage(makeNotification({ type: "rocket_chat", address: "" }), makeMessage());
expect(result).toBe(false);
expect(mockGotPost).not.toHaveBeenCalled();
});
it("returns false and logs when message delivery fails", async () => {
mockGotPost.mockRejectedValue(new Error("network failure"));
const { provider, logger } = createProvider();
const result = await provider.sendMessage(makeNotification({ type: "rocket_chat" }), makeMessage());
expect(result).toBe(false);
expect(logger.warn).toHaveBeenCalledWith(
expect.objectContaining({
message: "Rocket.Chat notification failed",
service: "RocketChatProvider",
method: "sendMessage",
})
);
});
});