

















@@ -10,6 +10,29 @@ const { sendMessageSlack } = await import("./send.js");
1010const SLACK_TEST_CFG = { channels: { slack: { botToken: "xoxb-test" } } };
1111const SLACK_TEXT_LIMIT = 8000;
121213+type MockCallSource = { mock: { calls: Array<Array<unknown>> } };
14+15+function mockObjectArg(
16+source: MockCallSource,
17+label: string,
18+callIndex = 0,
19+argIndex = 0,
20+): Record<string, unknown> {
21+const call = source.mock.calls[callIndex];
22+if (!call) {
23+throw new Error(`Expected ${label} call ${callIndex} to exist`);
24+}
25+const value = call[argIndex];
26+if (!value || typeof value !== "object") {
27+throw new Error(`Expected ${label} call ${callIndex} argument ${argIndex} to be an object`);
28+}
29+return value as Record<string, unknown>;
30+}
31+32+function postedMessage(client: ReturnType<typeof createSlackSendTestClient>, callIndex = 0) {
33+return mockObjectArg(client.chat.postMessage, "chat.postMessage", callIndex);
34+}
35+1336function slackDnsRequestError(): Error {
1437return Object.assign(new Error("A request error occurred: getaddrinfo EAI_AGAIN slack.com"), {
1538code: "slack_webapi_request_error",
@@ -127,12 +150,8 @@ describe("sendMessageSlack chunking", () => {
127150});
128151129152expect(client.chat.postMessage).toHaveBeenCalledTimes(1);
130-expect(client.chat.postMessage).toHaveBeenCalledWith(
131-expect.objectContaining({
132-channel: "C123",
133-text: message,
134-}),
135-);
153+expect(postedMessage(client).channel).toBe("C123");
154+expect(postedMessage(client).text).toBe(message);
136155});
137156138157it("splits oversized fallback text through the normal Slack sender", async () => {
@@ -168,25 +187,19 @@ describe("sendMessageSlack blocks", () => {
168187});
169188170189expect(client.conversations.open).not.toHaveBeenCalled();
171-expect(client.chat.postMessage).toHaveBeenCalledWith(
172-expect.objectContaining({
173-channel: "C123",
174-text: "Shared a Block Kit message",
175-blocks: [{ type: "divider" }],
176-}),
177-);
178-expect(result).toMatchObject({ messageId: "171234.567", channelId: "C123" });
179-expect(result.receipt).toMatchObject({
180-primaryPlatformMessageId: "171234.567",
181-platformMessageIds: ["171234.567"],
182-parts: [
183-expect.objectContaining({
184-platformMessageId: "171234.567",
185-kind: "card",
186-raw: expect.objectContaining({ channel: "slack", channelId: "C123" }),
187-}),
188-],
189-});
190+const post = postedMessage(client);
191+expect(post.channel).toBe("C123");
192+expect(post.text).toBe("Shared a Block Kit message");
193+expect(post.blocks).toEqual([{ type: "divider" }]);
194+expect(result.messageId).toBe("171234.567");
195+expect(result.channelId).toBe("C123");
196+expect(result.receipt.primaryPlatformMessageId).toBe("171234.567");
197+expect(result.receipt.platformMessageIds).toEqual(["171234.567"]);
198+const receiptPart = result.receipt.parts[0];
199+expect(receiptPart?.platformMessageId).toBe("171234.567");
200+expect(receiptPart?.kind).toBe("card");
201+expect((receiptPart?.raw as Record<string, unknown> | undefined)?.channel).toBe("slack");
202+expect((receiptPart?.raw as Record<string, unknown> | undefined)?.channelId).toBe("C123");
190203});
191204192205it("posts user-target block messages directly without conversations.open", async () => {
@@ -201,13 +214,10 @@ describe("sendMessageSlack blocks", () => {
201214});
202215203216expect(client.conversations.open).not.toHaveBeenCalled();
204-expect(client.chat.postMessage).toHaveBeenCalledWith(
205-expect.objectContaining({
206-channel: "U123",
207-text: "Shared a Block Kit message",
208-}),
209-);
210-expect(result).toMatchObject({ messageId: "171234.567", channelId: "U123" });
217+expect(postedMessage(client).channel).toBe("U123");
218+expect(postedMessage(client).text).toBe("Shared a Block Kit message");
219+expect(result.messageId).toBe("171234.567");
220+expect(result.channelId).toBe("U123");
211221expect(result.receipt.platformMessageIds).toEqual(["171234.567"]);
212222});
213223@@ -224,13 +234,10 @@ describe("sendMessageSlack blocks", () => {
224234});
225235226236expect(client.chat.postMessage).toHaveBeenCalledTimes(2);
227-expect(result).toMatchObject({ messageId: "171234.999", channelId: "C123" });
228-expect(result.receipt.parts[0]).toEqual(
229-expect.objectContaining({
230-platformMessageId: "171234.999",
231-kind: "text",
232-}),
233-);
237+expect(result.messageId).toBe("171234.999");
238+expect(result.channelId).toBe("C123");
239+expect(result.receipt.parts[0]?.platformMessageId).toBe("171234.999");
240+expect(result.receipt.parts[0]?.kind).toBe("text");
234241});
235242236243it("retries Slack conversations.open DNS request errors for threaded DMs", async () => {
@@ -247,10 +254,10 @@ describe("sendMessageSlack blocks", () => {
247254});
248255249256expect(client.conversations.open).toHaveBeenCalledTimes(2);
250-expect(client.chat.postMessage).toHaveBeenCalledWith(
251- expect.objectContaining({ channel: "D123", thread_ts: "171234.100" }),
252-);
253-expect(result).toMatchObject({ messageId: "171234.567", channelId: "D123" });
257+expect(postedMessage(client).channel).toBe("D123");
258+expect(postedMessage(client).thread_ts).toBe("171234.100");
259+expect(result.messageId).toBe("171234.567");
260+expect(result.channelId).toBe("D123");
254261expect(result.receipt.threadId).toBe("171234.100");
255262});
256263@@ -266,13 +273,9 @@ describe("sendMessageSlack blocks", () => {
266273});
267274268275expect(client.chat.postMessage).toHaveBeenCalledTimes(2);
269-expect(client.chat.postMessage.mock.calls[0]?.[0]).toEqual(
270-expect.objectContaining({
271-thread_ts: "171234.100",
272-reply_broadcast: true,
273-}),
274-);
275-expect(client.chat.postMessage.mock.calls[1]?.[0]).not.toHaveProperty("reply_broadcast");
276+expect(postedMessage(client).thread_ts).toBe("171234.100");
277+expect(postedMessage(client).reply_broadcast).toBe(true);
278+expect(postedMessage(client, 1)).not.toHaveProperty("reply_broadcast");
276279});
277280278281it("does not pass reply_broadcast when no thread is selected", async () => {
@@ -285,11 +288,7 @@ describe("sendMessageSlack blocks", () => {
285288replyBroadcast: true,
286289});
287290288-expect(client.chat.postMessage).toHaveBeenCalledWith(
289-expect.not.objectContaining({
290-reply_broadcast: true,
291-}),
292-);
291+expect(postedMessage(client)).not.toHaveProperty("reply_broadcast");
293292});
294293295294it("does not retry Slack platform errors", async () => {
@@ -322,11 +321,7 @@ describe("sendMessageSlack blocks", () => {
322321blocks: [{ type: "image", image_url: "https://example.com/a.png", alt_text: "Build chart" }],
323322});
324323325-expect(client.chat.postMessage).toHaveBeenCalledWith(
326-expect.objectContaining({
327-text: "Build chart",
328-}),
329-);
324+expect(postedMessage(client).text).toBe("Build chart");
330325});
331326332327it("derives fallback text from video blocks", async () => {
@@ -346,11 +341,7 @@ describe("sendMessageSlack blocks", () => {
346341],
347342});
348343349-expect(client.chat.postMessage).toHaveBeenCalledWith(
350-expect.objectContaining({
351-text: "Release demo",
352-}),
353-);
344+expect(postedMessage(client).text).toBe("Release demo");
354345});
355346356347it("derives fallback text from file blocks", async () => {
@@ -362,11 +353,7 @@ describe("sendMessageSlack blocks", () => {
362353blocks: [{ type: "file", source: "remote", external_id: "F123" }],
363354});
364355365-expect(client.chat.postMessage).toHaveBeenCalledWith(
366-expect.objectContaining({
367-text: "Shared a file",
368-}),
369-);
356+expect(postedMessage(client).text).toBe("Shared a file");
370357});
371358372359it("caps long fallback text while preserving blocks", async () => {
@@ -390,13 +377,10 @@ describe("sendMessageSlack blocks", () => {
390377 blocks,
391378});
392379393-expect(client.chat.postMessage).toHaveBeenCalledWith(
394-expect.objectContaining({
395-text: expect.stringMatching(/…$/),
396- blocks,
397-}),
398-);
399-expect(client.chat.postMessage.mock.calls[0]?.[0].text).toHaveLength(SLACK_TEXT_LIMIT);
380+const post = postedMessage(client);
381+expect(String(post.text).endsWith("…")).toBe(true);
382+expect(post.blocks).toBe(blocks);
383+expect(post.text).toHaveLength(SLACK_TEXT_LIMIT);
400384});
401385402386it("rejects blocks combined with mediaUrl", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。