

























@@ -0,0 +1,175 @@
1+import type { WebClient } from "@slack/web-api";
2+import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
3+import { describe, expect, it, vi } from "vitest";
4+import { sendMessageSlack } from "./send.js";
5+6+type SlackUnfurlTestClient = WebClient & {
7+chat: { postMessage: ReturnType<typeof vi.fn> };
8+conversations: { open: ReturnType<typeof vi.fn> };
9+};
10+11+function createSlackSendTestClient(): SlackUnfurlTestClient {
12+return {
13+conversations: {
14+open: vi.fn(async () => ({ channel: { id: "D123" } })),
15+},
16+chat: {
17+postMessage: vi.fn(async () => ({ ts: "171234.567" })),
18+},
19+} as unknown as SlackUnfurlTestClient;
20+}
21+22+function slackConfig(slack: NonNullable<OpenClawConfig["channels"]>["slack"]): OpenClawConfig {
23+return { channels: { slack } };
24+}
25+26+function missingCustomizeScopeError(): Error {
27+return Object.assign(new Error("An API error occurred: missing_scope"), {
28+data: {
29+error: "missing_scope",
30+needed: "chat:write.customize",
31+},
32+});
33+}
34+35+describe("sendMessageSlack unfurl controls", () => {
36+it("omits Slack unfurl flags when config is unset", async () => {
37+const client = createSlackSendTestClient();
38+39+await sendMessageSlack("channel:C123", "https://example.com", {
40+token: "xoxb-test",
41+cfg: slackConfig({ botToken: "xoxb-test" }),
42+ client,
43+});
44+45+expect(client.chat.postMessage).toHaveBeenCalledWith(
46+expect.not.objectContaining({
47+unfurl_links: expect.any(Boolean),
48+unfurl_media: expect.any(Boolean),
49+}),
50+);
51+});
52+53+it("passes top-level Slack unfurl flags to chat.postMessage", async () => {
54+const client = createSlackSendTestClient();
55+56+await sendMessageSlack("channel:C123", "https://example.com", {
57+token: "xoxb-test",
58+cfg: slackConfig({
59+botToken: "xoxb-test",
60+unfurlLinks: false,
61+unfurlMedia: false,
62+}),
63+ client,
64+});
65+66+expect(client.chat.postMessage).toHaveBeenCalledWith(
67+expect.objectContaining({
68+unfurl_links: false,
69+unfurl_media: false,
70+}),
71+);
72+});
73+74+it("lets account-level Slack unfurl flags override top-level defaults", async () => {
75+const client = createSlackSendTestClient();
76+77+await sendMessageSlack("channel:C123", "https://example.com", {
78+token: "xoxb-test",
79+accountId: "work",
80+cfg: slackConfig({
81+botToken: "xoxb-root",
82+unfurlLinks: false,
83+unfurlMedia: true,
84+accounts: {
85+work: {
86+unfurlLinks: true,
87+unfurlMedia: false,
88+},
89+},
90+}),
91+ client,
92+});
93+94+expect(client.chat.postMessage).toHaveBeenCalledWith(
95+expect.objectContaining({
96+unfurl_links: true,
97+unfurl_media: false,
98+}),
99+);
100+});
101+102+it("applies Slack unfurl flags to block messages", async () => {
103+const client = createSlackSendTestClient();
104+105+await sendMessageSlack("channel:C123", "https://example.com", {
106+token: "xoxb-test",
107+cfg: slackConfig({
108+botToken: "xoxb-test",
109+unfurlLinks: false,
110+unfurlMedia: false,
111+}),
112+ client,
113+blocks: [{ type: "divider" }],
114+});
115+116+expect(client.chat.postMessage).toHaveBeenCalledWith(
117+expect.objectContaining({
118+blocks: [{ type: "divider" }],
119+unfurl_links: false,
120+unfurl_media: false,
121+}),
122+);
123+});
124+125+it("preserves Slack unfurl flags when custom identity falls back", async () => {
126+const client = createSlackSendTestClient();
127+client.chat.postMessage
128+.mockRejectedValueOnce(missingCustomizeScopeError())
129+.mockResolvedValueOnce({ ts: "171234.567" });
130+131+await sendMessageSlack("channel:C123", "https://example.com", {
132+token: "xoxb-test",
133+cfg: slackConfig({
134+botToken: "xoxb-test",
135+unfurlLinks: false,
136+unfurlMedia: false,
137+}),
138+ client,
139+identity: {
140+username: "OpenClaw",
141+},
142+});
143+144+expect(client.chat.postMessage).toHaveBeenLastCalledWith(
145+expect.objectContaining({
146+unfurl_links: false,
147+unfurl_media: false,
148+}),
149+);
150+});
151+152+it("applies Slack unfurl flags to every text chunk", async () => {
153+const client = createSlackSendTestClient();
154+155+await sendMessageSlack("channel:C123", "a".repeat(8500), {
156+token: "xoxb-test",
157+cfg: slackConfig({
158+botToken: "xoxb-test",
159+unfurlLinks: false,
160+unfurlMedia: false,
161+}),
162+ client,
163+});
164+165+expect(client.chat.postMessage).toHaveBeenCalledTimes(2);
166+for (const [payload] of client.chat.postMessage.mock.calls) {
167+expect(payload).toEqual(
168+expect.objectContaining({
169+unfurl_links: false,
170+unfurl_media: false,
171+}),
172+);
173+}
174+});
175+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。