From 06343337e2f85d1eec1058dce85de4b79fac588e Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 22 Sep 2026 23:57:47 +0000 Subject: [PATCH] Keep make test from collecting tests in nested checkouts (closes #25) vitest does not read .gitignore when finding tests, so a checkout nested under .claude/ had its whole test/ tree run as part of this suite. vitest.config.ts adds .claude/** to vitest's default excludes. The new packaging test plants a nested checkout in a temp directory and fails if vitest, run with this config, would collect it. Model: opus-5-5 --- TODO.md | 6 ++++ test/packaging/nested-checkout.test.ts | 50 ++++++++++++++++++++++++++ vitest.config.ts | 10 ++++++ 3 files changed, 66 insertions(+) create mode 100644 test/packaging/nested-checkout.test.ts create mode 100644 vitest.config.ts diff --git a/TODO.md b/TODO.md index 6543b80..a3b390e 100644 --- a/TODO.md +++ b/TODO.md @@ -18,6 +18,12 @@ Tag v1.0.0. # Completed Steps +- 2026-09-22: Stopped `make test` collecting tests from checkouts nested under + `.claude/` (issue 25). vitest ignores `.gitignore` when finding tests, so a + nested checkout ran the whole suite again; `vitest.config.ts` now adds + `.claude/**` to vitest's default excludes, and + `test/packaging/nested-checkout.test.ts` plants a nested checkout in a temp + directory and fails if vitest would collect it. - 2026-09-22: Dropped the deprecated `@types/libsodium-wrappers-sumo` stub from `devDependencies` (issue 27). It shipped no declarations; the types come from `libsodium-wrappers-sumo` itself. `yarn.lock` regenerated by `yarn remove`. diff --git a/test/packaging/nested-checkout.test.ts b/test/packaging/nested-checkout.test.ts new file mode 100644 index 0000000..af26af6 --- /dev/null +++ b/test/packaging/nested-checkout.test.ts @@ -0,0 +1,50 @@ +// A checkout nested under `.claude/` must not add its tests to this suite. +// The test plants one in a temporary directory next to a real test file and +// asks vitest, with this repo's config, which test files it would run. +import { afterEach, describe, expect, it } from "vitest"; +import { execFileSync } from "node:child_process"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = fileURLToPath(new URL("../../", import.meta.url)); + +let root = ""; + +afterEach(() => { + rmSync(root, { recursive: true, force: true }); +}); + +const writeTest = (path: string): void => { + mkdirSync(join(root, path, ".."), { recursive: true }); + writeFileSync( + join(root, path), + 'import { it } from "vitest";\nit("runs", () => {});\n', + ); +}; + +describe("vitest.config.ts", () => { + it("does not collect tests from a checkout nested under .claude/", () => { + root = mkdtempSync(join(tmpdir(), "quak-nested-checkout-")); + writeTest("test/real.test.ts"); + writeTest(".claude/worktrees/other/test/real.test.ts"); + + const output = execFileSync( + process.execPath, + [ + join(repoRoot, "node_modules/vitest/vitest.mjs"), + "list", + "--filesOnly", + "--config", + join(repoRoot, "vitest.config.ts"), + "--root", + root, + ], + { cwd: root, encoding: "utf-8" }, + ); + + const files = output.split("\n").filter((line) => line !== ""); + expect(files).toEqual(["test/real.test.ts"]); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..e39bf41 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,10 @@ +import { configDefaults, defineConfig } from "vitest/config"; + +// vitest does not read .gitignore when looking for tests. A checkout nested +// under .claude/ has its own test/ tree, and without this exclude the suite +// runs once per nested checkout and still reports success. +export default defineConfig({ + test: { + exclude: [...configDefaults.exclude, ".claude/**"], + }, +}); -- 2.54.0