From fa7da15be110d2d30c3ffb3c9f0776dc682ad1d8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 21:33:37 +0100 Subject: [PATCH] test: share google oauth fetch fixture --- extensions/google/oauth.test.ts | 124 ++++++++++++++------------------ 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/extensions/google/oauth.test.ts b/extensions/google/oauth.test.ts index 825122666f7..1996eba7090 100644 --- a/extensions/google/oauth.test.ts +++ b/extensions/google/oauth.test.ts @@ -583,6 +583,48 @@ describe("loginGeminiCliOAuth", () => { }); } + function tokenResponse(): Response { + return responseJson({ + access_token: "access-token", + refresh_token: "refresh-token", + expires_in: 3600, + }); + } + + function userInfoResponse(): Response { + return responseJson({ email: "lobster@openclaw.ai" }); + } + + type RecordedFetchRequest = { + url: string; + init?: RequestInit; + }; + + function installGeminiOAuthFetchMock( + handleRequest: (request: RecordedFetchRequest) => Response | undefined, + ) { + const requests: RecordedFetchRequest[] = []; + const fetchMock = vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const request = { url: getRequestUrl(input), init }; + requests.push(request); + + if (request.url === TOKEN_URL) { + return tokenResponse(); + } + if (request.url === USERINFO_URL) { + return userInfoResponse(); + } + + const response = handleRequest(request); + if (response) { + return response; + } + throw new Error(`Unexpected request: ${request.url}`); + }); + vi.stubGlobal("fetch", fetchMock); + return { fetchMock, requests }; + } + function getFormField(body: RequestInit["body"], name: string): string | null { if (!(body instanceof URLSearchParams)) { throw new Error("Expected URLSearchParams body"); @@ -675,21 +717,7 @@ describe("loginGeminiCliOAuth", () => { }); it("falls back across loadCodeAssist endpoints with aligned headers and metadata", async () => { - const requests: Array<{ url: string; init?: RequestInit }> = []; - const fetchMock = vi.fn(async (input: string | URL | Request, init?: RequestInit) => { - const url = getRequestUrl(input); - requests.push({ url, init }); - - if (url === TOKEN_URL) { - return responseJson({ - access_token: "access-token", - refresh_token: "refresh-token", - expires_in: 3600, - }); - } - if (url === USERINFO_URL) { - return responseJson({ email: "lobster@openclaw.ai" }); - } + const { requests } = installGeminiOAuthFetchMock(({ url }) => { if (url === LOAD_PROD) { return responseJson({ error: { message: "temporary failure" } }, 503); } @@ -699,9 +727,8 @@ describe("loginGeminiCliOAuth", () => { cloudaicompanionProject: { id: "daily-project" }, }); } - throw new Error(`Unexpected request: ${url}`); + return undefined; }); - vi.stubGlobal("fetch", fetchMock); const { loginGeminiCliOAuth } = await import("./oauth.js"); await runRemoteLoginExpectingProjectId(loginGeminiCliOAuth, "daily-project"); @@ -729,30 +756,15 @@ describe("loginGeminiCliOAuth", () => { }); it("keeps OAuth state separate from the PKCE verifier during manual login", async () => { - const requests: Array<{ url: string; init?: RequestInit }> = []; - const fetchMock = vi.fn(async (input: string | URL | Request, init?: RequestInit) => { - const url = getRequestUrl(input); - requests.push({ url, init }); - - if (url === TOKEN_URL) { - return responseJson({ - access_token: "access-token", - refresh_token: "refresh-token", - expires_in: 3600, - }); - } - if (url === USERINFO_URL) { - return responseJson({ email: "lobster@openclaw.ai" }); - } + const { requests } = installGeminiOAuthFetchMock(({ url }) => { if (url === LOAD_PROD) { return responseJson({ currentTier: { id: "standard-tier" }, cloudaicompanionProject: { id: "prod-project" }, }); } - throw new Error(`Unexpected request: ${url}`); + return undefined; }); - vi.stubGlobal("fetch", fetchMock); const { loginGeminiCliOAuth } = await import("./oauth.js"); const { authUrl } = await runRemoteLoginWithCapturedAuthUrl(loginGeminiCliOAuth); @@ -786,32 +798,17 @@ describe("loginGeminiCliOAuth", () => { it("falls back to GOOGLE_CLOUD_PROJECT when all loadCodeAssist endpoints fail", async () => { process.env.GOOGLE_CLOUD_PROJECT = "env-project"; - const requests: string[] = []; - const fetchMock = vi.fn(async (input: string | URL | Request) => { - const url = getRequestUrl(input); - requests.push(url); - - if (url === TOKEN_URL) { - return responseJson({ - access_token: "access-token", - refresh_token: "refresh-token", - expires_in: 3600, - }); - } - if (url === USERINFO_URL) { - return responseJson({ email: "lobster@openclaw.ai" }); - } + const { requests } = installGeminiOAuthFetchMock(({ url }) => { if ([LOAD_PROD, LOAD_DAILY, LOAD_AUTOPUSH].includes(url)) { return responseJson({ error: { message: "unavailable" } }, 503); } - throw new Error(`Unexpected request: ${url}`); + return undefined; }); - vi.stubGlobal("fetch", fetchMock); const { loginGeminiCliOAuth } = await import("./oauth.js"); await runRemoteLoginExpectingProjectId(loginGeminiCliOAuth, "env-project"); - expect(requests.filter((url) => url.includes("v1internal:loadCodeAssist"))).toHaveLength(3); - expect(requests.some((url) => url.includes("v1internal:onboardUser"))).toBe(false); + expect(requests.filter(({ url }) => url.includes("v1internal:loadCodeAssist"))).toHaveLength(3); + expect(requests.some(({ url }) => url.includes("v1internal:onboardUser"))).toBe(false); }); it("skips loadCodeAssist entirely when Gemini CLI is configured for personal OAuth", async () => { @@ -826,29 +823,12 @@ describe("loginGeminiCliOAuth", () => { }), ); - const requests: string[] = []; - const fetchMock = vi.fn(async (input: string | URL | Request) => { - const url = getRequestUrl(input); - requests.push(url); - - if (url === TOKEN_URL) { - return responseJson({ - access_token: "access-token", - refresh_token: "refresh-token", - expires_in: 3600, - }); - } - if (url === USERINFO_URL) { - return responseJson({ email: "lobster@openclaw.ai" }); - } - throw new Error(`Unexpected request: ${url}`); - }); - vi.stubGlobal("fetch", fetchMock); + const { requests } = installGeminiOAuthFetchMock(() => undefined); const { loginGeminiCliOAuth } = await import("./oauth.js"); const { result } = await runRemoteLoginWithCapturedAuthUrl(loginGeminiCliOAuth); expect(result.projectId).toBeUndefined(); - expect(requests).toEqual([TOKEN_URL, USERINFO_URL]); + expect(requests.map(({ url }) => url)).toEqual([TOKEN_URL, USERINFO_URL]); }); });