From 572df971798b21b035d7137e92647248bfe76f44 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 18:05:46 +0000 Subject: [PATCH] test: simplify provider auth normalization coverage --- ...rovider-usage.auth.normalizes-keys.test.ts | 267 ++++++++---------- 1 file changed, 124 insertions(+), 143 deletions(-) diff --git a/src/infra/provider-usage.auth.normalizes-keys.test.ts b/src/infra/provider-usage.auth.normalizes-keys.test.ts index 87d3f1ffbed..851c789941d 100644 --- a/src/infra/provider-usage.auth.normalizes-keys.test.ts +++ b/src/infra/provider-usage.auth.normalizes-keys.test.ts @@ -8,6 +8,13 @@ import { resolveProviderAuths } from "./provider-usage.auth.js"; describe("resolveProviderAuths key normalization", () => { let suiteRoot = ""; let suiteCase = 0; + const EMPTY_PROVIDER_ENV = { + ZAI_API_KEY: undefined, + Z_AI_API_KEY: undefined, + MINIMAX_API_KEY: undefined, + MINIMAX_CODE_PLAN_KEY: undefined, + XIAOMI_API_KEY: undefined, + } satisfies Record; beforeAll(async () => { suiteRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-provider-auth-suite-")); @@ -140,54 +147,91 @@ describe("resolveProviderAuths key normalization", () => { }); }, { - MINIMAX_API_KEY: undefined, - MINIMAX_CODE_PLAN_KEY: undefined, + ...EMPTY_PROVIDER_ENV, }, ); } - it("strips embedded CR/LF from env keys", async () => { + async function expectResolvedAuthsFromSuiteHome(params: { + providers: Parameters[0]["providers"]; + expected: Awaited>; + env?: Record; + setup?: (home: string) => Promise; + }) { await withSuiteHome( - async () => { + async (home) => { + await params.setup?.(home); const auths = await resolveProviderAuths({ - providers: ["zai", "minimax", "xiaomi"], + providers: params.providers, }); - expect(auths).toEqual([ - { provider: "zai", token: "zai-key" }, - { provider: "minimax", token: "minimax-key" }, - { provider: "xiaomi", token: "xiaomi-key" }, - ]); + expect(auths).toEqual(params.expected); }, { + ...EMPTY_PROVIDER_ENV, + ...params.env, + }, + ); + } + + it.each([ + { + name: "strips embedded CR/LF from env keys", + providers: ["zai", "minimax", "xiaomi"] as const, + env: { ZAI_API_KEY: "zai-\r\nkey", MINIMAX_API_KEY: "minimax-\r\nkey", XIAOMI_API_KEY: "xiaomi-\r\nkey", }, - ); + expected: [ + { provider: "zai", token: "zai-key" }, + { provider: "minimax", token: "minimax-key" }, + { provider: "xiaomi", token: "xiaomi-key" }, + ], + }, + { + name: "accepts z-ai env alias and normalizes embedded CR/LF", + providers: ["zai"] as const, + env: { + Z_AI_API_KEY: "zai-\r\nkey", + }, + expected: [{ provider: "zai", token: "zai-key" }], + }, + { + name: "prefers ZAI_API_KEY over the z-ai alias when both are set", + providers: ["zai"] as const, + env: { + ZAI_API_KEY: "direct-zai-key", + Z_AI_API_KEY: "alias-zai-key", + }, + expected: [{ provider: "zai", token: "direct-zai-key" }], + }, + { + name: "prefers MINIMAX_CODE_PLAN_KEY over MINIMAX_API_KEY", + providers: ["minimax"] as const, + env: { + MINIMAX_CODE_PLAN_KEY: "code-plan-key", + MINIMAX_API_KEY: "api-key", + }, + expected: [{ provider: "minimax", token: "code-plan-key" }], + }, + ])("$name", async ({ providers, env, expected }) => { + await expectResolvedAuthsFromSuiteHome({ providers: [...providers], env, expected }); }); it("strips embedded CR/LF from stored auth profiles (token + api_key)", async () => { - await withSuiteHome( - async (home) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["minimax", "xiaomi"], + setup: async (home) => { await writeAuthProfiles(home, { "minimax:default": { type: "token", provider: "minimax", token: "mini-\r\nmax" }, "xiaomi:default": { type: "api_key", provider: "xiaomi", key: "xiao-\r\nmi" }, }); - - const auths = await resolveProviderAuths({ - providers: ["minimax", "xiaomi"], - }); - expect(auths).toEqual([ - { provider: "minimax", token: "mini-max" }, - { provider: "xiaomi", token: "xiao-mi" }, - ]); }, - { - MINIMAX_API_KEY: undefined, - MINIMAX_CODE_PLAN_KEY: undefined, - XIAOMI_API_KEY: undefined, - }, - ); + expected: [ + { provider: "minimax", token: "mini-max" }, + { provider: "xiaomi", token: "xiao-mi" }, + ], + }); }); it("returns injected auth values unchanged", async () => { @@ -198,80 +242,52 @@ describe("resolveProviderAuths key normalization", () => { expect(auths).toEqual([{ provider: "anthropic", token: "token-1", accountId: "acc-1" }]); }); - it("accepts z-ai env alias and normalizes embedded CR/LF", async () => { - await withSuiteHome( - async () => { - const auths = await resolveProviderAuths({ - providers: ["zai"], - }); - expect(auths).toEqual([{ provider: "zai", token: "zai-key" }]); - }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: "zai-\r\nkey", - }, - ); - }); - it("falls back to legacy .pi auth file for zai keys even after os.homedir() is primed", async () => { // Prime os.homedir() to simulate long-lived workers that may have touched it before HOME changes. os.homedir(); - await withSuiteHome( - async (home) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["zai"], + setup: async (home) => { await writeLegacyPiAuth( home, `${JSON.stringify({ "z-ai": { access: "legacy-zai-key" } }, null, 2)}\n`, ); + }, + expected: [{ provider: "zai", token: "legacy-zai-key" }], + }); + }); - const auths = await resolveProviderAuths({ - providers: ["zai"], + it.each([ + { + name: "extracts google oauth token from JSON payload in token profiles", + token: '{"token":"google-oauth-token"}', + expectedToken: "google-oauth-token", + }, + { + name: "keeps raw google token when token payload is not JSON", + token: "plain-google-token", + expectedToken: "plain-google-token", + }, + ])("$name", async ({ token, expectedToken }) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["google-gemini-cli"], + setup: async (home) => { + await writeAuthProfiles(home, { + "google-gemini-cli:default": { + type: "token", + provider: "google-gemini-cli", + token, + }, }); - expect(auths).toEqual([{ provider: "zai", token: "legacy-zai-key" }]); }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: undefined, - }, - ); - }); - - it("extracts google oauth token from JSON payload in token profiles", async () => { - await withSuiteHome(async (home) => { - await writeAuthProfiles(home, { - "google-gemini-cli:default": { - type: "token", - provider: "google-gemini-cli", - token: '{"token":"google-oauth-token"}', - }, - }); - - const auths = await resolveProviderAuths({ - providers: ["google-gemini-cli"], - }); - expect(auths).toEqual([{ provider: "google-gemini-cli", token: "google-oauth-token" }]); - }, {}); - }); - - it("keeps raw google token when token payload is not JSON", async () => { - await withSuiteHome(async (home) => { - await writeAuthProfiles(home, { - "google-gemini-cli:default": { - type: "token", - provider: "google-gemini-cli", - token: "plain-google-token", - }, - }); - - const auths = await resolveProviderAuths({ - providers: ["google-gemini-cli"], - }); - expect(auths).toEqual([{ provider: "google-gemini-cli", token: "plain-google-token" }]); - }, {}); + expected: [{ provider: "google-gemini-cli", token: expectedToken }], + }); }); it("uses config api keys when env and profiles are missing", async () => { - await withSuiteHome( - async (home) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["zai", "minimax", "xiaomi"], + setup: async (home) => { const modelDef = { id: "test-model", name: "Test Model", @@ -302,77 +318,42 @@ describe("resolveProviderAuths key normalization", () => { }, }, }); - - const auths = await resolveProviderAuths({ - providers: ["zai", "minimax", "xiaomi"], - }); - expect(auths).toEqual([ - { provider: "zai", token: "cfg-zai-key" }, - { provider: "minimax", token: "cfg-minimax-key" }, - { provider: "xiaomi", token: "cfg-xiaomi-key" }, - ]); }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: undefined, - MINIMAX_API_KEY: undefined, - MINIMAX_CODE_PLAN_KEY: undefined, - XIAOMI_API_KEY: undefined, - }, - ); + expected: [ + { provider: "zai", token: "cfg-zai-key" }, + { provider: "minimax", token: "cfg-minimax-key" }, + { provider: "xiaomi", token: "cfg-xiaomi-key" }, + ], + }); }); it("returns no auth when providers have no configured credentials", async () => { - await withSuiteHome( - async () => { - const auths = await resolveProviderAuths({ - providers: ["zai", "minimax", "xiaomi"], - }); - expect(auths).toEqual([]); - }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: undefined, - MINIMAX_API_KEY: undefined, - MINIMAX_CODE_PLAN_KEY: undefined, - XIAOMI_API_KEY: undefined, - }, - ); + await expectResolvedAuthsFromSuiteHome({ + providers: ["zai", "minimax", "xiaomi"], + expected: [], + }); }); it("uses zai api_key auth profiles when env and config are missing", async () => { - await withSuiteHome( - async (home) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["zai"], + setup: async (home) => { await writeAuthProfiles(home, { "zai:default": { type: "api_key", provider: "zai", key: "profile-zai-key" }, }); - - const auths = await resolveProviderAuths({ - providers: ["zai"], - }); - expect(auths).toEqual([{ provider: "zai", token: "profile-zai-key" }]); }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: undefined, - }, - ); + expected: [{ provider: "zai", token: "profile-zai-key" }], + }); }); it("ignores invalid legacy z-ai auth files", async () => { - await withSuiteHome( - async (home) => { + await expectResolvedAuthsFromSuiteHome({ + providers: ["zai"], + setup: async (home) => { await writeLegacyPiAuth(home, "{not-json"); - const auths = await resolveProviderAuths({ - providers: ["zai"], - }); - expect(auths).toEqual([]); }, - { - ZAI_API_KEY: undefined, - Z_AI_API_KEY: undefined, - }, - ); + expected: [], + }); }); it("discovers oauth provider from config but skips mismatched profile providers", async () => {