From e70e6eed4ec695c7ea7a01b09ec27853485b6a6f Mon Sep 17 00:00:00 2001 From: Michael Ramos Date: Mon, 28 Sep 2026 08:25:52 -0700 Subject: [PATCH] test: sandbox the data dir when tests run from a package directory Bun reads only the bunfig.toml in the directory bun test runs from, so a run from apps/pi-extension or packages/server skipped the root preloads and wrote history, feedback and submission records into the real ~/.plannotator. Mirror the root [test] preloads in every apps/* and packages/* directory that has tests, guarded by tests/package-bunfig.test.ts. Also stop storage.test.ts creating ~/.plannotator/test-plans in the real home. --- apps/amp-plugin/bunfig.toml | 6 ++++ apps/guides-show/bunfig.toml | 6 ++++ apps/hook/bunfig.toml | 6 ++++ apps/marketing/bunfig.toml | 6 ++++ apps/opencode-plugin/bunfig.toml | 6 ++++ apps/paste-service/bunfig.toml | 6 ++++ apps/pi-extension/bunfig.toml | 6 ++++ apps/skills/bunfig.toml | 6 ++++ apps/vscode-extension/bunfig.toml | 6 ++++ packages/ai/bunfig.toml | 6 ++++ packages/core/bunfig.toml | 6 ++++ packages/editor/bunfig.toml | 6 ++++ packages/guide-viewer/bunfig.toml | 6 ++++ packages/review-editor/bunfig.toml | 6 ++++ packages/server/bunfig.toml | 6 ++++ packages/server/storage.test.ts | 8 +++-- packages/shared/bunfig.toml | 6 ++++ packages/ui/bunfig.toml | 6 ++++ tests/package-bunfig.test.ts | 55 ++++++++++++++++++++++++++++++ 19 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 apps/amp-plugin/bunfig.toml create mode 100644 apps/guides-show/bunfig.toml create mode 100644 apps/hook/bunfig.toml create mode 100644 apps/marketing/bunfig.toml create mode 100644 apps/opencode-plugin/bunfig.toml create mode 100644 apps/paste-service/bunfig.toml create mode 100644 apps/pi-extension/bunfig.toml create mode 100644 apps/skills/bunfig.toml create mode 100644 apps/vscode-extension/bunfig.toml create mode 100644 packages/ai/bunfig.toml create mode 100644 packages/core/bunfig.toml create mode 100644 packages/editor/bunfig.toml create mode 100644 packages/guide-viewer/bunfig.toml create mode 100644 packages/review-editor/bunfig.toml create mode 100644 packages/server/bunfig.toml create mode 100644 packages/shared/bunfig.toml create mode 100644 packages/ui/bunfig.toml create mode 100644 tests/package-bunfig.test.ts diff --git a/apps/amp-plugin/bunfig.toml b/apps/amp-plugin/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/amp-plugin/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/guides-show/bunfig.toml b/apps/guides-show/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/guides-show/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/hook/bunfig.toml b/apps/hook/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/hook/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/marketing/bunfig.toml b/apps/marketing/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/marketing/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/opencode-plugin/bunfig.toml b/apps/opencode-plugin/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/opencode-plugin/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/paste-service/bunfig.toml b/apps/paste-service/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/paste-service/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/pi-extension/bunfig.toml b/apps/pi-extension/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/pi-extension/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/skills/bunfig.toml b/apps/skills/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/skills/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/apps/vscode-extension/bunfig.toml b/apps/vscode-extension/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/apps/vscode-extension/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/ai/bunfig.toml b/packages/ai/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/ai/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/core/bunfig.toml b/packages/core/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/core/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/editor/bunfig.toml b/packages/editor/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/editor/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/guide-viewer/bunfig.toml b/packages/guide-viewer/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/guide-viewer/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/review-editor/bunfig.toml b/packages/review-editor/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/review-editor/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/server/bunfig.toml b/packages/server/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/server/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/server/storage.test.ts b/packages/server/storage.test.ts index 8bdee91f2..9d7c2c4d1 100644 --- a/packages/server/storage.test.ts +++ b/packages/server/storage.test.ts @@ -6,7 +6,7 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, rmSync, readFileSync, readdirSync } from "node:fs"; -import { tmpdir } from "node:os"; +import { homedir, tmpdir } from "node:os"; import { join } from "node:path"; import { generateSlug, getPlanDir, savePlan, saveToHistory, getPlanVersion, getVersionCount, listVersions } from "./storage"; @@ -61,9 +61,11 @@ describe("getPlanDir", () => { }); test("expands tilde in custom path", () => { - const result = getPlanDir("~/.plannotator/test-plans"); + // getPlanDir mkdirs its result, and os.homedir() ignores a HOME override, so + // expand bare "~": the real home already exists and nothing is created in it. + const result = getPlanDir("~"); expect(result).not.toContain("~"); - expect(result).toMatch(/\.plannotator\/test-plans$/); + expect(result).toBe(homedir()); }); test("uses default when no custom path", () => { diff --git a/packages/shared/bunfig.toml b/packages/shared/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/shared/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/packages/ui/bunfig.toml b/packages/ui/bunfig.toml new file mode 100644 index 000000000..e7d35e53a --- /dev/null +++ b/packages/ui/bunfig.toml @@ -0,0 +1,6 @@ +# Bun reads only the bunfig.toml in the directory `bun test` runs from, so the +# root preloads are mirrored here for runs from this package directory. Keep in +# step with the root bunfig.toml [test] section (guarded by +# tests/package-bunfig.test.ts). +[test] +preload = ["../../tests/setup/feedback-archive-off.ts", "../../packages/ui/test-setup/happy-dom.ts"] diff --git a/tests/package-bunfig.test.ts b/tests/package-bunfig.test.ts new file mode 100644 index 000000000..c45b3cbd9 --- /dev/null +++ b/tests/package-bunfig.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, test } from "bun:test"; +import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { join, relative, resolve } from "node:path"; + +/** + * Bun reads only the bunfig.toml in the directory `bun test` runs from. Without + * a package-level copy, `bun test` inside a package skips the root preloads and + * tests write drafts, history, and feedback into the contributor's real + * ~/.plannotator. Catches a package that gains tests without a bunfig, or a + * package bunfig that drifts from the root preload list. + */ +const repoRoot = resolve(import.meta.dir, ".."); + +function readPreload(bunfigPath: string): string[] { + const parsed = Bun.TOML.parse(readFileSync(bunfigPath, "utf-8")) as { + test?: { preload?: string[] }; + }; + return parsed.test?.preload ?? []; +} + +function hasTestFiles(dir: string): boolean { + for (const entry of readdirSync(dir)) { + if (entry === "node_modules" || entry === "dist" || entry.startsWith(".")) continue; + const full = join(dir, entry); + if (statSync(full).isDirectory()) { + if (hasTestFiles(full)) return true; + } else if (/\.test\.tsx?$/.test(entry)) { + return true; + } + } + return false; +} + +const rootPreload = readPreload(join(repoRoot, "bunfig.toml")).map((p) => resolve(repoRoot, p)); + +const packageDirs = ["apps", "packages"].flatMap((group) => + readdirSync(join(repoRoot, group)) + .map((name) => join(repoRoot, group, name)) + .filter((dir) => statSync(dir).isDirectory() && hasTestFiles(dir)), +); + +describe("package-directory bunfig.toml", () => { + test("root preload sandboxes the data dir", () => { + expect(rootPreload).toContain(resolve(repoRoot, "tests/setup/feedback-archive-off.ts")); + }); + + for (const dir of packageDirs) { + const label = relative(repoRoot, dir); + test(`${label} mirrors the root test preloads`, () => { + const bunfig = join(dir, "bunfig.toml"); + expect(existsSync(bunfig)).toBe(true); + expect(readPreload(bunfig).map((p) => resolve(dir, p))).toEqual(rootPreload); + }); + } +});