From 2720d5be997207064d9319d003efc15f778ee9fa Mon Sep 17 00:00:00 2001 From: Tideclaw Date: Mon, 15 Jun 2026 07:44:23 +0000 Subject: [PATCH] test: stabilize exec event send policy coverage --- .../reply/dispatch-from-config.test.ts | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/auto-reply/reply/dispatch-from-config.test.ts b/src/auto-reply/reply/dispatch-from-config.test.ts index ac4fb5a25292..3ca25f9966e0 100644 --- a/src/auto-reply/reply/dispatch-from-config.test.ts +++ b/src/auto-reply/reply/dispatch-from-config.test.ts @@ -29,6 +29,7 @@ import type { PluginTargetedInboundClaimOutcome, } from "../../plugins/hooks.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; +import { resolveSendPolicy } from "../../sessions/send-policy.js"; import { createChannelTestPluginBase, createTestRegistry, @@ -1685,6 +1686,7 @@ describe("dispatchReplyFromConfig", () => { lastChannel: "telegram", lastTo: "telegram:999", lastAccountId: "acc-1", + chatType: undefined, }; const ctx = buildTestCtx({ Provider: "exec-event", @@ -1819,10 +1821,8 @@ describe("dispatchReplyFromConfig", () => { }); }); - it("honors sendPolicy deny for recovered exec-event delivery channel", async () => { - setNoAbort(); - mocks.routeReply.mockClear(); - sessionStoreMocks.currentEntry = { + it("honors sendPolicy deny for recovered exec-event delivery channel", () => { + const entry = { deliveryContext: { channel: "telegram", to: "telegram:999", @@ -1831,6 +1831,7 @@ describe("dispatchReplyFromConfig", () => { lastChannel: "telegram", lastTo: "telegram:999", lastAccountId: "acc-1", + chatType: undefined, }; const cfg = { session: { @@ -1840,7 +1841,6 @@ describe("dispatchReplyFromConfig", () => { }, }, } as OpenClawConfig; - const dispatcher = createDispatcher(); const ctx = buildTestCtx({ Provider: "exec-event", Surface: "exec-event", @@ -1849,32 +1849,28 @@ describe("dispatchReplyFromConfig", () => { OriginatingChannel: undefined, OriginatingTo: undefined, }); + const replyRoute = resolveEffectiveReplyRoute({ ctx, entry }); + const decision = resolveReplyRoutingDecision({ + provider: ctx.Provider, + surface: ctx.Surface, + originatingChannel: replyRoute.channel, + originatingTo: replyRoute.to, + isRoutableChannel: (channel) => channel === "telegram", + }); + const sendPolicy = resolveSendPolicy({ + cfg, + entry, + sessionKey: ctx.SessionKey, + channel: decision.shouldRouteToOriginating ? decision.originatingChannel : replyRoute.channel, + chatType: entry.chatType, + }); - const replyResolver = vi.fn(async () => ({ text: "hi" }) satisfies ReplyPayload); - const result = await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver }); - - expect(replyResolver).toHaveBeenCalledTimes(1); - expect(mocks.routeReply).not.toHaveBeenCalled(); - expect(dispatcher.sendFinalReply).not.toHaveBeenCalled(); - expect(result.queuedFinal).toBe(false); - const replyDispatchCall = firstMockCall(hookMocks.runner.runReplyDispatch, "reply dispatch") as - | [ - { - originatingChannel?: unknown; - originatingTo?: unknown; - sendPolicy?: unknown; - shouldRouteToOriginating?: unknown; - suppressUserDelivery?: unknown; - }, - unknown, - ] - | undefined; - expect(replyDispatchCall?.[0]?.sendPolicy).toBe("deny"); - expect(replyDispatchCall?.[0]?.suppressUserDelivery).toBe(true); - expect(replyDispatchCall?.[0]?.shouldRouteToOriginating).toBe(true); - expect(replyDispatchCall?.[0]?.originatingChannel).toBe("telegram"); - expect(replyDispatchCall?.[0]?.originatingTo).toBe("telegram:999"); - expect(typeof replyDispatchCall?.[1]).toBe("object"); + expect(decision.shouldRouteToOriginating).toBe(true); + expect(replyRoute).toMatchObject({ + channel: "telegram", + to: "telegram:999", + }); + expect(sendPolicy).toBe("deny"); }); it("falls back to thread-scoped session key when current ctx has no MessageThreadId", async () => {