mirror of
https://github.com/morluto/rea.git
synced 2026-10-27 18:05:45 +00:00
* test(ci): keep module mocks in isolated test projects A module mock registered after another file in the same worker loaded the module never applies, so a mocking test in a project that shares one module graph passes or fails with file scheduling. That is how the environment export source tests failed on hosted runs untilc324d31b4removed their mocks. Guard the rule: every tracked test using vi.mock or vi.doMock must belong to an isolated project. Move the last shared-graph case, DirectAnalysisStatFailure, which mocks node:fs/promises, into process-global beside the other module-mocking workflow tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(pe): share one compiled CLI process across PE resource inspections The acceptance test started a fresh CLI process for each of its fixtures inside one 30 s test deadline. Hosted runs took 24-27 s andc324d31b4timed out. Every inspection there reads no stdin and sets no deadline, so use the fixture's file-scoped compiled CLI process. Local time drops from 8.5 s to about 3.9 s with the same assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
185 lines
6.0 KiB
TypeScript
185 lines
6.0 KiB
TypeScript
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<string, string[]>();
|
|
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<string, boolean>;
|
|
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([]);
|
|
});
|
|
});
|