refactor(test): use env snapshots in setup hooks

This commit is contained in:
Peter Steinberger
2026-02-21 13:14:49 +00:00
parent 7724abeee0
commit 992b7e5577
4 changed files with 44 additions and 41 deletions

View File

@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { captureEnv } from "../test-utils/env.js";
const note = vi.hoisted(() => vi.fn());
@@ -13,21 +14,17 @@ import { noteSessionLockHealth } from "./doctor-session-locks.js";
describe("noteSessionLockHealth", () => {
let root: string;
let prevStateDir: string | undefined;
let envSnapshot: ReturnType<typeof captureEnv>;
beforeEach(async () => {
note.mockReset();
prevStateDir = process.env.OPENCLAW_STATE_DIR;
envSnapshot = captureEnv(["OPENCLAW_STATE_DIR"]);
root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-doctor-locks-"));
process.env.OPENCLAW_STATE_DIR = root;
});
afterEach(async () => {
if (prevStateDir === undefined) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = prevStateDir;
}
envSnapshot.restore();
await fs.rm(root, { recursive: true, force: true });
});

View File

@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { captureEnv } from "../test-utils/env.js";
import {
consumeRestartSentinel,
formatRestartSentinelMessage,
@@ -12,21 +13,17 @@ import {
} from "./restart-sentinel.js";
describe("restart sentinel", () => {
let prevStateDir: string | undefined;
let envSnapshot: ReturnType<typeof captureEnv>;
let tempDir: string;
beforeEach(async () => {
prevStateDir = process.env.OPENCLAW_STATE_DIR;
envSnapshot = captureEnv(["OPENCLAW_STATE_DIR"]);
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-sentinel-"));
process.env.OPENCLAW_STATE_DIR = tempDir;
});
afterEach(async () => {
if (prevStateDir) {
process.env.OPENCLAW_STATE_DIR = prevStateDir;
} else {
delete process.env.OPENCLAW_STATE_DIR;
}
envSnapshot.restore();
await fs.rm(tempDir, { recursive: true, force: true });
});

View File

@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { captureEnv } from "../test-utils/env.js";
import type { UpdateCheckResult } from "./update-check.js";
vi.mock("./openclaw-root.js", () => ({
@@ -38,12 +39,7 @@ describe("update-startup", () => {
let suiteRoot = "";
let suiteCase = 0;
let tempDir: string;
let prevStateDir: string | undefined;
let prevNodeEnv: string | undefined;
let prevVitest: string | undefined;
let hadStateDir = false;
let hadNodeEnv = false;
let hadVitest = false;
let envSnapshot: ReturnType<typeof captureEnv>;
let resolveOpenClawPackageRoot: (typeof import("./openclaw-root.js"))["resolveOpenClawPackageRoot"];
let checkUpdateStatus: (typeof import("./update-check.js"))["checkUpdateStatus"];
@@ -62,17 +58,12 @@ describe("update-startup", () => {
vi.setSystemTime(new Date("2026-01-17T10:00:00Z"));
tempDir = path.join(suiteRoot, `case-${++suiteCase}`);
await fs.mkdir(tempDir);
hadStateDir = Object.prototype.hasOwnProperty.call(process.env, "OPENCLAW_STATE_DIR");
prevStateDir = process.env.OPENCLAW_STATE_DIR;
envSnapshot = captureEnv(["OPENCLAW_STATE_DIR", "NODE_ENV", "VITEST"]);
process.env.OPENCLAW_STATE_DIR = tempDir;
hadNodeEnv = Object.prototype.hasOwnProperty.call(process.env, "NODE_ENV");
prevNodeEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "test";
// Ensure update checks don't short-circuit in test mode.
hadVitest = Object.prototype.hasOwnProperty.call(process.env, "VITEST");
prevVitest = process.env.VITEST;
delete process.env.VITEST;
// Perf: load mocked modules once (after timers/env are set up).
@@ -91,21 +82,7 @@ describe("update-startup", () => {
afterEach(async () => {
vi.useRealTimers();
if (hadStateDir) {
process.env.OPENCLAW_STATE_DIR = prevStateDir;
} else {
delete process.env.OPENCLAW_STATE_DIR;
}
if (hadNodeEnv) {
process.env.NODE_ENV = prevNodeEnv;
} else {
delete process.env.NODE_ENV;
}
if (hadVitest) {
process.env.VITEST = prevVitest;
} else {
delete process.env.VITEST;
}
envSnapshot.restore();
resetUpdateAvailableStateForTest();
});

View File

@@ -40,6 +40,22 @@ describe("env test utils", () => {
expect(process.env[key]).toBe(prev);
});
it("withEnv can delete a key only inside callback", () => {
const key = "OPENCLAW_ENV_TEST_SYNC_DELETE";
const prev = process.env[key];
process.env[key] = "outer";
const seen = withEnv({ [key]: undefined }, () => process.env[key]);
expect(seen).toBeUndefined();
expect(process.env[key]).toBe("outer");
if (prev === undefined) {
delete process.env[key];
} else {
process.env[key] = prev;
}
});
it("withEnvAsync restores values when callback throws", async () => {
const key = "OPENCLAW_ENV_TEST_ASYNC";
const prev = process.env[key];
@@ -63,4 +79,20 @@ describe("env test utils", () => {
expect(seen).toBe("inside");
expect(process.env[key]).toBe(prev);
});
it("withEnvAsync can delete a key only inside callback", async () => {
const key = "OPENCLAW_ENV_TEST_ASYNC_DELETE";
const prev = process.env[key];
process.env[key] = "outer";
const seen = await withEnvAsync({ [key]: undefined }, async () => process.env[key]);
expect(seen).toBeUndefined();
expect(process.env[key]).toBe("outer");
if (prev === undefined) {
delete process.env[key];
} else {
process.env[key] = prev;
}
});
});