133 lines
5.5 KiB
TypeScript
133 lines
5.5 KiB
TypeScript
import { describe, expect, it, jest, beforeEach } from "@jest/globals";
|
|
import { createMockLogger } from "../../../helpers/createMockLogger.ts";
|
|
import { makeNotification, makeMessage, makeMessageWithThresholds } from "../../../helpers/notificationMessage.ts";
|
|
import { testNotificationProviderContract } from "../../../helpers/notificationProviderContract.ts";
|
|
|
|
const mockGotPost = jest.fn().mockResolvedValue({});
|
|
jest.unstable_mockModule("got", () => ({ default: { post: mockGotPost } }));
|
|
|
|
const { PagerDutyProvider } = await import("../../../../src/domain/notifications/providers/pagerduty.ts");
|
|
|
|
const createProvider = () => {
|
|
const logger = createMockLogger();
|
|
return { provider: new PagerDutyProvider(logger as any), logger };
|
|
};
|
|
|
|
testNotificationProviderContract("PagerDutyProvider", {
|
|
create: () => {
|
|
mockGotPost.mockResolvedValue({});
|
|
return createProvider().provider;
|
|
},
|
|
makeNotification: () => makeNotification(),
|
|
});
|
|
|
|
describe("PagerDutyProvider", () => {
|
|
beforeEach(() => mockGotPost.mockReset().mockResolvedValue({}));
|
|
|
|
describe("sendTestAlert", () => {
|
|
it("sends to PagerDuty API and returns true", async () => {
|
|
expect(await createProvider().provider.sendTestAlert(makeNotification())).toBe(true);
|
|
expect(mockGotPost).toHaveBeenCalledWith(
|
|
"https://events.pagerduty.com/v2/enqueue",
|
|
expect.objectContaining({
|
|
json: expect.objectContaining({ routing_key: "https://hooks.example.com/webhook", event_action: "trigger" }),
|
|
})
|
|
);
|
|
});
|
|
|
|
it("returns false and logs on error", async () => {
|
|
mockGotPost.mockRejectedValue(new Error("fail"));
|
|
const { provider, logger } = createProvider();
|
|
expect(await provider.sendTestAlert(makeNotification())).toBe(false);
|
|
expect(logger.warn).toHaveBeenCalled();
|
|
});
|
|
|
|
it("handles non-Error thrown values", async () => {
|
|
mockGotPost.mockRejectedValue(null);
|
|
const { provider } = createProvider();
|
|
expect(await provider.sendTestAlert(makeNotification())).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("sendMessage", () => {
|
|
it("sends payload and returns true", async () => {
|
|
const { provider } = createProvider();
|
|
expect(await provider.sendMessage(makeNotification() as any, makeMessage())).toBe(true);
|
|
const payload = mockGotPost.mock.calls[0][1].json;
|
|
expect(payload.routing_key).toBe("https://hooks.example.com/webhook");
|
|
expect(payload.event_action).toBe("trigger");
|
|
expect(payload.dedup_key).toBe("checkmate-mon-1");
|
|
});
|
|
|
|
it("returns false when address is missing", async () => {
|
|
const { provider } = createProvider();
|
|
expect(await provider.sendMessage(makeNotification({ address: "" }) as any, makeMessage())).toBe(false);
|
|
});
|
|
|
|
it("returns false and logs on error", async () => {
|
|
mockGotPost.mockRejectedValue(new Error("fail"));
|
|
const { provider, logger } = createProvider();
|
|
expect(await provider.sendMessage(makeNotification() as any, makeMessage())).toBe(false);
|
|
expect(logger.warn).toHaveBeenCalled();
|
|
});
|
|
|
|
it("handles non-Error thrown values in sendMessage", async () => {
|
|
mockGotPost.mockRejectedValue(null);
|
|
const { provider } = createProvider();
|
|
expect(await provider.sendMessage(makeNotification() as any, makeMessage())).toBe(false);
|
|
});
|
|
|
|
it("uses 'resolve' event_action for monitor_up", async () => {
|
|
const { provider } = createProvider();
|
|
await provider.sendMessage(makeNotification() as any, makeMessage({ type: "monitor_up" }));
|
|
expect(mockGotPost.mock.calls[0][1].json.event_action).toBe("resolve");
|
|
});
|
|
|
|
it("uses 'resolve' event_action for threshold_resolved", async () => {
|
|
const { provider } = createProvider();
|
|
await provider.sendMessage(makeNotification() as any, makeMessage({ type: "threshold_resolved" }));
|
|
expect(mockGotPost.mock.calls[0][1].json.event_action).toBe("resolve");
|
|
});
|
|
|
|
it("includes threshold info in summary and custom_details", async () => {
|
|
const { provider } = createProvider();
|
|
await provider.sendMessage(makeNotification() as any, makeMessageWithThresholds());
|
|
const payload = mockGotPost.mock.calls[0][1].json;
|
|
expect(payload.payload.summary).toContain("CPU");
|
|
expect(payload.payload.custom_details.threshold_breaches).toBeDefined();
|
|
});
|
|
|
|
it("includes details in custom_details", async () => {
|
|
const { provider } = createProvider();
|
|
await provider.sendMessage(makeNotification() as any, makeMessage());
|
|
expect(mockGotPost.mock.calls[0][1].json.payload.custom_details.details).toBeDefined();
|
|
});
|
|
|
|
it("maps all severity levels", async () => {
|
|
const { provider } = createProvider();
|
|
for (const severity of ["critical", "warning", "info", "success"] as const) {
|
|
mockGotPost.mockClear();
|
|
await provider.sendMessage(makeNotification() as any, makeMessage({ severity }));
|
|
expect(mockGotPost.mock.calls[0][1].json.payload.severity).toBeTruthy();
|
|
}
|
|
});
|
|
|
|
it("uses 'error' for unknown severity", async () => {
|
|
const { provider } = createProvider();
|
|
await provider.sendMessage(makeNotification() as any, makeMessage({ severity: "unknown" as any }));
|
|
expect(mockGotPost.mock.calls[0][1].json.payload.severity).toBe("error");
|
|
});
|
|
|
|
it("omits threshold and details from custom_details when not present", async () => {
|
|
const { provider } = createProvider();
|
|
const msg = makeMessage();
|
|
msg.content.thresholds = undefined;
|
|
msg.content.details = undefined;
|
|
await provider.sendMessage(makeNotification() as any, msg);
|
|
const cd = mockGotPost.mock.calls[0][1].json.payload.custom_details;
|
|
expect(cd.threshold_breaches).toBeUndefined();
|
|
expect(cd.details).toBeUndefined();
|
|
});
|
|
});
|
|
});
|