diff --git a/extensions/msteams/src/send.test.ts b/extensions/msteams/src/send.test.ts index a4e5e1c6f06..fb2084b53aa 100644 --- a/extensions/msteams/src/send.test.ts +++ b/extensions/msteams/src/send.test.ts @@ -181,6 +181,26 @@ function mockSharePointPdfUpload(params: { }); } +type MockWithCalls = { + mock: { calls: unknown[][] }; +}; + +function firstObjectArg(mock: MockWithCalls): Record { + const value = mock.mock.calls[0]?.[0]; + if (value === undefined || value === null || typeof value !== "object" || Array.isArray(value)) { + throw new Error("expected first mock call to receive an object argument"); + } + return value as Record; +} + +function continueConversationRef(mock: MockWithCalls): Record { + const ref = mock.mock.calls[0]?.[1]; + if (ref === undefined || ref === null || typeof ref !== "object" || Array.isArray(ref)) { + throw new Error("expected continueConversation ref object"); + } + return ref as Record; +} + describe("sendMessageMSTeams", () => { beforeEach(() => { mockState.loadOutboundMediaFromUrl.mockReset(); @@ -244,21 +264,16 @@ describe("sendMessageMSTeams", () => { }, ); - expect(mockState.sendMSTeamsMessages).toHaveBeenCalledWith( - expect.objectContaining({ - messages: [ - expect.objectContaining({ - text: "hello", - mediaUrl: `data:image/png;base64,${mediaBuffer.toString("base64")}`, - }), - ], - }), - ); - expect(result.receipt).toMatchObject({ - primaryPlatformMessageId: "message-1", - platformMessageIds: ["message-1"], - parts: [expect.objectContaining({ platformMessageId: "message-1", kind: "media" })], - }); + const sendPayload = firstObjectArg(mockState.sendMSTeamsMessages); + const messages = sendPayload.messages as Array>; + expect(messages).toHaveLength(1); + expect(messages[0]?.text).toBe("hello"); + expect(messages[0]?.mediaUrl).toBe(`data:image/png;base64,${mediaBuffer.toString("base64")}`); + expect(result.receipt?.primaryPlatformMessageId).toBe("message-1"); + expect(result.receipt?.platformMessageIds).toEqual(["message-1"]); + expect(result.receipt?.parts).toHaveLength(1); + expect(result.receipt?.parts[0]?.platformMessageId).toBe("message-1"); + expect(result.receipt?.parts[0]?.kind).toBe("media"); }); it("sends with provided cfg even when Teams runtime text helpers are unavailable", async () => { @@ -277,15 +292,13 @@ describe("sendMessageMSTeams", () => { text: "hello", }); - expect(result).toMatchObject({ - messageId: "message-1", - conversationId: "19:conversation@thread.tacv2", - receipt: { - primaryPlatformMessageId: "message-1", - platformMessageIds: ["message-1"], - parts: [expect.objectContaining({ platformMessageId: "message-1", kind: "text" })], - }, - }); + expect(result.messageId).toBe("message-1"); + expect(result.conversationId).toBe("19:conversation@thread.tacv2"); + expect(result.receipt?.primaryPlatformMessageId).toBe("message-1"); + expect(result.receipt?.platformMessageIds).toEqual(["message-1"]); + expect(result.receipt?.parts).toHaveLength(1); + expect(result.receipt?.parts[0]?.platformMessageId).toBe("message-1"); + expect(result.receipt?.parts[0]?.kind).toBe("text"); expect(mockState.resolveMarkdownTableMode).toHaveBeenCalledWith({ cfg: {}, @@ -317,9 +330,7 @@ describe("sendMessageMSTeams", () => { text: "threaded reply", }); - expect(mockState.sendMSTeamsMessages).toHaveBeenCalledWith( - expect.objectContaining({ replyStyle: "thread" }), - ); + expect(firstObjectArg(mockState.sendMSTeamsMessages).replyStyle).toBe("thread"); }); it("keeps top-level proactive replyStyle when resolved for a channel", async () => { @@ -345,9 +356,7 @@ describe("sendMessageMSTeams", () => { text: "top-level reply", }); - expect(mockState.sendMSTeamsMessages).toHaveBeenCalledWith( - expect.objectContaining({ replyStyle: "top-level" }), - ); + expect(firstObjectArg(mockState.sendMSTeamsMessages).replyStyle).toBe("top-level"); }); it("uses graphChatId instead of conversationId when uploading to SharePoint", async () => { @@ -378,12 +387,9 @@ describe("sendMessageMSTeams", () => { }); // The Graph-native chatId must be passed to SharePoint upload, not the Bot Framework ID - expect(mockState.uploadAndShareSharePoint).toHaveBeenCalledWith( - expect.objectContaining({ - chatId: graphChatId, - siteId: "site-123", - }), - ); + const uploadPayload = firstObjectArg(mockState.uploadAndShareSharePoint); + expect(uploadPayload.chatId).toBe(graphChatId); + expect(uploadPayload.siteId).toBe("site-123"); }); it("falls back to conversationId when graphChatId is not available", async () => { @@ -411,12 +417,9 @@ describe("sendMessageMSTeams", () => { }); // Falls back to conversationId when graphChatId is null - expect(mockState.uploadAndShareSharePoint).toHaveBeenCalledWith( - expect.objectContaining({ - chatId: botFrameworkConversationId, - siteId: "site-456", - }), - ); + const uploadPayload = firstObjectArg(mockState.uploadAndShareSharePoint); + expect(uploadPayload.chatId).toBe(botFrameworkConversationId); + expect(uploadPayload.siteId).toBe("site-456"); }); }); @@ -477,9 +480,7 @@ describe("editMessageMSTeams", () => { expect(mockContinueConversation).toHaveBeenCalledTimes(1); const continueConversationCall = mockContinueConversation.mock.calls[0]; expect(continueConversationCall?.[0]).toBe("app-id"); - expect(continueConversationCall?.[1]).toEqual( - expect.objectContaining({ activityId: undefined }), - ); + expect(continueConversationRef(mockContinueConversation).activityId).toBeUndefined(); expect(typeof continueConversationCall?.[2]).toBe("function"); expect(mockUpdateActivity).toHaveBeenCalledWith({ type: "message", @@ -530,9 +531,7 @@ describe("deleteMessageMSTeams", () => { expect(mockContinueConversation).toHaveBeenCalledTimes(1); const continueConversationCall = mockContinueConversation.mock.calls[0]; expect(continueConversationCall?.[0]).toBe("app-id"); - expect(continueConversationCall?.[1]).toEqual( - expect.objectContaining({ activityId: undefined }), - ); + expect(continueConversationRef(mockContinueConversation).activityId).toBeUndefined(); expect(typeof continueConversationCall?.[2]).toBe("function"); expect(mockDeleteActivity).toHaveBeenCalledWith("activity-456"); }); @@ -572,8 +571,6 @@ describe("deleteMessageMSTeams", () => { // appId should be forwarded correctly expect(mockContinueConversation.mock.calls[0]?.[0]).toBe("my-app-id"); // activityId on the proactive ref should be cleared (undefined) — proactive pattern - expect(mockContinueConversation.mock.calls[0]?.[1]).toMatchObject({ - activityId: undefined, - }); + expect(continueConversationRef(mockContinueConversation).activityId).toBeUndefined(); }); });