You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.9 KiB

import { afterEach, describe, expect, it, vi } from "vitest";
import {
emitAlert,
getEmittedAlerts,
resetAlertState,
} from "@/services/alert/webhook";
import { enableTestModeEnv, disableTestModeEnv } from "@/services/test/test-mode-env";
describe("alert webhook", () => {
afterEach(() => {
resetAlertState();
delete process.env.ALERT_WEBHOOK_URL;
disableTestModeEnv();
vi.unstubAllGlobals();
});
it("records in memory when webhook url empty", async () => {
enableTestModeEnv();
const sent = await emitAlert({
key: "imap.consecutive_fail",
title: "IMAP 连续拉取失败",
severity: "error",
fields: { consecutiveFail: 3 },
});
expect(sent).toBe(true);
expect(getEmittedAlerts()).toHaveLength(1);
expect(getEmittedAlerts()[0].title).toMatch(/IMAP/);
});
it("dedups same key within window", async () => {
enableTestModeEnv();
await emitAlert({ key: "cc.auth_expired", title: "a", severity: "error" });
const second = await emitAlert({
key: "cc.auth_expired",
title: "b",
severity: "error",
});
expect(second).toBe(false);
expect(getEmittedAlerts()).toHaveLength(1);
});
it("POSTs JSON when ALERT_WEBHOOK_URL is set", async () => {
enableTestModeEnv();
process.env.ALERT_WEBHOOK_URL = "https://example.test/hook";
const { resetEnvCache } = await import("@/lib/env");
resetEnvCache();
const fetchMock = vi.fn().mockResolvedValue({ ok: true });
vi.stubGlobal("fetch", fetchMock);
resetAlertState();
await emitAlert({
key: "cc.login_fail",
title: "CC 登录失败",
severity: "error",
fields: { code: 401 },
});
expect(fetchMock).toHaveBeenCalledTimes(1);
const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
expect(url).toBe("https://example.test/hook");
expect(init.method).toBe("POST");
delete process.env.ALERT_WEBHOOK_URL;
resetEnvCache();
});
});