From 59318d9ff8396608923ccc483df71d068833bd82 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 7 Apr 2026 07:43:53 +0100 Subject: [PATCH] Tests: preserve isolated home across non-isolated files --- test/non-isolated-runner.ts | 32 ++++++++++++++++++++++++++++++++ test/setup-openclaw-runtime.ts | 9 +++++++-- test/setup.shared.ts | 7 +++++++ test/setup.ts | 7 +------ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/test/non-isolated-runner.ts b/test/non-isolated-runner.ts index 208d6f21cc5..89ef4d259ac 100644 --- a/test/non-isolated-runner.ts +++ b/test/non-isolated-runner.ts @@ -1,4 +1,5 @@ import fs from "node:fs"; +import path from "node:path"; import { TestRunner, type RunnerTestSuite, vi } from "vitest"; type EvaluatedModuleNode = { @@ -12,6 +13,15 @@ type EvaluatedModules = { idToModuleMap: Map; }; +const SHARED_TEST_SETUP = Symbol.for("openclaw.sharedTestSetup"); + +function getSharedTestHome(): string | undefined { + const globalState = globalThis as typeof globalThis & { + [SHARED_TEST_SETUP]?: { tempHome?: string }; + }; + return globalState[SHARED_TEST_SETUP]?.tempHome ?? process.env.OPENCLAW_TEST_HOME; +} + function resetEvaluatedModules(modules: EvaluatedModules, resetMocks: boolean) { const skipPaths = [ /\/vitest\/dist\//, @@ -31,9 +41,29 @@ function resetEvaluatedModules(modules: EvaluatedModules, resetMocks: boolean) { }); } +function restoreSharedTestHomeAfterEnvUnstub(testHomeRaw: string | undefined): void { + const testHome = testHomeRaw?.trim(); + if (!testHome) { + return; + } + + process.env.HOME = testHome; + process.env.USERPROFILE = testHome; + process.env.OPENCLAW_TEST_HOME = testHome; + delete process.env.OPENCLAW_CONFIG_PATH; + delete process.env.OPENCLAW_STATE_DIR; + delete process.env.OPENCLAW_AGENT_DIR; + delete process.env.PI_CODING_AGENT_DIR; + process.env.XDG_CONFIG_HOME = path.join(testHome, ".config"); + process.env.XDG_DATA_HOME = path.join(testHome, ".local", "share"); + process.env.XDG_STATE_HOME = path.join(testHome, ".local", "state"); + process.env.XDG_CACHE_HOME = path.join(testHome, ".cache"); +} + export default class OpenClawNonIsolatedRunner extends TestRunner { override onCollectStart(file: { filepath: string }) { super.onCollectStart(file); + restoreSharedTestHomeAfterEnvUnstub(getSharedTestHome()); const orderLogPath = process.env.OPENCLAW_VITEST_FILE_ORDER_LOG?.trim(); if (orderLogPath) { fs.appendFileSync(orderLogPath, `START ${file.filepath}\n`); @@ -59,7 +89,9 @@ export default class OpenClawNonIsolatedRunner extends TestRunner { } vi.restoreAllMocks(); vi.unstubAllGlobals(); + const testHome = getSharedTestHome(); vi.unstubAllEnvs(); + restoreSharedTestHomeAfterEnvUnstub(testHome); vi.clearAllMocks(); vi.resetModules(); this.moduleRunner?.mocker?.reset?.(); diff --git a/test/setup-openclaw-runtime.ts b/test/setup-openclaw-runtime.ts index 0ff654c1c14..5a402359af7 100644 --- a/test/setup-openclaw-runtime.ts +++ b/test/setup-openclaw-runtime.ts @@ -15,11 +15,13 @@ import { clearSessionStoreCaches } from "../src/config/sessions/store-cache.js"; import { drainSessionStoreLockQueuesForTest } from "../src/config/sessions/store-lock-state.js"; import { drainFileLockStateForTest, resetFileLockStateForTest } from "../src/infra/file-lock.js"; import type { OutboundSendDeps } from "../src/infra/outbound/deliver.js"; +import { clearPluginDiscoveryCache } from "../src/plugins/discovery.js"; +import { clearPluginManifestRegistryCache } from "../src/plugins/manifest-registry.js"; import type { PluginRegistry } from "../src/plugins/registry.js"; import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../src/plugins/runtime.js"; import { installSharedTestSetup } from "./setup.shared.js"; -const testEnv = installSharedTestSetup(); +installSharedTestSetup(); const WORKER_RUNTIME_STATE = Symbol.for("openclaw.testSetupRuntimeState"); type WorkerRuntimeState = { @@ -332,6 +334,8 @@ afterEach(async () => { resetContextWindowCacheForTest(); resetModelsJsonReadyCacheForTest(); resetSessionWriteLockStateForTest(); + clearPluginDiscoveryCache(); + clearPluginManifestRegistryCache(); installDefaultPluginRegistry(); }); @@ -339,5 +343,6 @@ afterAll(async () => { clearSessionStoreCaches(); await drainFileLockStateForTest(); await drainSessionWriteLockStateForTest(); - testEnv.cleanup(); + clearPluginDiscoveryCache(); + clearPluginManifestRegistryCache(); }); diff --git a/test/setup.shared.ts b/test/setup.shared.ts index f0bdbea7698..fd644b35d6e 100644 --- a/test/setup.shared.ts +++ b/test/setup.shared.ts @@ -11,6 +11,12 @@ vi.mock("@mariozechner/pi-ai", async () => { }; }); +vi.mock("@mariozechner/pi-ai/oauth", () => ({ + getOAuthApiKey: () => undefined, + getOAuthProviders: () => [], + loginOpenAICodex: vi.fn(), +})); + vi.mock("@mariozechner/clipboard", () => ({ availableFormats: () => [], getText: async () => "", @@ -87,6 +93,7 @@ export function installSharedTestSetup(options?: SharedTestSetupOptions): { delete globalState[SHARED_TEST_SETUP]; }, }; + process.once("exit", handle.cleanup); globalState[SHARED_TEST_SETUP] = handle; return handle; } diff --git a/test/setup.ts b/test/setup.ts index e6d989375b6..7595d6042a7 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,8 +1,3 @@ -import { afterAll } from "vitest"; import { installSharedTestSetup } from "./setup.shared.js"; -const testEnv = installSharedTestSetup(); - -afterAll(() => { - testEnv.cleanup(); -}); +installSharedTestSetup();