import { execFileSync } from "node:child_process"; import { readFile, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; import { describe, expect, it } from "vitest"; import { BUILT_TEST_PROJECTS, SOURCE_TEST_PROJECTS, projectForTest, } from "../../../scripts/lib/test-projects.mjs"; import { developmentTestPlan, parseDevelopmentTestRequest, } from "../../../scripts/lib/development-tests.mjs"; import { execFileOutput } from "../../../src/process/ExecFileOutput.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; const repository = process.cwd(); describe("canonical test-project ownership", () => { it("assigns every tracked test file exactly once to source or built", () => { const files = execFileSync("git", ["ls-files", "*.test.ts"], { cwd: repository, encoding: "utf8", }) .trim() .split("\n") .filter(Boolean); const grouped = new Map(); for (const file of files) { const project = projectForTest(file); grouped.set(project.group, [...(grouped.get(project.group) ?? []), file]); } expect(grouped.get("source")).not.toBeUndefined(); expect(grouped.get("built")).not.toBeUndefined(); expect( (grouped.get("source")?.length ?? 0) + (grouped.get("built")?.length ?? 0), ).toBe(files.length); expect( SOURCE_TEST_PROJECTS.reduce( (count, project) => count + project.include.length, 0, ), ).toBeGreaterThan(0); expect( BUILT_TEST_PROJECTS.every((project) => project.group === "built"), ).toBe(true); expect(() => projectForTest("tests/unowned/example.test.ts")).toThrow( "No test project owns", ); }); it("owns the Hopper real-provider conformance test as built and requires preparation", () => { const testPath = "tests/conformance/providers/hopper/realHopperSearch.test.ts"; expect(projectForTest(testPath)).toMatchObject({ name: "boundary", group: "built", }); expect(() => parseDevelopmentTestRequest("local", [testPath])).toThrow( `Use test:focused for built test projects: ${testPath}`, ); const request = parseDevelopmentTestRequest("focused", [testPath]); expect(developmentTestPlan(request)).toMatchObject({ needsBuild: true }); }); it("uses canonical selectors in Vitest while retaining independent runner policy", async () => { const config = await readFile(join(repository, "vitest.config.ts"), "utf8"); expect(config).toContain( "[...SOURCE_TEST_PROJECTS, ...BUILT_TEST_PROJECTS]", ); expect(config).toContain("PROJECT_POLICIES"); expect(config).not.toContain('"src/{contracts,domain}/**/*.test.ts"'); }); it.each([ { flags: [], heap: 384, timeout: 30_000, lines: 68 }, { flags: ["--coverage"], heap: 512, timeout: 60_000, lines: 68 }, { flags: ["--coverage.enabled"], heap: 512, timeout: 60_000, lines: 68 }, { flags: ["--coverage=false"], heap: 384, timeout: 30_000, lines: 68 }, { flags: ["--coverage.enabled=false"], heap: 384, timeout: 30_000, lines: 68, }, { flags: ["--coverage.provider=v8"], heap: 384, timeout: 30_000, lines: 68, }, { flags: ["--coverage.enabled", "--shard", "1/6"], heap: 512, timeout: 60_000, lines: 0, }, { flags: ["--coverage.enabled=false", "--shard=1/6"], heap: 384, timeout: 30_000, lines: 0, }, ])( "resolves worker resources from actual CLI options: $flags", async ({ flags, heap, timeout, lines }) => { const root = await createTestTempDirectory("rea-vitest-worker-policy-"); const script = join(root, "worker-policy.mjs"); await writeFile( script, ` import config from ${JSON.stringify(pathToFileURL(join(repository, "vitest.config.ts")).href)}; const project = config.test.projects.find(project => project.test.name === 'cli-boundary'); console.log(JSON.stringify({ execArgv: project.test.execArgv, timeout: config.test.testTimeout, lines: config.test.coverage.thresholds.lines, })); `, ); const result = await execFileOutput( process.execPath, ["--import", "tsx", script, ...flags], { cwd: repository, timeout: 10_000, maxBuffer: 64 * 1024, stopSignal: "SIGTERM", }, ); expect(JSON.parse(result.stdout)).toEqual({ execArgv: [`--max-old-space-size=${String(heap)}`], timeout, lines, }); }, ); }); describe("test module isolation", () => { it("keeps module mocks out of projects that share one module graph", async () => { // A mock registered after another file in the same worker loaded the // module never applies, so the test's outcome depends on file scheduling. const root = await createTestTempDirectory("rea-vitest-mock-isolation-"); const script = join(root, "project-isolation.mjs"); await writeFile( script, ` import config from ${JSON.stringify(pathToFileURL(join(repository, "vitest.config.ts")).href)}; console.log(JSON.stringify(Object.fromEntries( config.test.projects.map(project => [project.test.name, project.test.isolate !== false]), ))); `, ); const result = await execFileOutput( process.execPath, ["--import", "tsx", script], { cwd: repository, timeout: 10_000, maxBuffer: 64 * 1024, stopSignal: "SIGTERM", }, ); const isolated = JSON.parse(result.stdout) as Record; const mocking = execFileSync( "git", ["grep", "-l", "-E", String.raw`vi\.(mock|doMock)\(`, "--", "*.test.ts"], { cwd: repository, encoding: "utf8" }, ) .trim() .split("\n") .filter(Boolean); expect(mocking.length).toBeGreaterThan(0); expect( mocking.filter((file) => isolated[projectForTest(file).name] !== true), ).toEqual([]); }); });