





















@@ -21,6 +21,22 @@ function defaultActionOptions() {
2121};
2222}
232324+function expectDiscordActionCall(params: {
25+payload: unknown;
26+cfg: OpenClawConfig;
27+options?: unknown;
28+}) {
29+expect(handleDiscordActionMock).toHaveBeenCalledTimes(1);
30+const [payload, cfg, options] = handleDiscordActionMock.mock.calls[0] ?? [];
31+expect(payload).toEqual(params.payload);
32+expect(cfg).toBe(params.cfg);
33+if ("options" in params) {
34+expect(options).toEqual(params.options);
35+} else {
36+expect(options).toBeUndefined();
37+}
38+}
39+2440describe("handleDiscordMessageAction", () => {
2541beforeEach(() => {
2642handleDiscordActionMock.mockClear();
@@ -41,16 +57,20 @@ describe("handleDiscordMessageAction", () => {
4157toolContext: { currentChannelProvider: "discord" },
4258});
435944-expect(handleDiscordActionMock).toHaveBeenCalledWith(
45-expect.objectContaining({
60+expectDiscordActionCall({
61+payload: {
4662action: "timeout",
63+accountId: undefined,
4764guildId: "guild-1",
4865userId: "user-2",
4966durationMinutes: 5,
67+until: undefined,
68+reason: undefined,
69+deleteMessageDays: undefined,
5070senderUserId: "trusted-sender-id",
51-}),
71+},
5272 cfg,
53-);
73+});
5474});
55755676it("falls back to toolContext.currentMessageId for reactions", async () => {
@@ -65,16 +85,18 @@ describe("handleDiscordMessageAction", () => {
6585toolContext: { currentMessageId: "9001" },
6686});
678768-expect(handleDiscordActionMock).toHaveBeenCalledWith(
69-expect.objectContaining({
88+expectDiscordActionCall({
89+payload: {
7090action: "react",
91+accountId: undefined,
7192channelId: "123",
7293messageId: "9001",
7394emoji: "ok",
74-}),
95+remove: undefined,
96+},
7597 cfg,
76-defaultActionOptions(),
77-);
98+options: defaultActionOptions(),
99+});
78100});
7910180102it("falls back to Discord toolContext.currentChannelId for reaction targets", async () => {
@@ -92,16 +114,18 @@ describe("handleDiscordMessageAction", () => {
92114},
93115});
9411695-expect(handleDiscordActionMock).toHaveBeenCalledWith(
96-expect.objectContaining({
117+expectDiscordActionCall({
118+payload: {
97119action: "react",
120+accountId: undefined,
98121channelId: "user:U1",
99122messageId: "9001",
100123emoji: "ok",
101-}),
124+remove: undefined,
125+},
102126 cfg,
103-defaultActionOptions(),
104-);
127+options: defaultActionOptions(),
128+});
105129});
106130107131it("falls back to Discord toolContext.currentChannelId for sends", async () => {
@@ -118,15 +142,25 @@ describe("handleDiscordMessageAction", () => {
118142},
119143});
120144121-expect(handleDiscordActionMock).toHaveBeenCalledWith(
122-expect.objectContaining({
145+expectDiscordActionCall({
146+payload: {
123147action: "sendMessage",
148+accountId: undefined,
124149to: "channel:123",
125150content: "hello",
126-}),
151+mediaUrl: undefined,
152+filename: undefined,
153+replyTo: undefined,
154+components: undefined,
155+embeds: undefined,
156+asVoice: false,
157+silent: false,
158+__sessionKey: undefined,
159+__agentId: undefined,
160+},
127161 cfg,
128-defaultActionOptions(),
129-);
162+options: defaultActionOptions(),
163+});
130164});
131165132166it("maps upload-file to Discord sendMessage with media read context", async () => {
@@ -155,9 +189,10 @@ describe("handleDiscordMessageAction", () => {
155189 mediaReadFile,
156190});
157191158-expect(handleDiscordActionMock).toHaveBeenCalledWith(
159-expect.objectContaining({
192+expectDiscordActionCall({
193+payload: {
160194action: "sendMessage",
195+accountId: undefined,
161196to: "channel:123",
162197content: "caption",
163198mediaUrl: "/tmp/agent-root/image.png",
@@ -166,14 +201,14 @@ describe("handleDiscordMessageAction", () => {
166201silent: true,
167202__sessionKey: "session-1",
168203__agentId: "agent-1",
169-}),
204+},
170205 cfg,
171-{
206+options: {
172207 mediaAccess,
173208mediaLocalRoots: ["/tmp/agent-root"],
174209 mediaReadFile,
175210},
176-);
211+});
177212});
178213179214it("falls back to Discord toolContext.currentChannelId for upload-file", async () => {
@@ -190,16 +225,22 @@ describe("handleDiscordMessageAction", () => {
190225},
191226});
192227193-expect(handleDiscordActionMock).toHaveBeenCalledWith(
194-expect.objectContaining({
228+expectDiscordActionCall({
229+payload: {
195230action: "sendMessage",
231+accountId: undefined,
196232to: "channel:123",
197233content: "",
198234mediaUrl: "/tmp/agent-root/image.png",
199-}),
235+filename: undefined,
236+replyTo: undefined,
237+silent: false,
238+__sessionKey: undefined,
239+__agentId: undefined,
240+},
200241 cfg,
201-defaultActionOptions(),
202-);
242+options: defaultActionOptions(),
243+});
203244});
204245205246it("requires a file path for upload-file", async () => {
@@ -232,20 +273,21 @@ describe("handleDiscordMessageAction", () => {
232273 mediaReadFile,
233274});
234275235-expect(handleDiscordActionMock).toHaveBeenCalledWith(
236-expect.objectContaining({
276+expectDiscordActionCall({
277+payload: {
237278action: "threadReply",
279+accountId: undefined,
238280channelId: "thread-123",
239281content: "thread update",
240282mediaUrl: "/tmp/agent-root/report.md",
241-}),
283+replyTo: undefined,
284+},
242285 cfg,
243-{
286+options: {
244287mediaLocalRoots: ["/tmp/agent-root"],
245-mediaAccess: undefined,
246288 mediaReadFile,
247289},
248-);
290+});
249291});
250292251293it("forwards top-level components on sends", async () => {
@@ -265,16 +307,25 @@ describe("handleDiscordMessageAction", () => {
265307},
266308});
267309268-expect(handleDiscordActionMock).toHaveBeenCalledWith(
269-expect.objectContaining({
310+expectDiscordActionCall({
311+payload: {
270312action: "sendMessage",
313+accountId: undefined,
271314to: "channel:123",
272315content: "hello",
316+mediaUrl: undefined,
317+filename: undefined,
318+replyTo: undefined,
273319 components,
274-}),
320+embeds: undefined,
321+asVoice: false,
322+silent: false,
323+__sessionKey: undefined,
324+__agentId: undefined,
325+},
275326 cfg,
276-defaultActionOptions(),
277-);
327+options: defaultActionOptions(),
328+});
278329});
279330280331it("does not use another provider's current target for Discord sends", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。