test: speed up auth profile session override

This commit is contained in:
Peter Steinberger
2026-04-18 19:57:33 +01:00
parent 796f272f7d
commit f168a62068

View File

@@ -1,18 +1,77 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { SessionEntry } from "../../config/sessions.js";
import { withStateDirEnv } from "../../test-helpers/state-dir-env.js";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { SessionEntry } from "../../config/sessions/types.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolveSessionAuthProfileOverride } from "./session-override.js";
import type { AuthProfileStore } from "./types.js";
vi.mock("../../plugins/provider-runtime.js", () => ({
resolveExternalAuthProfilesWithPlugins: () => [],
const authStoreMocks = vi.hoisted(() => {
const normalizeProvider = (value: string) => value.toLowerCase().replace(/[^a-z0-9]+/g, "");
const state: { hasSource: boolean; store: AuthProfileStore } = {
hasSource: false,
store: { version: 1, profiles: {} },
};
return {
state,
ensureAuthProfileStore: vi.fn(() => state.store),
hasAnyAuthProfileStoreSource: vi.fn(() => state.hasSource),
isProfileInCooldown: vi.fn(() => false),
reset() {
state.hasSource = false;
state.store = { version: 1, profiles: {} };
},
resolveAuthProfileOrder: vi.fn(
({ store, provider }: { store: AuthProfileStore; provider: string }) => {
const providerKey = normalizeProvider(provider);
const ordered = Object.entries(store.order ?? {}).find(
([key]) => normalizeProvider(key) === providerKey,
)?.[1];
if (ordered) {
return ordered;
}
return Object.entries(store.profiles)
.filter(([, profile]) => normalizeProvider(profile.provider) === providerKey)
.map(([profileId]) => profileId);
},
),
};
});
vi.mock("./store.js", () => ({
ensureAuthProfileStore: authStoreMocks.ensureAuthProfileStore,
hasAnyAuthProfileStoreSource: authStoreMocks.hasAnyAuthProfileStoreSource,
}));
async function writeAuthStore(agentDir: string) {
const authPath = path.join(agentDir, "auth-profiles.json");
const payload = {
vi.mock("./order.js", () => ({
resolveAuthProfileOrder: authStoreMocks.resolveAuthProfileOrder,
}));
vi.mock("./usage.js", () => ({
isProfileInCooldown: authStoreMocks.isProfileInCooldown,
}));
async function withAuthStateDir<T>(run: (params: { stateDir: string }) => Promise<T>): Promise<T> {
const previousStateDir = process.env.OPENCLAW_STATE_DIR;
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
const stateDir = path.join(tempRoot, "state");
process.env.OPENCLAW_STATE_DIR = stateDir;
try {
await fs.mkdir(stateDir, { recursive: true });
return await run({ stateDir });
} finally {
if (previousStateDir === undefined) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = previousStateDir;
}
await fs.rm(tempRoot, { recursive: true, force: true });
}
}
function createAuthStore(): AuthProfileStore {
return {
version: 1,
profiles: {
"zai:work": { type: "api_key", provider: "zai", key: "sk-test" },
@@ -21,38 +80,30 @@ async function writeAuthStore(agentDir: string) {
zai: ["zai:work"],
},
};
await fs.writeFile(authPath, JSON.stringify(payload), "utf-8");
}
async function writeAuthStoreWithProfiles(
agentDir: string,
params: {
profiles: Record<string, { type: "api_key"; provider: string; key: string }>;
order?: Record<string, string[]>;
},
) {
const authPath = path.join(agentDir, "auth-profiles.json");
await fs.writeFile(
authPath,
JSON.stringify(
{
version: 1,
profiles: params.profiles,
...(params.order ? { order: params.order } : {}),
},
null,
2,
),
"utf-8",
);
function createAuthStoreWithProfiles(params: {
profiles: Record<string, { type: "api_key"; provider: string; key: string }>;
order?: Record<string, string[]>;
}): AuthProfileStore {
return {
version: 1,
profiles: params.profiles,
...(params.order ? { order: params.order } : {}),
};
}
const TEST_PRIMARY_PROFILE_ID = "openai-codex:primary@example.test";
const TEST_SECONDARY_PROFILE_ID = "openai-codex:secondary@example.test";
describe("resolveSessionAuthProfileOverride", () => {
afterEach(() => {
authStoreMocks.reset();
vi.clearAllMocks();
});
it("returns early when no auth sources exist", async () => {
await withStateDirEnv("openclaw-auth-", async ({ stateDir }) => {
await withAuthStateDir(async ({ stateDir }) => {
const agentDir = path.join(stateDir, "agent");
await fs.mkdir(agentDir, { recursive: true });
@@ -74,6 +125,7 @@ describe("resolveSessionAuthProfileOverride", () => {
});
expect(resolved).toBeUndefined();
expect(authStoreMocks.ensureAuthProfileStore).not.toHaveBeenCalled();
await expect(fs.access(path.join(agentDir, "auth-profiles.json"))).rejects.toMatchObject({
code: "ENOENT",
});
@@ -81,10 +133,11 @@ describe("resolveSessionAuthProfileOverride", () => {
});
it("keeps user override when provider alias differs", async () => {
await withStateDirEnv("openclaw-auth-", async ({ stateDir }) => {
await withAuthStateDir(async ({ stateDir }) => {
const agentDir = path.join(stateDir, "agent");
await fs.mkdir(agentDir, { recursive: true });
await writeAuthStore(agentDir);
authStoreMocks.state.hasSource = true;
authStoreMocks.state.store = createAuthStore();
const sessionEntry: SessionEntry = {
sessionId: "s1",
@@ -111,10 +164,11 @@ describe("resolveSessionAuthProfileOverride", () => {
});
it("keeps explicit user override when stored order prefers another profile", async () => {
await withStateDirEnv("openclaw-auth-", async ({ stateDir }) => {
await withAuthStateDir(async ({ stateDir }) => {
const agentDir = path.join(stateDir, "agent");
await fs.mkdir(agentDir, { recursive: true });
await writeAuthStoreWithProfiles(agentDir, {
authStoreMocks.state.hasSource = true;
authStoreMocks.state.store = createAuthStoreWithProfiles({
profiles: {
[TEST_PRIMARY_PROFILE_ID]: {
type: "api_key",