refactor(test): centralize auth test env lifecycle cleanup

This commit is contained in:
Peter Steinberger
2026-02-16 16:09:22 +00:00
parent 9a1e168685
commit 110b1cf46f
5 changed files with 48 additions and 49 deletions

View File

@@ -1,9 +1,8 @@
import fs from "node:fs/promises";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { WizardPrompter } from "../wizard/prompts.js";
import { captureEnv } from "../test-utils/env.js";
import { applyAuthChoiceHuggingface } from "./auth-choice.apply.huggingface.js";
import {
createAuthTestLifecycle,
createExitThrowingRuntime,
createWizardPrompter,
readAuthProfilesForAgent,
@@ -26,18 +25,17 @@ function createHuggingfacePrompter(params: {
}
describe("applyAuthChoiceHuggingface", () => {
const envSnapshot = captureEnv([
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
"PI_CODING_AGENT_DIR",
"HF_TOKEN",
"HUGGINGFACE_HUB_TOKEN",
]);
let tempStateDir: string | null = null;
async function setupTempState() {
const env = await setupAuthTestEnv("openclaw-hf-");
tempStateDir = env.stateDir;
lifecycle.setStateDir(env.stateDir);
return env.agentDir;
}
@@ -48,11 +46,7 @@ describe("applyAuthChoiceHuggingface", () => {
}
afterEach(async () => {
if (tempStateDir) {
await fs.rm(tempStateDir, { recursive: true, force: true });
tempStateDir = null;
}
envSnapshot.restore();
await lifecycle.cleanup();
});
it("returns null when authChoice is not huggingface-api-key", async () => {

View File

@@ -2,7 +2,6 @@ import fs from "node:fs/promises";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { WizardPrompter } from "../wizard/prompts.js";
import type { AuthChoice } from "./onboard-types.js";
import { captureEnv } from "../test-utils/env.js";
import { applyAuthChoice, resolvePreferredProviderForAuthChoice } from "./auth-choice.js";
import {
MINIMAX_CN_API_BASE_URL,
@@ -11,6 +10,7 @@ import {
} from "./onboard-auth.js";
import {
authProfilePathForAgent,
createAuthTestLifecycle,
createExitThrowingRuntime,
createWizardPrompter,
readAuthProfilesForAgent,
@@ -43,7 +43,7 @@ type StoredAuthProfile = {
};
describe("applyAuthChoice", () => {
const envSnapshot = captureEnv([
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
"PI_CODING_AGENT_DIR",
@@ -57,10 +57,9 @@ describe("applyAuthChoice", () => {
"SSH_TTY",
"CHUTES_CLIENT_ID",
]);
let tempStateDir: string | null = null;
async function setupTempState() {
const env = await setupAuthTestEnv("openclaw-auth-");
tempStateDir = env.stateDir;
lifecycle.setStateDir(env.stateDir);
}
function createPrompter(overrides: Partial<WizardPrompter>): WizardPrompter {
return createWizardPrompter(overrides, { defaultSelect: "" });
@@ -102,11 +101,7 @@ describe("applyAuthChoice", () => {
resolvePluginProviders.mockReset();
loginOpenAICodexOAuth.mockReset();
loginOpenAICodexOAuth.mockResolvedValue(null);
if (tempStateDir) {
await fs.rm(tempStateDir, { recursive: true, force: true });
tempStateDir = null;
}
envSnapshot.restore();
await lifecycle.cleanup();
});
it("does not throw when openai-codex oauth fails", async () => {

View File

@@ -1,9 +1,8 @@
import fs from "node:fs/promises";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { WizardPrompter } from "../wizard/prompts.js";
import { captureEnv } from "../test-utils/env.js";
import { applyAuthChoice } from "./auth-choice.js";
import {
createAuthTestLifecycle,
createExitThrowingRuntime,
createWizardPrompter,
readAuthProfilesForAgent,
@@ -16,17 +15,16 @@ function createPrompter(overrides: Partial<WizardPrompter>): WizardPrompter {
}
describe("applyAuthChoice (moonshot)", () => {
const envSnapshot = captureEnv([
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
"PI_CODING_AGENT_DIR",
"MOONSHOT_API_KEY",
]);
let tempStateDir: string | null = null;
async function setupTempState() {
const env = await setupAuthTestEnv("openclaw-auth-");
tempStateDir = env.stateDir;
lifecycle.setStateDir(env.stateDir);
delete process.env.MOONSHOT_API_KEY;
}
@@ -37,11 +35,7 @@ describe("applyAuthChoice (moonshot)", () => {
}
afterEach(async () => {
if (tempStateDir) {
await fs.rm(tempStateDir, { recursive: true, force: true });
tempStateDir = null;
}
envSnapshot.restore();
await lifecycle.cleanup();
});
it("keeps the .cn baseUrl when setDefaultModel is false", async () => {

View File

@@ -2,7 +2,6 @@ import type { OAuthCredentials } from "@mariozechner/pi-ai";
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { captureEnv } from "../test-utils/env.js";
import {
applyAuthProfileConfig,
applyLitellmProviderConfig,
@@ -29,7 +28,11 @@ import {
ZAI_CODING_CN_BASE_URL,
ZAI_GLOBAL_BASE_URL,
} from "./onboard-auth.js";
import { readAuthProfilesForAgent, setupAuthTestEnv } from "./test-wizard-helpers.js";
import {
createAuthTestLifecycle,
readAuthProfilesForAgent,
setupAuthTestEnv,
} from "./test-wizard-helpers.js";
function createLegacyProviderConfig(params: {
providerId: string;
@@ -62,25 +65,20 @@ function createLegacyProviderConfig(params: {
}
describe("writeOAuthCredentials", () => {
const envSnapshot = captureEnv([
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
"PI_CODING_AGENT_DIR",
"OPENCLAW_OAUTH_DIR",
]);
let tempStateDir: string | null = null;
afterEach(async () => {
if (tempStateDir) {
await fs.rm(tempStateDir, { recursive: true, force: true });
tempStateDir = null;
}
envSnapshot.restore();
await lifecycle.cleanup();
});
it("writes auth-profiles.json under OPENCLAW_AGENT_DIR when set", async () => {
const env = await setupAuthTestEnv("openclaw-oauth-");
tempStateDir = env.stateDir;
lifecycle.setStateDir(env.stateDir);
const creds = {
refresh: "refresh-token",
@@ -100,30 +98,25 @@ describe("writeOAuthCredentials", () => {
});
await expect(
fs.readFile(path.join(tempStateDir, "agents", "main", "agent", "auth-profiles.json"), "utf8"),
fs.readFile(path.join(env.stateDir, "agents", "main", "agent", "auth-profiles.json"), "utf8"),
).rejects.toThrow();
});
});
describe("setMinimaxApiKey", () => {
const envSnapshot = captureEnv([
const lifecycle = createAuthTestLifecycle([
"OPENCLAW_STATE_DIR",
"OPENCLAW_AGENT_DIR",
"PI_CODING_AGENT_DIR",
]);
let tempStateDir: string | null = null;
afterEach(async () => {
if (tempStateDir) {
await fs.rm(tempStateDir, { recursive: true, force: true });
tempStateDir = null;
}
envSnapshot.restore();
await lifecycle.cleanup();
});
it("writes to OPENCLAW_AGENT_DIR when set", async () => {
const env = await setupAuthTestEnv("openclaw-minimax-", { agentSubdir: "custom-agent" });
tempStateDir = env.stateDir;
lifecycle.setStateDir(env.stateDir);
await setMinimaxApiKey("sk-minimax-test");
@@ -137,7 +130,7 @@ describe("setMinimaxApiKey", () => {
});
await expect(
fs.readFile(path.join(tempStateDir, "agents", "main", "agent", "auth-profiles.json"), "utf8"),
fs.readFile(path.join(env.stateDir, "agents", "main", "agent", "auth-profiles.json"), "utf8"),
).rejects.toThrow();
});
});

View File

@@ -4,6 +4,7 @@ import { vi } from "vitest";
import type { RuntimeEnv } from "../runtime.js";
import type { WizardPrompter } from "../wizard/prompts.js";
import { makeTempWorkspace } from "../test-helpers/workspace.js";
import { captureEnv } from "../test-utils/env.js";
export const noopAsync = async () => {};
export const noop = () => {};
@@ -51,6 +52,28 @@ export async function setupAuthTestEnv(
return { stateDir, agentDir };
}
export type AuthTestLifecycle = {
setStateDir: (stateDir: string) => void;
cleanup: () => Promise<void>;
};
export function createAuthTestLifecycle(envKeys: string[]): AuthTestLifecycle {
const envSnapshot = captureEnv(envKeys);
let stateDir: string | null = null;
return {
setStateDir(nextStateDir: string) {
stateDir = nextStateDir;
},
async cleanup() {
if (stateDir) {
await fs.rm(stateDir, { recursive: true, force: true });
stateDir = null;
}
envSnapshot.restore();
},
};
}
export function requireOpenClawAgentDir(): string {
const agentDir = process.env.OPENCLAW_AGENT_DIR;
if (!agentDir) {