From cf26082e4dc439a63f7a3e7ad0ff6a46a32e37a5 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Fri, 3 Jul 2026 14:05:26 -0400 Subject: [PATCH] test: clean up isolated config homes after integration runs Addresses Greptile's review note on #506: the per-file XDG_CONFIG_HOME temp dirs were created at module scope and never removed. Bun's test runner never emits process 'exit', so the helper exports an explicit cleanupTestConfigHomes() that each consumer registers via afterAll. Co-Authored-By: Claude Fable 5 --- .changeset/config-home-sweep.md | 2 ++ test/helpers/config-home.ts | 22 ++++++++++++++++++++-- test/session/broker-e2e.test.ts | 6 ++++-- test/session/cli.test.ts | 6 ++++-- test/session/daemon.test.ts | 6 ++++-- test/smoke/tty.test.ts | 6 ++++-- 6 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 .changeset/config-home-sweep.md diff --git a/.changeset/config-home-sweep.md b/.changeset/config-home-sweep.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/config-home-sweep.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/test/helpers/config-home.ts b/test/helpers/config-home.ts index 531683eb..bcdd3a14 100644 --- a/test/helpers/config-home.ts +++ b/test/helpers/config-home.ts @@ -1,12 +1,30 @@ -import { mkdtempSync } from "node:fs"; +import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; +const createdDirs: string[] = []; + /** * Create an empty XDG_CONFIG_HOME for spawned hunk processes so integration tests assert * against built-in defaults instead of the developer's ambient ~/.config/hunk/config.toml. * hunk resolves XDG_CONFIG_HOME ahead of platform defaults, so this isolates every OS. + * + * Callers create the dir at module scope, so pair it with + * `afterAll(cleanupTestConfigHomes)` — Bun's test runner does not emit `process.on("exit")`, + * so the helper cannot sweep after itself. */ export function createTestConfigHome(prefix = "hunk-test-config-") { - return mkdtempSync(join(tmpdir(), prefix)); + const dir = mkdtempSync(join(tmpdir(), prefix)); + createdDirs.push(dir); + return dir; +} + +/** Remove every config home this module created; safe to call from multiple test files. */ +export function cleanupTestConfigHomes() { + while (createdDirs.length > 0) { + const dir = createdDirs.pop(); + if (dir) { + rmSync(dir, { recursive: true, force: true }); + } + } } diff --git a/test/session/broker-e2e.test.ts b/test/session/broker-e2e.test.ts index aad780fd..1b016975 100644 --- a/test/session/broker-e2e.test.ts +++ b/test/session/broker-e2e.test.ts @@ -1,14 +1,16 @@ -import { afterEach, describe, expect, test } from "bun:test"; +import { afterAll, afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { createServer } from "node:http"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createTestConfigHome } from "../helpers/config-home"; +import { cleanupTestConfigHomes, createTestConfigHome } from "../helpers/config-home"; const repoRoot = process.cwd(); const sourceEntrypoint = join(repoRoot, "src/main.tsx"); // Spawned hunk processes must assert built-in defaults, not the developer's ambient user config. const testConfigHome = createTestConfigHome(); + +afterAll(cleanupTestConfigHomes); const tempDirs: string[] = []; const ttyToolsAvailable = Bun.spawnSync(["bash", "-lc", "command -v script >/dev/null && command -v timeout >/dev/null"], { diff --git a/test/session/cli.test.ts b/test/session/cli.test.ts index 9ebe3ff6..5f781d4d 100644 --- a/test/session/cli.test.ts +++ b/test/session/cli.test.ts @@ -1,13 +1,15 @@ -import { afterEach, describe, expect, test } from "bun:test"; +import { afterAll, afterEach, describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createTestConfigHome } from "../helpers/config-home"; +import { cleanupTestConfigHomes, createTestConfigHome } from "../helpers/config-home"; const repoRoot = process.cwd(); const sourceEntrypoint = join(repoRoot, "src/main.tsx"); // Spawned hunk processes must assert built-in defaults, not the developer's ambient user config. const testConfigHome = createTestConfigHome(); + +afterAll(cleanupTestConfigHomes); const tempDirs: string[] = []; const ttyToolsAvailable = Bun.spawnSync(["bash", "-lc", "command -v script >/dev/null && command -v timeout >/dev/null"], { diff --git a/test/session/daemon.test.ts b/test/session/daemon.test.ts index 61b1980b..f559d30d 100644 --- a/test/session/daemon.test.ts +++ b/test/session/daemon.test.ts @@ -1,11 +1,13 @@ -import { afterEach, describe, expect, test } from "bun:test"; +import { afterAll, afterEach, describe, expect, test } from "bun:test"; import type { Subprocess } from "bun"; import { createServer } from "node:net"; -import { createTestConfigHome } from "../helpers/config-home"; +import { cleanupTestConfigHomes, createTestConfigHome } from "../helpers/config-home"; const repoRoot = process.cwd(); // Spawned hunk processes must assert built-in defaults, not the developer's ambient user config. const testConfigHome = createTestConfigHome(); + +afterAll(cleanupTestConfigHomes); const spawned: Subprocess[] = []; async function reserveLoopbackPort() { diff --git a/test/smoke/tty.test.ts b/test/smoke/tty.test.ts index e541dca2..bf361818 100644 --- a/test/smoke/tty.test.ts +++ b/test/smoke/tty.test.ts @@ -1,13 +1,15 @@ -import { afterEach, describe, expect, setDefaultTimeout, test } from "bun:test"; +import { afterAll, afterEach, describe, expect, setDefaultTimeout, test } from "bun:test"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createTestConfigHome } from "../helpers/config-home"; +import { cleanupTestConfigHomes, createTestConfigHome } from "../helpers/config-home"; const repoRoot = process.cwd(); const sourceEntrypoint = join(repoRoot, "src/main.tsx"); // Spawned hunk processes must assert built-in defaults, not the developer's ambient user config. const testConfigHome = createTestConfigHome(); + +afterAll(cleanupTestConfigHomes); const tempDirs: string[] = []; const enableTtySmokeTests = process.env.HUNK_RUN_TTY_SMOKE === "1"; if (enableTtySmokeTests) {