Skip to content

Commit 48adcb1

Browse files
ubeherasteipete
authored andcommitted
test(discord): cover deliver-lambda abort-skip path via processDiscordMessage integration
1 parent 3a48366 commit 48adcb1

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

extensions/discord/src/monitor/message-handler.process.test.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
type ChannelBotLoopProtectionFacts,
66
} from "openclaw/plugin-sdk/inbound-reply-dispatch";
77
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-dispatch-runtime";
8+
import * as runtimeEnvModule from "openclaw/plugin-sdk/runtime-env";
89
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
910
import type { DiscordMessagePreflightContext } from "./message-handler.preflight.js";
1011

@@ -211,6 +212,7 @@ let createDiscordDirectMessageContextOverrides: typeof import("./message-handler
211212
let threadBindingTesting: typeof import("./thread-bindings.js").testing;
212213
let createThreadBindingManager: typeof import("./thread-bindings.js").createThreadBindingManager;
213214
let processDiscordMessage: typeof import("./message-handler.process.js").processDiscordMessage;
215+
let formatDiscordReplySkip: typeof import("./message-handler.process.js").formatDiscordReplySkip;
214216
let notifyDiscordInboundEventOutboundSuccess: typeof import("../inbound-event-delivery.js").notifyDiscordInboundEventOutboundSuccess;
215217

216218
vi.mock("openclaw/plugin-sdk/reply-runtime", () => ({
@@ -373,7 +375,8 @@ beforeAll(async () => {
373375
await import("./message-handler.test-harness.js"));
374376
({ testing: threadBindingTesting, createThreadBindingManager } =
375377
await import("./thread-bindings.js"));
376-
({ processDiscordMessage } = await import("./message-handler.process.js"));
378+
({ processDiscordMessage, formatDiscordReplySkip } =
379+
await import("./message-handler.process.js"));
377380
({ notifyDiscordInboundEventOutboundSuccess } = await import("../inbound-event-delivery.js"));
378381
});
379382

@@ -2745,3 +2748,55 @@ describe("processDiscordMessage draft streaming", () => {
27452748
expect(draftStream.update).not.toHaveBeenCalled();
27462749
});
27472750
});
2751+
2752+
describe("processDiscordMessage deliver-lambda abort logging", () => {
2753+
it("emits logVerbose with formatDiscordReplySkip when deliver fires on a pre-aborted signal", async () => {
2754+
// Capture logVerbose calls via the ESM namespace binding. We rely on the
2755+
// same vi.spyOn pattern used in native-command.model-picker.test.ts so the
2756+
// production module keeps its real logVerbose import while the test still
2757+
// sees every invocation that the deliver lambda surfaces.
2758+
const verboseSpy = vi.spyOn(runtimeEnvModule, "logVerbose").mockImplementation(() => {});
2759+
2760+
const abortController = new AbortController();
2761+
// Drive the dispatcher so deliver actually runs: abort the signal inside
2762+
// the dispatch mock and then queue a single block reply via the captured
2763+
// dispatcher. The mocked createReplyDispatcherWithTyping (see line ~229)
2764+
// routes sendBlockReply straight into the deliver lambda, where the very
2765+
// first gate is `if (isProcessAborted(abortSignal)) return;` — the line
2766+
// the PR added the logVerbose call to.
2767+
dispatchInboundMessage.mockImplementationOnce(async (params?: DispatchInboundParams) => {
2768+
abortController.abort();
2769+
await params?.dispatcher.sendBlockReply({ text: "post-abort block payload" });
2770+
return { queuedFinal: false, counts: { final: 0, tool: 0, block: 1 } };
2771+
});
2772+
2773+
const ctx = await createAutomaticSourceDeliveryContext({
2774+
abortSignal: abortController.signal,
2775+
cfg: {
2776+
messages: {
2777+
ackReaction: "👀",
2778+
},
2779+
session: { store: "/tmp/openclaw-discord-process-test-sessions.json" },
2780+
},
2781+
});
2782+
2783+
await runProcessDiscordMessage(ctx);
2784+
2785+
// The base test harness routes through guild g1 / channel c1 (see
2786+
// createBaseDiscordMessageContext) so the deliver lambda receives the
2787+
// matching deliver target and session key from ctxPayload.SessionKey.
2788+
const dispatchedSessionKey = getLastDispatchCtx()?.SessionKey;
2789+
expect(dispatchedSessionKey).toBeTypeOf("string");
2790+
const expectedLog = formatDiscordReplySkip({
2791+
kind: "block",
2792+
reason: "aborted before delivery",
2793+
target: "channel:c1",
2794+
sessionKey: dispatchedSessionKey,
2795+
});
2796+
const verboseCalls = verboseSpy.mock.calls.map((call) => call[0]);
2797+
expect(verboseCalls).toContain(expectedLog);
2798+
// Restore so other tests sharing this worker (isolate=false) keep the
2799+
// real logVerbose binding.
2800+
verboseSpy.mockRestore();
2801+
});
2802+
});

0 commit comments

Comments
 (0)