test: guard msteams oauth mock calls

This commit is contained in:
Peter Steinberger
2026-05-12 01:52:52 +01:00
parent 7857bf0c5c
commit fb15b32df2
3 changed files with 46 additions and 5 deletions

View File

@@ -34,6 +34,22 @@ const baseParams = {
log: { debug: vi.fn() },
};
function firstGraphMediaCall() {
const [call] = vi.mocked(downloadMSTeamsGraphMedia).mock.calls;
if (!call) {
throw new Error("expected Graph media download call");
}
return call[0];
}
function firstBotFrameworkAttachmentCall() {
const [call] = vi.mocked(downloadMSTeamsBotFrameworkAttachments).mock.calls;
if (!call) {
throw new Error("expected Bot Framework attachment download call");
}
return call[0];
}
describe("resolveMSTeamsInboundMedia graph fallback trigger", () => {
it("triggers Graph fallback when HTML contains <attachment> tags", async () => {
vi.mocked(downloadMSTeamsAttachments).mockResolvedValue([]);
@@ -133,7 +149,7 @@ describe("resolveMSTeamsInboundMedia graph fallback trigger", () => {
],
});
const call = vi.mocked(downloadMSTeamsGraphMedia).mock.calls[0]?.[0];
const call = firstGraphMediaCall();
// The monitor handler's logger is forwarded so graph.ts can report
// message fetch failures instead of swallowing them (#51749).
expect(call?.logger).toBe(log);
@@ -187,7 +203,7 @@ describe("resolveMSTeamsInboundMedia bot framework DM routing", () => {
});
expect(downloadMSTeamsBotFrameworkAttachments).toHaveBeenCalledTimes(1);
const call = vi.mocked(downloadMSTeamsBotFrameworkAttachments).mock.calls[0]?.[0];
const call = firstBotFrameworkAttachmentCall();
expect(call?.serviceUrl).toBe(dmParams.serviceUrl);
expect(call?.attachmentIds).toEqual(["att-0", "att-1"]);
expect(downloadMSTeamsGraphMedia).not.toHaveBeenCalled();

View File

@@ -38,6 +38,14 @@ function responseJson(body: unknown, status = 200): Response {
});
}
function firstFetchCall(fetchSpy: ReturnType<typeof vi.fn>): [string, RequestInit] {
const [call] = fetchSpy.mock.calls;
if (!call) {
throw new Error("expected fetch call");
}
return call as [string, RequestInit];
}
describe("generatePkce", () => {
it("produces a 64-char hex verifier and a base64url SHA-256 challenge", () => {
const { verifier, challenge } = generatePkce();
@@ -191,7 +199,7 @@ describe("exchangeMSTeamsCodeForTokens", () => {
// Verify the request was well-formed
expect(fetchSpy).toHaveBeenCalledOnce();
const [url, init] = fetchSpy.mock.calls[0] as [string, RequestInit];
const [url, init] = firstFetchCall(fetchSpy);
expect(url).toBe(buildMSTeamsTokenEndpoint("tenant-1"));
const body = new URLSearchParams(init.body as string);
expect(body.get("client_id")).toBe("client-1");
@@ -259,7 +267,7 @@ describe("refreshMSTeamsDelegatedTokens", () => {
expect(tokens.expiresAt).toBeGreaterThanOrEqual(now + 3300 * 1000 - 1000);
// Verify the request body includes refresh_token grant type
const [, init] = fetchSpy.mock.calls[0] as [string, RequestInit];
const [, init] = firstFetchCall(fetchSpy);
const body = new URLSearchParams(init.body as string);
expect(body.get("grant_type")).toBe("refresh_token");
expect(body.get("refresh_token")).toBe("original-rt");

View File

@@ -48,6 +48,23 @@ function requireSendPoll(): MSTeamsSendPoll {
return sendPoll;
}
type PollRecord = Record<string, unknown> & { createdAt: string };
function firstPollRecord(): PollRecord {
const [call] = mocks.createPoll.mock.calls;
if (!call) {
throw new Error("expected createPoll call");
}
const [pollRecord] = call;
if (!pollRecord || typeof pollRecord !== "object" || Array.isArray(pollRecord)) {
throw new Error("expected createPoll record");
}
if (typeof (pollRecord as { createdAt?: unknown }).createdAt !== "string") {
throw new Error("expected createPoll record timestamp");
}
return pollRecord as PollRecord;
}
describe("msteamsOutbound cfg threading", () => {
beforeEach(() => {
mocks.sendMessageMSTeams.mockReset();
@@ -138,7 +155,7 @@ describe("msteamsOutbound cfg threading", () => {
options: ["Pizza", "Sushi"],
maxSelections: 1,
});
const [pollRecord] = mocks.createPoll.mock.calls[0] ?? [];
const pollRecord = firstPollRecord();
expect(pollRecord).toEqual({
id: "poll-1",
question: "Snack?",