From 0c184e6d0c614b239ae86dd2c2fcb28bdde73ba6 Mon Sep 17 00:00:00 2001 From: Marcos Paulo Diniz Date: Wed, 5 Aug 2026 08:33:29 -0300 Subject: [PATCH] fix(notifications): guard incident link Refs #3821 --- .../notifications/providers/rocketChat.ts | 4 +++- .../notifications/rocketChatProvider.test.ts | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/server/src/domain/notifications/providers/rocketChat.ts b/server/src/domain/notifications/providers/rocketChat.ts index aa6852d74..345eec8c3 100644 --- a/server/src/domain/notifications/providers/rocketChat.ts +++ b/server/src/domain/notifications/providers/rocketChat.ts @@ -81,7 +81,9 @@ export class RocketChatProvider extends NotificationProvider { ); } - lines.push("", `Incident: ${message.clientHost}/infrastructure/${message.monitor.id}`); + if (message.content.incident) { + lines.push("", `Incident: ${message.clientHost}/infrastructure/${message.monitor.id}`); + } return lines.join("\n"); } diff --git a/server/test/unit/providers/notifications/rocketChatProvider.test.ts b/server/test/unit/providers/notifications/rocketChatProvider.test.ts index 8ceb60bee..ac9ffc4c1 100644 --- a/server/test/unit/providers/notifications/rocketChatProvider.test.ts +++ b/server/test/unit/providers/notifications/rocketChatProvider.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, jest } from "@jest/globals"; import { createMockLogger } from "../../../helpers/createMockLogger.ts"; -import { makeMessage, makeMessageWithThresholds, makeNotification } from "../../../helpers/notificationMessage.ts"; +import { makeMessage, makeMessageWithIncident, makeMessageWithThresholds, makeNotification } from "../../../helpers/notificationMessage.ts"; import { testNotificationProviderContract } from "../../../helpers/notificationProviderContract.ts"; const mockGotPost = jest.fn().mockResolvedValue({}); @@ -90,8 +90,6 @@ describe("RocketChatProvider", () => { "Details:", "- URL: https://example.com", "- Status: Down", - "", - "Incident: https://app.example.com/infrastructure/mon-1", ].join("\n"), }, }) @@ -116,15 +114,31 @@ describe("RocketChatProvider", () => { expect(payload.text).toContain("Thresholds:\n- CPU: 90.0% (threshold: 80%)\n- MEMORY: 85.0% (threshold: 70%)"); }); - it("includes a monitor-scoped incident link without synthetic incident data", async () => { + it("includes a monitor-scoped link when incident data is present", async () => { const { provider } = createProvider(); - await provider.sendMessage(makeNotification({ type: "rocket_chat" }), makeMessage()); + await provider.sendMessage(makeNotification({ type: "rocket_chat" }), makeMessageWithIncident()); const payload = mockGotPost.mock.calls[0][1].json; expect(payload.text).toContain("Incident: https://app.example.com/infrastructure/mon-1"); }); + it("omits the incident link when incident data is absent", async () => { + const { provider } = createProvider(); + + await provider.sendMessage( + makeNotification({ type: "rocket_chat" }), + makeMessage({ + type: "monitor_up", + severity: "success", + monitor: { id: "mon-1", name: "Test Monitor", url: "https://example.com", type: "http", status: "up" }, + }) + ); + + const payload = mockGotPost.mock.calls[0][1].json; + expect(payload.text).not.toContain("Incident:"); + }); + it("returns false and logs when message delivery fails", async () => { mockGotPost.mockRejectedValue(new Error("network failure")); const { provider, logger } = createProvider();