diff --git a/src/agents/sandbox-skills.e2e.test.ts b/src/agents/sandbox-skills.e2e.test.ts index ae37f2a9f..0280c5d52 100644 --- a/src/agents/sandbox-skills.e2e.test.ts +++ b/src/agents/sandbox-skills.e2e.test.ts @@ -3,6 +3,7 @@ import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; +import { captureFullEnv } from "../test-utils/env.js"; import { resolveSandboxContext } from "./sandbox.js"; vi.mock("./sandbox/docker.js", () => ({ @@ -27,30 +28,15 @@ async function writeSkill(params: { dir: string; name: string; description: stri ); } -function restoreEnv(snapshot: Record) { - for (const key of Object.keys(process.env)) { - if (!(key in snapshot)) { - delete process.env[key]; - } - } - for (const [key, value] of Object.entries(snapshot)) { - if (value === undefined) { - delete process.env[key]; - } else { - process.env[key] = value; - } - } -} - describe("sandbox skill mirroring", () => { - let envSnapshot: Record; + let envSnapshot: ReturnType; beforeEach(() => { - envSnapshot = { ...process.env }; + envSnapshot = captureFullEnv(); }); afterEach(() => { - restoreEnv(envSnapshot); + envSnapshot.restore(); }); const runContext = async (workspaceAccess: "none" | "ro") => { diff --git a/src/infra/process-respawn.test.ts b/src/infra/process-respawn.test.ts index d7ea3649a..324282ec9 100644 --- a/src/infra/process-respawn.test.ts +++ b/src/infra/process-respawn.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it, vi } from "vitest"; +import { captureFullEnv } from "../test-utils/env.js"; const spawnMock = vi.hoisted(() => vi.fn()); @@ -8,27 +9,12 @@ vi.mock("node:child_process", () => ({ import { restartGatewayProcessWithFreshPid } from "./process-respawn.js"; -const originalEnv = { ...process.env }; const originalArgv = [...process.argv]; const originalExecArgv = [...process.execArgv]; - -function restoreEnv() { - for (const key of Object.keys(process.env)) { - if (!(key in originalEnv)) { - delete process.env[key]; - } - } - for (const [key, value] of Object.entries(originalEnv)) { - if (value === undefined) { - delete process.env[key]; - } else { - process.env[key] = value; - } - } -} +const envSnapshot = captureFullEnv(); afterEach(() => { - restoreEnv(); + envSnapshot.restore(); process.argv = [...originalArgv]; process.execArgv = [...originalExecArgv]; spawnMock.mockReset(); diff --git a/src/media/store.test.ts b/src/media/store.test.ts index 5e7f510a8..642ab1c37 100644 --- a/src/media/store.test.ts +++ b/src/media/store.test.ts @@ -5,30 +5,21 @@ import path from "node:path"; import sharp from "sharp"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { isPathWithinBase } from "../../test/helpers/paths.js"; +import { captureEnv } from "../test-utils/env.js"; describe("media store", () => { let store: typeof import("./store.js"); let home = ""; - const envSnapshot: Record = {}; - - const snapshotEnv = () => { - for (const key of ["HOME", "USERPROFILE", "HOMEDRIVE", "HOMEPATH", "OPENCLAW_STATE_DIR"]) { - envSnapshot[key] = process.env[key]; - } - }; - - const restoreEnv = () => { - for (const [key, value] of Object.entries(envSnapshot)) { - if (value === undefined) { - delete process.env[key]; - } else { - process.env[key] = value; - } - } - }; + let envSnapshot: ReturnType; beforeAll(async () => { - snapshotEnv(); + envSnapshot = captureEnv([ + "HOME", + "USERPROFILE", + "HOMEDRIVE", + "HOMEPATH", + "OPENCLAW_STATE_DIR", + ]); home = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-home-")); process.env.HOME = home; process.env.USERPROFILE = home; @@ -45,7 +36,7 @@ describe("media store", () => { }); afterAll(async () => { - restoreEnv(); + envSnapshot.restore(); try { await fs.rm(home, { recursive: true, force: true }); } catch { diff --git a/src/test-utils/env.ts b/src/test-utils/env.ts index 9e813dcff..36c9b137f 100644 --- a/src/test-utils/env.ts +++ b/src/test-utils/env.ts @@ -17,6 +17,27 @@ export function captureEnv(keys: string[]) { }; } +export function captureFullEnv() { + const snapshot: Record = { ...process.env }; + + return { + restore() { + for (const key of Object.keys(process.env)) { + if (!(key in snapshot)) { + delete process.env[key]; + } + } + for (const [key, value] of Object.entries(snapshot)) { + if (value === undefined) { + delete process.env[key]; + } else { + process.env[key] = value; + } + } + }, + }; +} + export function withEnv(env: Record, fn: () => T): T { const snapshot = captureEnv(Object.keys(env)); try {