From 023091ded3563f9cbcffc1ee0a2788e4129f8be6 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 15 Feb 2026 20:46:36 +0000 Subject: [PATCH] perf(test): consolidate slack tool-result suites --- ...es-thread-replies-replytoid-is-set.test.ts | 153 ------- ...ix.test.ts => monitor.tool-result.test.ts} | 382 +++++++++++++++++- ...p-level-replies-replytomode-is-all.test.ts | 272 ------------- 3 files changed, 381 insertions(+), 426 deletions(-) delete mode 100644 src/slack/monitor.tool-result.forces-thread-replies-replytoid-is-set.test.ts rename src/slack/{monitor.tool-result.sends-tool-summaries-responseprefix.test.ts => monitor.tool-result.test.ts} (52%) delete mode 100644 src/slack/monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts diff --git a/src/slack/monitor.tool-result.forces-thread-replies-replytoid-is-set.test.ts b/src/slack/monitor.tool-result.forces-thread-replies-replytoid-is-set.test.ts deleted file mode 100644 index 4743cd85188..00000000000 --- a/src/slack/monitor.tool-result.forces-thread-replies-replytoid-is-set.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js"; -import { - defaultSlackTestConfig, - getSlackClient, - getSlackHandlerOrThrow, - getSlackTestState, - resetSlackTestState, - runSlackMessageOnce, - startSlackMonitor, - stopSlackMonitor, -} from "./monitor.test-helpers.js"; - -const { monitorSlackProvider } = await import("./monitor.js"); - -const slackTestState = getSlackTestState(); -const { sendMock, replyMock, reactMock, upsertPairingRequestMock } = slackTestState; - -beforeEach(() => { - resetInboundDedupe(); - resetSlackTestState(defaultSlackTestConfig()); -}); - -describe("monitorSlackProvider tool results", () => { - it("forces thread replies when replyToId is set", async () => { - replyMock.mockResolvedValue({ text: "forced reply", replyToId: "555" }); - slackTestState.config = { - messages: { - responsePrefix: "PFX", - ackReaction: "👀", - ackReactionScope: "group-mentions", - }, - channels: { - slack: { - dmPolicy: "open", - allowFrom: ["*"], - dm: { enabled: true }, - replyToMode: "off", - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "789", - channel: "C1", - channel_type: "im", - }, - }); - - expect(sendMock).toHaveBeenCalledTimes(1); - expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "555" }); - }); - - it("reacts to mention-gated room messages when ackReaction is enabled", async () => { - replyMock.mockResolvedValue(undefined); - const client = getSlackClient(); - if (!client) { - throw new Error("Slack client not registered"); - } - const conversations = client.conversations as { - info: ReturnType; - }; - conversations.info.mockResolvedValueOnce({ - channel: { name: "general", is_channel: true }, - }); - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "<@bot-user> hello", - ts: "456", - channel: "C1", - channel_type: "channel", - }, - }); - - expect(reactMock).toHaveBeenCalledWith({ - channel: "C1", - timestamp: "456", - name: "👀", - }); - }); - - it("replies with pairing code when dmPolicy is pairing and no allowFrom is set", async () => { - slackTestState.config = { - ...slackTestState.config, - channels: { - ...slackTestState.config.channels, - slack: { - ...slackTestState.config.channels?.slack, - dm: { enabled: true, policy: "pairing", allowFrom: [] }, - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "123", - channel: "C1", - channel_type: "im", - }, - }); - - expect(replyMock).not.toHaveBeenCalled(); - expect(upsertPairingRequestMock).toHaveBeenCalled(); - expect(sendMock).toHaveBeenCalledTimes(1); - expect(String(sendMock.mock.calls[0]?.[1] ?? "")).toContain("Your Slack user id: U1"); - expect(String(sendMock.mock.calls[0]?.[1] ?? "")).toContain("Pairing code: PAIRCODE"); - }); - - it("does not resend pairing code when a request is already pending", async () => { - slackTestState.config = { - ...slackTestState.config, - channels: { - ...slackTestState.config.channels, - slack: { - ...slackTestState.config.channels?.slack, - dm: { enabled: true, policy: "pairing", allowFrom: [] }, - }, - }, - }; - upsertPairingRequestMock - .mockResolvedValueOnce({ code: "PAIRCODE", created: true }) - .mockResolvedValueOnce({ code: "PAIRCODE", created: false }); - - const { controller, run } = startSlackMonitor(monitorSlackProvider); - const handler = await getSlackHandlerOrThrow("message"); - - const baseEvent = { - type: "message", - user: "U1", - text: "hello", - ts: "123", - channel: "C1", - channel_type: "im", - }; - - await handler({ event: baseEvent }); - await handler({ event: { ...baseEvent, ts: "124", text: "hello again" } }); - - await stopSlackMonitor({ controller, run }); - - expect(sendMock).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/slack/monitor.tool-result.sends-tool-summaries-responseprefix.test.ts b/src/slack/monitor.tool-result.test.ts similarity index 52% rename from src/slack/monitor.tool-result.sends-tool-summaries-responseprefix.test.ts rename to src/slack/monitor.tool-result.test.ts index f9fc21705c1..2e98b8e2653 100644 --- a/src/slack/monitor.tool-result.sends-tool-summaries-responseprefix.test.ts +++ b/src/slack/monitor.tool-result.test.ts @@ -16,7 +16,7 @@ import { const { monitorSlackProvider } = await import("./monitor.js"); const slackTestState = getSlackTestState(); -const { sendMock, replyMock } = slackTestState; +const { sendMock, replyMock, reactMock, upsertPairingRequestMock } = slackTestState; beforeEach(() => { resetInboundDedupe(); @@ -439,4 +439,384 @@ describe("monitorSlackProvider tool results", () => { expect(sendMock).toHaveBeenCalledTimes(1); expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "456" }); }); + + it("forces thread replies when replyToId is set", async () => { + replyMock.mockResolvedValue({ text: "forced reply", replyToId: "555" }); + slackTestState.config = { + messages: { + responsePrefix: "PFX", + ackReaction: "👀", + ackReactionScope: "group-mentions", + }, + channels: { + slack: { + dmPolicy: "open", + allowFrom: ["*"], + dm: { enabled: true }, + replyToMode: "off", + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "789", + channel: "C1", + channel_type: "im", + }, + }); + + expect(sendMock).toHaveBeenCalledTimes(1); + expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "555" }); + }); + + it("reacts to mention-gated room messages when ackReaction is enabled", async () => { + replyMock.mockResolvedValue(undefined); + const client = getSlackClient(); + if (!client) { + throw new Error("Slack client not registered"); + } + const conversations = client.conversations as { + info: ReturnType; + }; + conversations.info.mockResolvedValueOnce({ + channel: { name: "general", is_channel: true }, + }); + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "<@bot-user> hello", + ts: "456", + channel: "C1", + channel_type: "channel", + }, + }); + + expect(reactMock).toHaveBeenCalledWith({ + channel: "C1", + timestamp: "456", + name: "👀", + }); + }); + + it("replies with pairing code when dmPolicy is pairing and no allowFrom is set", async () => { + slackTestState.config = { + ...slackTestState.config, + channels: { + ...slackTestState.config.channels, + slack: { + ...slackTestState.config.channels?.slack, + dm: { enabled: true, policy: "pairing", allowFrom: [] }, + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "123", + channel: "C1", + channel_type: "im", + }, + }); + + expect(replyMock).not.toHaveBeenCalled(); + expect(upsertPairingRequestMock).toHaveBeenCalled(); + expect(sendMock).toHaveBeenCalledTimes(1); + expect(String(sendMock.mock.calls[0]?.[1] ?? "")).toContain("Your Slack user id: U1"); + expect(String(sendMock.mock.calls[0]?.[1] ?? "")).toContain("Pairing code: PAIRCODE"); + }); + + it("does not resend pairing code when a request is already pending", async () => { + slackTestState.config = { + ...slackTestState.config, + channels: { + ...slackTestState.config.channels, + slack: { + ...slackTestState.config.channels?.slack, + dm: { enabled: true, policy: "pairing", allowFrom: [] }, + }, + }, + }; + upsertPairingRequestMock + .mockResolvedValueOnce({ code: "PAIRCODE", created: true }) + .mockResolvedValueOnce({ code: "PAIRCODE", created: false }); + + const { controller, run } = startSlackMonitor(monitorSlackProvider); + const handler = await getSlackHandlerOrThrow("message"); + + const baseEvent = { + type: "message", + user: "U1", + text: "hello", + ts: "123", + channel: "C1", + channel_type: "im", + }; + + await handler({ event: baseEvent }); + await handler({ event: { ...baseEvent, ts: "124", text: "hello again" } }); + + await stopSlackMonitor({ controller, run }); + + expect(sendMock).toHaveBeenCalledTimes(1); + }); + + it("threads top-level replies when replyToMode is all", async () => { + replyMock.mockResolvedValue({ text: "thread reply" }); + slackTestState.config = { + messages: { + responsePrefix: "PFX", + ackReaction: "👀", + ackReactionScope: "group-mentions", + }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + replyToMode: "all", + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "123", + channel: "C1", + channel_type: "im", + }, + }); + + expect(sendMock).toHaveBeenCalledTimes(1); + expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "123" }); + }); + + it("treats parent_user_id as a thread reply even when thread_ts matches ts", async () => { + replyMock.mockResolvedValue({ text: "thread reply" }); + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "123", + thread_ts: "123", + parent_user_id: "U2", + channel: "C1", + channel_type: "im", + }, + }); + + expect(replyMock).toHaveBeenCalledTimes(1); + const ctx = replyMock.mock.calls[0]?.[0] as { + SessionKey?: string; + ParentSessionKey?: string; + }; + expect(ctx.SessionKey).toBe("agent:main:main:thread:123"); + expect(ctx.ParentSessionKey).toBeUndefined(); + }); + + it("keeps thread parent inheritance opt-in", async () => { + replyMock.mockResolvedValue({ text: "thread reply" }); + + slackTestState.config = { + messages: { responsePrefix: "PFX" }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + channels: { C1: { allow: true, requireMention: false } }, + thread: { inheritParent: true }, + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "123", + thread_ts: "111.222", + channel: "C1", + channel_type: "channel", + }, + }); + + expect(replyMock).toHaveBeenCalledTimes(1); + const ctx = replyMock.mock.calls[0]?.[0] as { + SessionKey?: string; + ParentSessionKey?: string; + }; + expect(ctx.SessionKey).toBe("agent:main:slack:channel:c1:thread:111.222"); + expect(ctx.ParentSessionKey).toBe("agent:main:slack:channel:c1"); + }); + + it("injects starter context for thread replies", async () => { + replyMock.mockResolvedValue({ text: "ok" }); + + const client = getSlackClient(); + if (client?.conversations?.info) { + client.conversations.info.mockResolvedValue({ + channel: { name: "general", is_channel: true }, + }); + } + if (client?.conversations?.replies) { + client.conversations.replies.mockResolvedValue({ + messages: [{ text: "starter message", user: "U2", ts: "111.222" }], + }); + } + + slackTestState.config = { + messages: { responsePrefix: "PFX" }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + channels: { C1: { allow: true, requireMention: false } }, + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "thread reply", + ts: "123.456", + thread_ts: "111.222", + channel: "C1", + channel_type: "channel", + }, + }); + + expect(replyMock).toHaveBeenCalledTimes(1); + const ctx = replyMock.mock.calls[0]?.[0] as { + SessionKey?: string; + ParentSessionKey?: string; + ThreadStarterBody?: string; + ThreadLabel?: string; + }; + expect(ctx.SessionKey).toBe("agent:main:slack:channel:c1:thread:111.222"); + expect(ctx.ParentSessionKey).toBeUndefined(); + expect(ctx.ThreadStarterBody).toContain("starter message"); + expect(ctx.ThreadLabel).toContain("Slack thread #general"); + }); + + it("scopes thread session keys to the routed agent", async () => { + replyMock.mockResolvedValue({ text: "ok" }); + slackTestState.config = { + messages: { responsePrefix: "PFX" }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + channels: { C1: { allow: true, requireMention: false } }, + }, + }, + bindings: [{ agentId: "support", match: { channel: "slack", teamId: "T1" } }], + }; + + const client = getSlackClient(); + if (client?.auth?.test) { + client.auth.test.mockResolvedValue({ + user_id: "bot-user", + team_id: "T1", + }); + } + if (client?.conversations?.info) { + client.conversations.info.mockResolvedValue({ + channel: { name: "general", is_channel: true }, + }); + } + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "thread reply", + ts: "123.456", + thread_ts: "111.222", + channel: "C1", + channel_type: "channel", + }, + }); + + expect(replyMock).toHaveBeenCalledTimes(1); + const ctx = replyMock.mock.calls[0]?.[0] as { + SessionKey?: string; + ParentSessionKey?: string; + }; + expect(ctx.SessionKey).toBe("agent:support:slack:channel:c1:thread:111.222"); + expect(ctx.ParentSessionKey).toBeUndefined(); + }); + + it("keeps replies in channel root when message is not threaded (replyToMode off)", async () => { + replyMock.mockResolvedValue({ text: "root reply" }); + slackTestState.config = { + messages: { + responsePrefix: "PFX", + ackReaction: "👀", + ackReactionScope: "group-mentions", + }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + replyToMode: "off", + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "789", + channel: "C1", + channel_type: "im", + }, + }); + + expect(sendMock).toHaveBeenCalledTimes(1); + expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: undefined }); + }); + + it("threads first reply when replyToMode is first and message is not threaded", async () => { + replyMock.mockResolvedValue({ text: "first reply" }); + slackTestState.config = { + messages: { + responsePrefix: "PFX", + ackReaction: "👀", + ackReactionScope: "group-mentions", + }, + channels: { + slack: { + dm: { enabled: true, policy: "open", allowFrom: ["*"] }, + replyToMode: "first", + }, + }, + }; + + await runSlackMessageOnce(monitorSlackProvider, { + event: { + type: "message", + user: "U1", + text: "hello", + ts: "789", + channel: "C1", + channel_type: "im", + }, + }); + + expect(sendMock).toHaveBeenCalledTimes(1); + // First reply starts a thread under the incoming message + expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "789" }); + }); }); diff --git a/src/slack/monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts b/src/slack/monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts deleted file mode 100644 index 7e2574d6967..00000000000 --- a/src/slack/monitor.tool-result.threads-top-level-replies-replytomode-is-all.test.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { beforeEach, describe, expect, it } from "vitest"; -import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js"; -import { - defaultSlackTestConfig, - getSlackClient, - getSlackTestState, - resetSlackTestState, - runSlackMessageOnce, -} from "./monitor.test-helpers.js"; - -const { monitorSlackProvider } = await import("./monitor.js"); - -const slackTestState = getSlackTestState(); -const { sendMock, replyMock } = slackTestState; - -beforeEach(() => { - resetInboundDedupe(); - resetSlackTestState(defaultSlackTestConfig()); -}); - -describe("monitorSlackProvider tool results", () => { - it("threads top-level replies when replyToMode is all", async () => { - replyMock.mockResolvedValue({ text: "thread reply" }); - slackTestState.config = { - messages: { - responsePrefix: "PFX", - ackReaction: "👀", - ackReactionScope: "group-mentions", - }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - replyToMode: "all", - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "123", - channel: "C1", - channel_type: "im", - }, - }); - - expect(sendMock).toHaveBeenCalledTimes(1); - expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "123" }); - }); - - it("treats parent_user_id as a thread reply even when thread_ts matches ts", async () => { - replyMock.mockResolvedValue({ text: "thread reply" }); - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "123", - thread_ts: "123", - parent_user_id: "U2", - channel: "C1", - channel_type: "im", - }, - }); - - expect(replyMock).toHaveBeenCalledTimes(1); - const ctx = replyMock.mock.calls[0]?.[0] as { - SessionKey?: string; - ParentSessionKey?: string; - }; - expect(ctx.SessionKey).toBe("agent:main:main:thread:123"); - expect(ctx.ParentSessionKey).toBeUndefined(); - }); - - it("keeps thread parent inheritance opt-in", async () => { - replyMock.mockResolvedValue({ text: "thread reply" }); - - slackTestState.config = { - messages: { responsePrefix: "PFX" }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - channels: { C1: { allow: true, requireMention: false } }, - thread: { inheritParent: true }, - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "123", - thread_ts: "111.222", - channel: "C1", - channel_type: "channel", - }, - }); - - expect(replyMock).toHaveBeenCalledTimes(1); - const ctx = replyMock.mock.calls[0]?.[0] as { - SessionKey?: string; - ParentSessionKey?: string; - }; - expect(ctx.SessionKey).toBe("agent:main:slack:channel:c1:thread:111.222"); - expect(ctx.ParentSessionKey).toBe("agent:main:slack:channel:c1"); - }); - - it("injects starter context for thread replies", async () => { - replyMock.mockResolvedValue({ text: "ok" }); - - const client = getSlackClient(); - if (client?.conversations?.info) { - client.conversations.info.mockResolvedValue({ - channel: { name: "general", is_channel: true }, - }); - } - if (client?.conversations?.replies) { - client.conversations.replies.mockResolvedValue({ - messages: [{ text: "starter message", user: "U2", ts: "111.222" }], - }); - } - - slackTestState.config = { - messages: { responsePrefix: "PFX" }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - channels: { C1: { allow: true, requireMention: false } }, - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "thread reply", - ts: "123.456", - thread_ts: "111.222", - channel: "C1", - channel_type: "channel", - }, - }); - - expect(replyMock).toHaveBeenCalledTimes(1); - const ctx = replyMock.mock.calls[0]?.[0] as { - SessionKey?: string; - ParentSessionKey?: string; - ThreadStarterBody?: string; - ThreadLabel?: string; - }; - expect(ctx.SessionKey).toBe("agent:main:slack:channel:c1:thread:111.222"); - expect(ctx.ParentSessionKey).toBeUndefined(); - expect(ctx.ThreadStarterBody).toContain("starter message"); - expect(ctx.ThreadLabel).toContain("Slack thread #general"); - }); - - it("scopes thread session keys to the routed agent", async () => { - replyMock.mockResolvedValue({ text: "ok" }); - slackTestState.config = { - messages: { responsePrefix: "PFX" }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - channels: { C1: { allow: true, requireMention: false } }, - }, - }, - bindings: [{ agentId: "support", match: { channel: "slack", teamId: "T1" } }], - }; - - const client = getSlackClient(); - if (client?.auth?.test) { - client.auth.test.mockResolvedValue({ - user_id: "bot-user", - team_id: "T1", - }); - } - if (client?.conversations?.info) { - client.conversations.info.mockResolvedValue({ - channel: { name: "general", is_channel: true }, - }); - } - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "thread reply", - ts: "123.456", - thread_ts: "111.222", - channel: "C1", - channel_type: "channel", - }, - }); - - expect(replyMock).toHaveBeenCalledTimes(1); - const ctx = replyMock.mock.calls[0]?.[0] as { - SessionKey?: string; - ParentSessionKey?: string; - }; - expect(ctx.SessionKey).toBe("agent:support:slack:channel:c1:thread:111.222"); - expect(ctx.ParentSessionKey).toBeUndefined(); - }); - - it("keeps replies in channel root when message is not threaded (replyToMode off)", async () => { - replyMock.mockResolvedValue({ text: "root reply" }); - slackTestState.config = { - messages: { - responsePrefix: "PFX", - ackReaction: "👀", - ackReactionScope: "group-mentions", - }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - replyToMode: "off", - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "789", - channel: "C1", - channel_type: "im", - }, - }); - - expect(sendMock).toHaveBeenCalledTimes(1); - expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: undefined }); - }); - - it("threads first reply when replyToMode is first and message is not threaded", async () => { - replyMock.mockResolvedValue({ text: "first reply" }); - slackTestState.config = { - messages: { - responsePrefix: "PFX", - ackReaction: "👀", - ackReactionScope: "group-mentions", - }, - channels: { - slack: { - dm: { enabled: true, policy: "open", allowFrom: ["*"] }, - replyToMode: "first", - }, - }, - }; - - await runSlackMessageOnce(monitorSlackProvider, { - event: { - type: "message", - user: "U1", - text: "hello", - ts: "789", - channel: "C1", - channel_type: "im", - }, - }); - - expect(sendMock).toHaveBeenCalledTimes(1); - // First reply starts a thread under the incoming message - expect(sendMock.mock.calls[0][2]).toMatchObject({ threadTs: "789" }); - }); -});