|
1 | 1 | // Cron notification tests protect completion-delivery warning behavior, |
2 | 2 | // including URL redaction for invalid webhook destinations. |
3 | | -import { describe, expect, it, vi } from "vitest"; |
| 3 | +import { beforeEach, describe, expect, it, vi } from "vitest"; |
4 | 4 | import type { CliDeps } from "../cli/deps.types.js"; |
5 | 5 | import type { CronJob } from "../cron/types.js"; |
| 6 | + |
| 7 | +const mocks = vi.hoisted(() => ({ |
| 8 | +sendFailureNotificationAnnounce: vi.fn(), |
| 9 | +})); |
| 10 | + |
| 11 | +vi.mock("../cron/delivery.js", async (importOriginal) => { |
| 12 | +const actual = await importOriginal<typeof import("../cron/delivery.js")>(); |
| 13 | +return { |
| 14 | + ...actual, |
| 15 | +sendFailureNotificationAnnounce: mocks.sendFailureNotificationAnnounce, |
| 16 | +}; |
| 17 | +}); |
| 18 | + |
6 | 19 | import { dispatchGatewayCronFinishedNotifications } from "./server-cron-notifications.js"; |
7 | 20 | |
8 | 21 | describe("dispatchGatewayCronFinishedNotifications", () => { |
| 22 | +beforeEach(() => { |
| 23 | +vi.clearAllMocks(); |
| 24 | +}); |
| 25 | + |
9 | 26 | it("redacts invalid completion webhook targets in warnings", () => { |
10 | 27 | const logger = { |
11 | 28 | warn: vi.fn(), |
@@ -46,4 +63,56 @@ describe("dispatchGatewayCronFinishedNotifications", () => {
|
46 | 63 | "cron: skipped completion webhook delivery, delivery.completionDestination.to must be a valid http(s) URL", |
47 | 64 | ); |
48 | 65 | }); |
| 66 | + |
| 67 | +it("keeps configured failure destinations from inheriting the primary delivery thread", () => { |
| 68 | +const logger = { |
| 69 | +warn: vi.fn(), |
| 70 | +}; |
| 71 | +const job = { |
| 72 | +id: "cron-threaded-failure-dest", |
| 73 | +name: "threaded failure dest", |
| 74 | +enabled: true, |
| 75 | +createdAtMs: 1, |
| 76 | +updatedAtMs: 1, |
| 77 | +schedule: { kind: "every", everyMs: 60_000 }, |
| 78 | +sessionTarget: "isolated", |
| 79 | +sessionKey: "agent:main:telegram:group:-1001234567890:thread:42", |
| 80 | +wakeMode: "next-heartbeat", |
| 81 | +payload: { kind: "agentTurn", message: "hello" }, |
| 82 | +delivery: { |
| 83 | +mode: "announce", |
| 84 | +channel: "telegram", |
| 85 | +to: "-1001234567890", |
| 86 | +threadId: 42, |
| 87 | +failureDestination: { |
| 88 | +mode: "announce", |
| 89 | +channel: "telegram", |
| 90 | +to: "-1001234567890", |
| 91 | +}, |
| 92 | +}, |
| 93 | +state: {}, |
| 94 | +} satisfies CronJob; |
| 95 | + |
| 96 | +dispatchGatewayCronFinishedNotifications({ |
| 97 | +evt: { |
| 98 | +jobId: job.id, |
| 99 | +action: "finished", |
| 100 | +status: "error", |
| 101 | +error: "boom", |
| 102 | +}, |
| 103 | + job, |
| 104 | +deps: {} as CliDeps, |
| 105 | + logger, |
| 106 | +resolveCronAgent: () => ({ agentId: "main", cfg: {} }), |
| 107 | +}); |
| 108 | + |
| 109 | +expect(mocks.sendFailureNotificationAnnounce).toHaveBeenCalledTimes(1); |
| 110 | +expect(mocks.sendFailureNotificationAnnounce.mock.calls[0]?.[4]).toEqual({ |
| 111 | +channel: "telegram", |
| 112 | +to: "-1001234567890", |
| 113 | +accountId: undefined, |
| 114 | +sessionKey: "agent:main:telegram:group:-1001234567890:thread:42", |
| 115 | +inheritSessionThread: false, |
| 116 | +}); |
| 117 | +}); |
49 | 118 | }); |