
























@@ -115,6 +115,30 @@ async function setupLifecycleMonitor() {
115115});
116116}
117117118+function latestReplyDispatcherParams() {
119+const call = createFeishuReplyDispatcherMock.mock.calls.at(-1);
120+if (!call) {
121+throw new Error("expected Feishu reply dispatcher call");
122+}
123+return call[0] as {
124+accountId?: string;
125+chatId?: string;
126+replyToMessageId?: string;
127+};
128+}
129+130+function latestFinalizedContext() {
131+const call = finalizeInboundContextMock.mock.calls.at(-1);
132+if (!call) {
133+throw new Error("expected finalized inbound context call");
134+}
135+return call[0] as {
136+AccountId?: string;
137+SessionKey?: string;
138+MessageSid?: string;
139+};
140+}
141+118142describe("Feishu card-action lifecycle", () => {
119143beforeEach(() => {
120144vi.useRealTimers();
@@ -180,20 +204,14 @@ describe("Feishu card-action lifecycle", () => {
180204expect(lastRuntime?.error).not.toHaveBeenCalled();
181205expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
182206expect(createFeishuReplyDispatcherMock).toHaveBeenCalledTimes(1);
183-expect(createFeishuReplyDispatcherMock).toHaveBeenCalledWith(
184-expect.objectContaining({
185-accountId: "acct-card",
186-chatId: "p2p:ou_user1",
187-replyToMessageId: undefined,
188-}),
189-);
190-expect(finalizeInboundContextMock).toHaveBeenCalledWith(
191-expect.objectContaining({
192-AccountId: "acct-card",
193-SessionKey: "agent:bound-agent:feishu:direct:ou_user1",
194-MessageSid: "card-action-tok-card-once",
195-}),
196-);
207+const dispatcherParams = latestReplyDispatcherParams();
208+expect(dispatcherParams.accountId).toBe("acct-card");
209+expect(dispatcherParams.chatId).toBe("p2p:ou_user1");
210+expect(dispatcherParams.replyToMessageId).toBeUndefined();
211+const finalized = latestFinalizedContext();
212+expect(finalized.AccountId).toBe("acct-card");
213+expect(finalized.SessionKey).toBe("agent:bound-agent:feishu:direct:ou_user1");
214+expect(finalized.MessageSid).toBe("card-action-tok-card-once");
197215expect(touchBindingMock).toHaveBeenCalledWith("binding-card");
198216199217expectFeishuReplyDispatcherSentFinalReplyOnce({ createFeishuReplyDispatcherMock });
@@ -232,18 +250,11 @@ describe("Feishu card-action lifecycle", () => {
232250233251expect(lastRuntime?.error).not.toHaveBeenCalled();
234252expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
235-expect(createFeishuReplyDispatcherMock).toHaveBeenCalledWith(
236-expect.objectContaining({
237-accountId: "acct-card",
238- chatId,
239-replyToMessageId: "om_card_v2",
240-}),
241-);
242-expect(finalizeInboundContextMock).toHaveBeenCalledWith(
243-expect.objectContaining({
244-MessageSid: "card-action-tok-card-v2-context",
245-}),
246-);
253+const dispatcherParams = latestReplyDispatcherParams();
254+expect(dispatcherParams.accountId).toBe("acct-card");
255+expect(dispatcherParams.chatId).toBe(chatId);
256+expect(dispatcherParams.replyToMessageId).toBe("om_card_v2");
257+expect(latestFinalizedContext().MessageSid).toBe("card-action-tok-card-v2-context");
247258});
248259249260it("routes SDK-style card callbacks without context as direct callbacks", async () => {
@@ -265,18 +276,11 @@ describe("Feishu card-action lifecycle", () => {
265276266277expect(lastRuntime?.error).not.toHaveBeenCalled();
267278expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
268-expect(createFeishuReplyDispatcherMock).toHaveBeenCalledWith(
269-expect.objectContaining({
270-accountId: "acct-card",
271-chatId: "ou_user1",
272-replyToMessageId: "om_sdk_card",
273-}),
274-);
275-expect(finalizeInboundContextMock).toHaveBeenCalledWith(
276-expect.objectContaining({
277-MessageSid: "card-action-tok-card-sdk-flat",
278-}),
279-);
279+const dispatcherParams = latestReplyDispatcherParams();
280+expect(dispatcherParams.accountId).toBe("acct-card");
281+expect(dispatcherParams.chatId).toBe("ou_user1");
282+expect(dispatcherParams.replyToMessageId).toBe("om_sdk_card");
283+expect(latestFinalizedContext().MessageSid).toBe("card-action-tok-card-sdk-flat");
280284});
281285282286it("plain-sends card action replies when Feishu provides no real message id", async () => {
@@ -295,18 +299,11 @@ describe("Feishu card-action lifecycle", () => {
295299296300expect(lastRuntime?.error).not.toHaveBeenCalled();
297301expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
298-expect(createFeishuReplyDispatcherMock).toHaveBeenCalledWith(
299-expect.objectContaining({
300-accountId: "acct-card",
301-chatId: "ou_user1",
302-replyToMessageId: undefined,
303-}),
304-);
305-expect(finalizeInboundContextMock).toHaveBeenCalledWith(
306-expect.objectContaining({
307-MessageSid: "card-action-tok-card-no-reply-target",
308-}),
309-);
302+const dispatcherParams = latestReplyDispatcherParams();
303+expect(dispatcherParams.accountId).toBe("acct-card");
304+expect(dispatcherParams.chatId).toBe("ou_user1");
305+expect(dispatcherParams.replyToMessageId).toBeUndefined();
306+expect(latestFinalizedContext().MessageSid).toBe("card-action-tok-card-no-reply-target");
310307});
311308312309it("does not duplicate delivery when retrying after a post-send failure", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。