From 3a8cfdf652d0bc6305075389cc55c557f81befca Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 9 May 2026 07:39:33 +0100 Subject: [PATCH] test: mock durable channel send seam --- src/channels/turn/kernel.test.ts | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/channels/turn/kernel.test.ts b/src/channels/turn/kernel.test.ts index dfcee7641b3..67bc4af93ba 100644 --- a/src/channels/turn/kernel.test.ts +++ b/src/channels/turn/kernel.test.ts @@ -16,6 +16,7 @@ import { const deliverOutboundPayloads = vi.hoisted(() => vi.fn()); const resolveOutboundDurableFinalDeliverySupport = vi.hoisted(() => vi.fn()); +const sendDurableMessageBatch = vi.hoisted(() => vi.fn()); vi.mock("../../infra/outbound/deliver.js", async (importOriginal) => { const actual = await importOriginal(); @@ -26,6 +27,14 @@ vi.mock("../../infra/outbound/deliver.js", async (importOriginal) => { }; }); +vi.mock("../message/send.js", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + sendDurableMessageBatch, + }; +}); + const cfg = {} as OpenClawConfig; function createCtx(overrides: Partial = {}): FinalizedMsgContext { @@ -62,6 +71,18 @@ function createDispatch( }) as DispatchReplyWithBufferedBlockDispatcher; } +function createDurableSendResult(messageIds: string[]) { + return { + status: "sent", + results: messageIds.map((messageId) => ({ messageId })), + receipt: { + platformMessageIds: messageIds, + parts: [], + sentAt: 1, + }, + }; +} + describe("channel turn kernel", () => { beforeEach(() => { vi.clearAllMocks(); @@ -69,7 +90,7 @@ describe("channel turn kernel", () => { }); it("routes assembled final replies through durable outbound delivery", async () => { - deliverOutboundPayloads.mockResolvedValueOnce([{ messageId: "tg-1" }]); + sendDurableMessageBatch.mockResolvedValueOnce(createDurableSendResult(["tg-1"])); const deliver = vi.fn(); const recordInboundSession = createRecordInboundSession(); const dispatchReplyWithBufferedBlockDispatcher = createDispatch(); @@ -96,13 +117,13 @@ describe("channel turn kernel", () => { expect(result.dispatched).toBe(true); expect(deliver).not.toHaveBeenCalled(); - expect(deliverOutboundPayloads).toHaveBeenCalledWith( + expect(sendDurableMessageBatch).toHaveBeenCalledWith( expect.objectContaining({ channel: "telegram", to: "123", accountId: "acct", payloads: [expect.objectContaining({ text: "reply" })], - queuePolicy: "best_effort", + durability: "best_effort", replyToMode: "first", threadId: 777, session: expect.objectContaining({ @@ -127,7 +148,7 @@ describe("channel turn kernel", () => { }); it("returns durable delivery result to the buffered dispatcher", async () => { - deliverOutboundPayloads.mockResolvedValueOnce([{ messageId: "tg-1" }, { messageId: "tg-2" }]); + sendDurableMessageBatch.mockResolvedValueOnce(createDurableSendResult(["tg-1", "tg-2"])); let deliveredResult: unknown; const dispatchReplyWithBufferedBlockDispatcher = vi.fn( async (params: Parameters[0]) => { @@ -167,7 +188,7 @@ describe("channel turn kernel", () => { }); it("prepares payloads before durable enqueue and observes handled delivery", async () => { - deliverOutboundPayloads.mockResolvedValueOnce([{ messageId: "tlon-1" }]); + sendDurableMessageBatch.mockResolvedValueOnce(createDurableSendResult(["tlon-1"])); const onDelivered = vi.fn(); const dispatchReplyWithBufferedBlockDispatcher = createDispatch(); @@ -195,7 +216,7 @@ describe("channel turn kernel", () => { }, }); - expect(deliverOutboundPayloads).toHaveBeenCalledWith( + expect(sendDurableMessageBatch).toHaveBeenCalledWith( expect.objectContaining({ payloads: [expect.objectContaining({ text: "reply\n\n_[Generated by test]_" })], }),