Files
openclaw/test/setup.shared.ts
Peter Steinberger 341c7250a4 test: release shared setup exit listener (#148404)
Summary:
- The PR unregisters the shared test environment’s exit callback during cleanup and moves existing imports to the top of the file.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head 148ad59708.
- Required merge gates passed before the squash merge.

Prepared head SHA: 148ad59708
Review: https://github.com/openclaw/openclaw/pull/148404#issuecomment-5668111160

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Approved-by: steipete
2026-09-15 01:55:36 +00:00

100 lines
3.1 KiB
TypeScript

// Shared test setup installs common Vitest mocks and cleanup behavior.
import { vi } from "vitest";
import { installProcessWarningFilter } from "../src/infra/warning-filter.js";
import { withIsolatedTestHome } from "./test-env.js";
const openAiCodexTokenRefreshTestHook = "__OPENCLAW_TEST_REFRESH_OPENAI_CODEX_TOKEN__";
type GlobalWithOpenAiCodexTokenRefreshTestHook = typeof globalThis & {
[openAiCodexTokenRefreshTestHook]?: ((...args: unknown[]) => unknown) | undefined;
};
vi.mock("../src/llm/oauth.js", () => ({
getOAuthApiKey: () => undefined,
getOAuthProviders: () => [],
loginOpenAICodex: vi.fn(),
refreshOpenAICodexToken: vi.fn((...args: unknown[]) =>
(globalThis as GlobalWithOpenAiCodexTokenRefreshTestHook)[openAiCodexTokenRefreshTestHook]?.(
...args,
),
),
}));
vi.mock("@mariozechner/clipboard", () => ({
availableFormats: () => [],
getText: async () => "",
setText: async () => {},
hasText: () => false,
getImageBinary: async () => [],
getImageBase64: async () => "",
setImageBinary: async () => {},
setImageBase64: async () => {},
hasImage: () => false,
getHtml: async () => "",
setHtml: async () => {},
hasHtml: () => false,
getRtf: async () => "",
setRtf: async () => {},
hasRtf: () => false,
clear: async () => {},
watch: () => {},
callThreadsafeFunction: () => {},
}));
// Ensure Vitest environment is properly set.
process.env.VITEST = "true";
// Tests frequently point bundled plugin discovery at temp fixture roots. Production still rejects
// arbitrary OPENCLAW_BUNDLED_PLUGINS_DIR overrides unless this Vitest-only opt-in is present.
process.env.OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR ??= "1";
// Vitest fork workers can load transitive lockfile helpers many times per worker.
// Raise listener budget to avoid noisy MaxListeners warnings and warning-stack overhead.
const TEST_PROCESS_MAX_LISTENERS = 256;
if (process.getMaxListeners() > 0 && process.getMaxListeners() < TEST_PROCESS_MAX_LISTENERS) {
process.setMaxListeners(TEST_PROCESS_MAX_LISTENERS);
}
type SharedTestSetupOptions = {
loadProfileEnv?: boolean;
};
const SHARED_TEST_SETUP = Symbol.for("openclaw.sharedTestSetup");
type SharedTestSetupHandle = {
cleanup: () => void;
tempHome: string;
};
export function installSharedTestSetup(options?: SharedTestSetupOptions): {
cleanup: () => void;
tempHome: string;
} {
const globalState = globalThis as typeof globalThis & {
[SHARED_TEST_SETUP]?: SharedTestSetupHandle;
};
const existing = globalState[SHARED_TEST_SETUP];
if (existing) {
return existing;
}
const testEnv = withIsolatedTestHome({
loadProfileEnv: options?.loadProfileEnv,
});
installProcessWarningFilter();
let cleaned = false;
const handle: SharedTestSetupHandle = {
tempHome: testEnv.tempHome,
cleanup: () => {
if (cleaned) {
return;
}
cleaned = true;
process.removeListener("exit", handle.cleanup);
testEnv.cleanup();
delete globalState[SHARED_TEST_SETUP];
},
};
process.once("exit", handle.cleanup);
globalState[SHARED_TEST_SETUP] = handle;
return handle;
}