mirror of https://github.com/openclaw/openclaw.git
test: simplify provider auth normalization coverage
This commit is contained in:
parent
91d4f5cd2f
commit
572df97179
|
|
@ -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<string, string | undefined>;
|
||||
|
||||
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<typeof resolveProviderAuths>[0]["providers"];
|
||||
expected: Awaited<ReturnType<typeof resolveProviderAuths>>;
|
||||
env?: Record<string, string | undefined>;
|
||||
setup?: (home: string) => Promise<void>;
|
||||
}) {
|
||||
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 () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue