mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
Restore source-position-aware ambient aliases, scalar env/argv reads, candidate endpoint worker data, Chrome DOMSnapshot empty strings, and accumulated Ghidra LaunchSupport diagnostics. Align regression fixtures with declared current contracts, while preserving identity, provenance, cancellation, and cleanup checks. Assert workflow caveats independently at both established locations. Validation: original five source failures reproduced on main; 307 focused tests passed with one platform skip, 22 fixture follow-up tests and 22 workflow/MCP tests passed; full static and docs checks passed. Real public http-server CLI analyses preserve identical artifact identity, statistics, and 581-token selected output. Real Chromium confirms restored DOM form destinations; isolated real service-worker verification passes on main and the change. The complete local browser run retained an unclassified later marker timeout; current-head CI provides complete real-browser and recovery lane results. Native IDA/Ghidra execution and complete local suite execution are not claimed. Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> Co-authored-by: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
318 lines
11 KiB
TypeScript
318 lines
11 KiB
TypeScript
import {
|
|
copyFile,
|
|
lstat,
|
|
mkdir,
|
|
readFile,
|
|
symlink,
|
|
writeFile,
|
|
} from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { execFileOutput } from "../../../src/process/ExecFileOutput.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
|
|
const run = (
|
|
root: string,
|
|
command: string,
|
|
arguments_: readonly string[],
|
|
env?: NodeJS.ProcessEnv,
|
|
) =>
|
|
execFileOutput(command, arguments_, {
|
|
cwd: root,
|
|
stopSignal: "SIGTERM",
|
|
timeout: 30_000,
|
|
maxBuffer: 1024 * 1024,
|
|
...(env === undefined ? {} : { env }),
|
|
});
|
|
|
|
const git = (root: string, ...arguments_: string[]) =>
|
|
run(root, "git", arguments_);
|
|
|
|
const commit = (root: string, message: string) =>
|
|
git(
|
|
root,
|
|
"-c",
|
|
"user.name=REA fixture",
|
|
"-c",
|
|
"user.email=fixture@example.test",
|
|
"-c",
|
|
"commit.gpgSign=false",
|
|
"commit",
|
|
"--quiet",
|
|
"-m",
|
|
message,
|
|
);
|
|
|
|
const fixture = async () => {
|
|
const root = await createTestTempDirectory("rea-development-tests-");
|
|
await mkdir(join(root, "scripts", "lib"), { recursive: true });
|
|
await mkdir(join(root, "src"));
|
|
for (const path of [
|
|
"scripts/run-development-tests.mjs",
|
|
"scripts/run-exact-tests.mjs",
|
|
"scripts/lib/development-tests.mjs",
|
|
"scripts/lib/test-projects.mjs",
|
|
])
|
|
await copyFile(join(process.cwd(), path), join(root, path));
|
|
await symlink(
|
|
join(process.cwd(), "node_modules"),
|
|
join(root, "node_modules"),
|
|
process.platform === "win32" ? "junction" : undefined,
|
|
);
|
|
await writeFile(join(root, "package.json"), '{"type":"module"}\n');
|
|
await writeFile(join(root, ".gitignore"), "node_modules\nselected.txt\n");
|
|
await writeFile(
|
|
join(root, "vitest.config.mjs"),
|
|
'export default { test: { projects: [{ test: { name: "domain", include: ["src/**/*.test.ts"] } }] } };\n',
|
|
);
|
|
await writeFile(join(root, "src/value.ts"), "export const value = 1;\n");
|
|
await writeFile(
|
|
join(root, "src/value.test.ts"),
|
|
'import { expect, it } from "vitest"; import { writeFileSync } from "node:fs"; import { value } from "./value.js"; it("checks the selected source", () => { expect(value).toBe(1); writeFileSync("selected.txt", String(value)); });\n',
|
|
);
|
|
await git(root, "init", "--quiet", "-b", "main");
|
|
await git(root, "add", ".");
|
|
await commit(root, "fixture");
|
|
return root;
|
|
};
|
|
|
|
// Assertions read the child's plain-text summary. An inherited color setting
|
|
// styled the counts in the CI lane; NO_COLOR takes precedence over FORCE_COLOR.
|
|
const testCommand = (root: string, ...arguments_: string[]) =>
|
|
run(
|
|
root,
|
|
process.execPath,
|
|
["scripts/run-development-tests.mjs", ...arguments_],
|
|
{ ...process.env, NO_COLOR: "1" },
|
|
);
|
|
|
|
describe("development test runner exact selection", () => {
|
|
it("matches selected path casing to the host filesystem", async () => {
|
|
const root = await fixture();
|
|
try {
|
|
await lstat(join(root, "src/VALUE.test.ts"));
|
|
} catch (cause) {
|
|
if (
|
|
!(cause instanceof Error) ||
|
|
!("code" in cause) ||
|
|
cause.code !== "ENOENT"
|
|
)
|
|
throw cause;
|
|
await expect(
|
|
testCommand(root, "focused", "src/VALUE.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining("ENOENT"),
|
|
});
|
|
return;
|
|
}
|
|
await testCommand(root, "focused", "src/VALUE.test.ts");
|
|
expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1");
|
|
});
|
|
|
|
it("matches Unicode-normalized aliases by filesystem identity", async () => {
|
|
const root = await fixture();
|
|
const composed = "caf\u00e9.test.ts";
|
|
const decomposed = composed.normalize("NFD");
|
|
await writeFile(
|
|
join(root, "src", composed),
|
|
'import { it } from "vitest"; it("checks the selected Unicode path", () => {});\n',
|
|
);
|
|
const selected = join(root, "src", decomposed);
|
|
try {
|
|
await lstat(selected);
|
|
} catch (cause) {
|
|
if (
|
|
!(cause instanceof Error) ||
|
|
!("code" in cause) ||
|
|
cause.code !== "ENOENT"
|
|
)
|
|
throw cause;
|
|
await expect(
|
|
testCommand(root, "focused", `src/${decomposed}`),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining("ENOENT"),
|
|
});
|
|
return;
|
|
}
|
|
const result = await testCommand(root, "focused", `src/${decomposed}`);
|
|
expect(result.stdout).toContain("1 passed");
|
|
});
|
|
|
|
it.each(["local", "focused"])(
|
|
"runs only the exact selected file in %s mode",
|
|
async (mode) => {
|
|
const root = await fixture();
|
|
await mkdir(join(root, "src", "nested", "src"), { recursive: true });
|
|
await writeFile(
|
|
join(root, "src", "nested", "src", "value.test.ts"),
|
|
'import { it } from "vitest"; it("must not run", () => { throw new Error("unselected nested test ran"); });\n',
|
|
);
|
|
const result = await testCommand(root, mode, "src/value.test.ts");
|
|
expect(result.stdout).toContain("1 passed");
|
|
expect(result.stdout).not.toContain("nested/src/value.test.ts");
|
|
expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1");
|
|
},
|
|
);
|
|
|
|
it("fails when any selected existing test file is excluded from discovery", async () => {
|
|
const root = await fixture();
|
|
await writeFile(
|
|
join(root, "src", "excluded.test.ts"),
|
|
'import { it } from "vitest"; it("excluded", () => {});\n',
|
|
);
|
|
await writeFile(
|
|
join(root, "vitest.config.mjs"),
|
|
'export default { test: { projects: [{ test: { name: "domain", include: ["src/value.test.ts"] } }] } };\n',
|
|
);
|
|
await expect(
|
|
testCommand(root, "focused", "src/value.test.ts", "src/excluded.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining(
|
|
"Selected test files were not discovered: src/excluded.test.ts",
|
|
),
|
|
});
|
|
});
|
|
|
|
it("runs every selected file and preserves selected test failures", async () => {
|
|
const root = await fixture();
|
|
await writeFile(
|
|
join(root, "src", "failure.test.ts"),
|
|
'import { it } from "vitest"; it("selected failure", () => { throw new Error("selected regression"); });\n',
|
|
);
|
|
await expect(
|
|
testCommand(root, "focused", "src/value.test.ts", "src/failure.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stdout: expect.stringContaining("1 failed | 1 passed"),
|
|
stderr: expect.stringContaining("selected regression"),
|
|
});
|
|
expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1");
|
|
});
|
|
|
|
it("preserves all configured projects for an exact file", async () => {
|
|
const root = await fixture();
|
|
await writeFile(
|
|
join(root, "vitest.config.mjs"),
|
|
'export default { test: { projects: ["domain", "evaluation"].map(name => ({ test: { name, include: ["src/value.test.ts"] } })) } };\n',
|
|
);
|
|
const result = await testCommand(root, "focused", "src/value.test.ts");
|
|
expect(result.stdout).toMatch(/Test Files\s+2 passed/u);
|
|
});
|
|
|
|
it("fails an exact file with no tests even when another selected file passes", async () => {
|
|
const root = await fixture();
|
|
await writeFile(join(root, "src", "empty.test.ts"), "export {};\n");
|
|
await expect(
|
|
testCommand(root, "focused", "src/value.test.ts", "src/empty.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining("No test suite found"),
|
|
});
|
|
expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1");
|
|
});
|
|
});
|
|
|
|
describe("development test runner public CLI", () => {
|
|
it("runs an explicitly selected source test on a clean tree without build artifacts", async () => {
|
|
const root = await fixture();
|
|
const { stdout: status } = await git(root, "status", "--porcelain");
|
|
expect(status).toBe("");
|
|
await testCommand(root, "local", "src/value.test.ts");
|
|
expect(await readFile(join(root, "selected.txt"), "utf8")).toBe("1");
|
|
});
|
|
|
|
it("plans an exact local test without building", async () => {
|
|
const root = await fixture();
|
|
const { stdout } = await testCommand(
|
|
root,
|
|
"local",
|
|
"src/value.test.ts",
|
|
"--dry-run",
|
|
);
|
|
expect(JSON.parse(stdout)).toMatchObject({
|
|
needsBuild: false,
|
|
artifactTasks: [],
|
|
vitestArguments: expect.arrayContaining([
|
|
"run",
|
|
"--project",
|
|
"domain",
|
|
"--project",
|
|
"services",
|
|
"--project",
|
|
"adapters",
|
|
"--project",
|
|
"composition",
|
|
"--project",
|
|
"conformance",
|
|
"--project",
|
|
"evaluation",
|
|
"src/value.test.ts",
|
|
]),
|
|
});
|
|
});
|
|
|
|
it("uses committed dependency changes to select source tests and reports failures", async () => {
|
|
const root = await fixture();
|
|
const { stdout: base } = await git(root, "rev-parse", "HEAD");
|
|
await writeFile(join(root, "src/value.ts"), "export const value = 2;\n");
|
|
await git(root, "add", "src/value.ts");
|
|
await commit(root, "change dependency");
|
|
await expect(
|
|
testCommand(root, "changed", "--base", base.trim()),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stdout: expect.stringContaining("src/value.test.ts"),
|
|
stderr: expect.stringContaining("expected 2 to be 1"),
|
|
});
|
|
});
|
|
|
|
it("runs changed and focused tests from a committed branch regression", async () => {
|
|
const root = await fixture();
|
|
const { stdout: baseline } = await git(root, "rev-parse", "HEAD");
|
|
await git(root, "update-ref", "refs/remotes/origin/main", baseline.trim());
|
|
await git(root, "switch", "--quiet", "-c", "regression");
|
|
await writeFile(join(root, "src/value.ts"), "export const value = 2;\n");
|
|
await writeFile(
|
|
join(root, "src/value.test.ts"),
|
|
'import { expect, it } from "vitest"; import { value } from "./value.js"; it("checks current source", () => expect(value).toBe(2));\n',
|
|
);
|
|
await git(root, "add", "src");
|
|
await commit(root, "regression fix");
|
|
expect((await git(root, "status", "--porcelain")).stdout).toBe("");
|
|
|
|
const changed = await testCommand(root, "changed");
|
|
expect(changed.stdout).toContain("1 passed");
|
|
const focused = await testCommand(root, "focused", "src/value.test.ts");
|
|
expect(focused.stdout).toContain("1 passed");
|
|
}, 60_000);
|
|
|
|
it("reports a missing comparison base and rejects missing or compiled-boundary paths", async () => {
|
|
const root = await fixture();
|
|
await expect(
|
|
testCommand(root, "changed", "--base", "missing-test-base", "--dry-run"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining(
|
|
"Fetch origin/main or pass --base REVISION",
|
|
),
|
|
});
|
|
await expect(
|
|
testCommand(root, "focused", "src/missing.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining("ENOENT"),
|
|
});
|
|
await expect(
|
|
testCommand(root, "local", "tests/acceptance/runtime.test.ts"),
|
|
).rejects.toMatchObject({
|
|
code: 1,
|
|
stderr: expect.stringContaining("Use test:focused"),
|
|
});
|
|
});
|
|
});
|