fix: restore repo-wide gate after upstream sync

This commit is contained in:
Peter Steinberger
2026-03-22 17:16:04 +00:00
parent 0ac939059e
commit 14074d3337
9 changed files with 143 additions and 125 deletions

View File

@@ -111,7 +111,7 @@ describe("resolveGraphChatId", () => {
const result = await resolveGraphChatId({
botFrameworkConversationId: "19:abc123@thread.tacv2",
tokenProvider,
fetchFn,
fetchFn: withFetchPreconnect(fetchFn),
});
// Should short-circuit without making any API call
expect(fetchFn).not.toHaveBeenCalled();
@@ -131,7 +131,7 @@ describe("resolveGraphChatId", () => {
botFrameworkConversationId: "a:1abc_bot_framework_dm_id",
userAadObjectId: "user-aad-object-id-123",
tokenProvider,
fetchFn,
fetchFn: withFetchPreconnect(fetchFn),
});
expect(fetchFn).toHaveBeenCalledWith(
@@ -158,7 +158,7 @@ describe("resolveGraphChatId", () => {
const result = await resolveGraphChatId({
botFrameworkConversationId: "8:orgid:user-object-id",
tokenProvider,
fetchFn,
fetchFn: withFetchPreconnect(fetchFn),
});
expect(fetchFn).toHaveBeenCalledOnce();
@@ -178,7 +178,7 @@ describe("resolveGraphChatId", () => {
botFrameworkConversationId: "a:1unknown_dm",
userAadObjectId: "some-user",
tokenProvider,
fetchFn,
fetchFn: withFetchPreconnect(fetchFn),
});
expect(result).toBeNull();
@@ -197,7 +197,7 @@ describe("resolveGraphChatId", () => {
botFrameworkConversationId: "a:1some_dm_id",
userAadObjectId: "some-user",
tokenProvider,
fetchFn,
fetchFn: withFetchPreconnect(fetchFn),
});
expect(result).toBeNull();

View File

@@ -138,7 +138,12 @@ function createConsentInvokeHarness(params: {
contentType: "text/plain",
conversationId: params.pendingConversationId ?? "19:victim@thread.v2",
});
const handler = registerMSTeamsHandlers(createActivityHandler(), createDeps());
const handler = registerMSTeamsHandlers(
createActivityHandler(),
createDeps(),
) as MSTeamsActivityHandler & {
run: NonNullable<MSTeamsActivityHandler["run"]>;
};
const { context, sendActivity } = createInvokeContext({
conversationId: params.invokeConversationId,
uploadId,

View File

@@ -1,4 +1,5 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../../test/helpers/extensions/fetch-mock.js";
import { refreshQwenPortalCredentials } from "./refresh.js";
function expiredCredentials() {
@@ -22,18 +23,20 @@ describe("refreshQwenPortalCredentials", () => {
const runRefresh = async () => await refreshQwenPortalCredentials(expiredCredentials());
it("refreshes oauth credentials and preserves existing refresh token when absent", async () => {
globalThis.fetch = vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
expires_in: 3600,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
expires_in: 3600,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}),
);
const result = await runRefresh();
@@ -51,19 +54,21 @@ describe("refreshQwenPortalCredentials", () => {
});
it("replaces the refresh token when the server rotates it", async () => {
globalThis.fetch = vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
refresh_token: "rotated-refresh",
expires_in: 1200,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
refresh_token: "rotated-refresh",
expires_in: 1200,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}),
);
const result = await runRefresh();
@@ -71,18 +76,20 @@ describe("refreshQwenPortalCredentials", () => {
});
it("rejects invalid expires_in payloads", async () => {
globalThis.fetch = vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
expires_in: 0,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => {
return new Response(
JSON.stringify({
access_token: "new-access",
expires_in: 0,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}),
);
await expect(runRefresh()).rejects.toThrow(
"Qwen OAuth refresh response missing or invalid expires_in",
@@ -90,9 +97,9 @@ describe("refreshQwenPortalCredentials", () => {
});
it("turns 400 responses into a re-authenticate hint", async () => {
globalThis.fetch = vi.fn(
async () => new Response("bad refresh", { status: 400 }),
) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => new Response("bad refresh", { status: 400 })),
);
await expect(runRefresh()).rejects.toThrow("Qwen OAuth refresh token expired or invalid");
});
@@ -110,25 +117,27 @@ describe("refreshQwenPortalCredentials", () => {
});
it("rejects missing access tokens", async () => {
globalThis.fetch = vi.fn(async () => {
return new Response(
JSON.stringify({
expires_in: 3600,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => {
return new Response(
JSON.stringify({
expires_in: 3600,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}),
);
await expect(runRefresh()).rejects.toThrow("Qwen OAuth refresh response missing access token");
});
it("surfaces non-400 refresh failures", async () => {
globalThis.fetch = vi.fn(
async () => new Response("gateway down", { status: 502 }),
) as typeof fetch;
globalThis.fetch = withFetchPreconnect(
vi.fn(async () => new Response("gateway down", { status: 502 })),
);
await expect(runRefresh()).rejects.toThrow("Qwen OAuth refresh failed: gateway down");
});