test: reuse identical JavaScript analysis fixtures

This commit is contained in:
morluto
2026-10-11 17:43:28 +08:00
parent aaeadf2d4c
commit 42951bbbbe
2 changed files with 90 additions and 79 deletions
@@ -113,18 +113,20 @@ describe("JavaScript export return-shape comparison", () => {
});
describe("JavaScript export return-shape pairing limits", () => {
it.each([
{ presence: "absent", side: "left" },
{ presence: "unknown-coverage", side: "left" },
{ presence: "absent", side: "right" },
{ presence: "unknown-coverage", side: "right" },
] as const)(
"does not pair an inline $side discriminant whose presence is $presence",
async ({ presence, side }) => {
const [left, right] = await analyzeSources({
left: 'export default () => ({ kind: "result", count: 1 });',
right: 'export default () => ({ kind: "result", total: 2 });',
});
it("does not pair an inline discriminant with absent or unknown presence", async () => {
const rows = [
{ presence: "absent", side: "left" },
{ presence: "unknown-coverage", side: "left" },
{ presence: "absent", side: "right" },
{ presence: "unknown-coverage", side: "right" },
] as const;
const [left, right] = await analyzeSources({
left: 'export default () => ({ kind: "result", count: 1 });',
right: 'export default () => ({ kind: "result", total: 2 });',
});
for (const { presence, side } of rows) {
const label = `${side} discriminant presence ${presence}`;
const selected = side === "left" ? left : right;
const graph = createJavaScriptApplicationGraph({
schema: "JavaScriptApplicationGraph",
@@ -165,26 +167,28 @@ describe("JavaScript export return-shape pairing limits", () => {
side === "left"
? compare({ ...left, graph }, right)
: compare(left, { ...right, graph });
expect(result.coverage).toMatchObject({
expect(result.coverage, label).toMatchObject({
status: "partial",
paired_variants: 0,
unpaired_left_variants: 1,
unpaired_right_variants: 1,
});
expect(result.changes).toHaveLength(2);
expect(result.changes, label).toHaveLength(2);
expect(
result.changes.every(
({ status, discriminant }) =>
status === "unknown" && discriminant === null,
),
label,
).toBe(true);
expect(
result.property_inventories.every(
({ paired, discriminant }) => !paired && discriminant === null,
),
label,
).toBe(true);
},
);
}
});
it("does not pair discriminants that an unknown trailing spread can overwrite", async () => {
const [left, right] = await analyzeSources({
@@ -169,27 +169,13 @@ const nativeResultSchema = z.object({
code: z.string().nullable(),
});
it.each(
(["import", "require"] as const).flatMap((moduleKind) =>
cases.map((testCase) => ({ ...testCase, moduleKind })),
),
)(
"matches Node $moduleKind target selection for $name",
async ({
moduleKind,
name,
exports,
expected,
nodeError,
rejectedTarget,
}) => {
it.each(cases)(
"matches Node import and require target selection for $name",
async ({ name, exports, expected, nodeError, rejectedTarget }) => {
const root = await createTestTempDirectory("rea-package-target-");
const mainPath = moduleKind === "import" ? "main.mjs" : "main.cjs";
const files = {
[mainPath]:
moduleKind === "import"
? 'import value from "fixture"; export default value;'
: 'module.exports = require("fixture");',
"main.mjs": 'import value from "fixture"; export default value;',
"main.cjs": 'module.exports = require("fixture");',
"node_modules/fixture/package.json": JSON.stringify({ exports }),
...Object.fromEntries(
[
@@ -209,57 +195,78 @@ it.each(
await writeFile(join(root, path), text);
}),
);
const runner =
moduleKind === "import"
? 'const load = async () => (await import("fixture")).default;'
: 'const load = async () => require("fixture");';
const native = await promisify(execFile)(
process.execPath,
[
"--input-type",
moduleKind === "import" ? "module" : "commonjs",
"--eval",
`${runner} load().then(value => console.log(JSON.stringify({value,code:null})), error => console.log(JSON.stringify({value:null,code:error.code ?? error.name})));`,
],
{ cwd: root, timeout: 5_000 },
);
const oracle = nativeResultSchema.parse(JSON.parse(native.stdout));
expect(oracle.value, name).toBe(expected);
if (nodeError !== undefined)
expect(oracle.code).toBe(
moduleKind === "import" && nodeError === "MODULE_NOT_FOUND"
? "ERR_MODULE_NOT_FOUND"
: nodeError,
for (const moduleKind of ["import", "require"] as const) {
const runner =
moduleKind === "import"
? 'const load = async () => (await import("fixture")).default;'
: 'const load = async () => require("fixture");';
const native = await promisify(execFile)(
process.execPath,
[
"--input-type",
moduleKind === "import" ? "module" : "commonjs",
"--eval",
`${runner} load().then(value => console.log(JSON.stringify({value,code:null})), error => console.log(JSON.stringify({value:null,code:error.code ?? error.name})));`,
],
{ cwd: root, timeout: 5_000 },
);
const oracle = nativeResultSchema.parse(JSON.parse(native.stdout));
expect(oracle.value, `${name} (${moduleKind})`).toBe(expected);
if (nodeError !== undefined)
expect(oracle.code, `${name} (${moduleKind})`).toBe(
moduleKind === "import" && nodeError === "MODULE_NOT_FOUND"
? "ERR_MODULE_NOT_FOUND"
: nodeError,
);
}
const result = await reconstructJavaScriptArtifact({
input_path: root,
format: "directory",
});
const edge = result.graph.edges.find(
({ properties }) =>
properties.specifier === "fixture" &&
properties.resolution_status !== undefined &&
properties.resolution_status !== null,
);
expect(edge).toBeDefined();
expect(edge?.properties.resolved_path).toBe(expected);
if (expected !== null) {
expect(edge?.properties.resolution_status).toBe("resolved");
} else {
expect(edge?.properties.resolution_status).not.toBe("resolved");
}
if (rejectedTarget !== undefined) {
expect(edge?.properties.resolution_status).toBe("rejected");
expect(edge?.evidence.limitations.join(" ")).toContain(
JSON.stringify(rejectedTarget),
for (const mainPath of ["main.mjs", "main.cjs"] as const) {
const edge = result.graph.edges.find(
({ evidence, properties }) =>
properties.specifier === "fixture" &&
properties.resolution_status !== undefined &&
properties.resolution_status !== null &&
evidence.location.available &&
evidence.location.value.kind === "source-range" &&
evidence.location.value.source === mainPath,
);
expect(edge?.evidence.limitations.join(" ")).toContain("exports target");
expect(edge?.evidence.limitations.join(" ")).not.toContain(
"not valid package JSON",
expect(edge, `${name} (${mainPath})`).toBeDefined();
expect(edge?.properties.resolved_path, `${name} (${mainPath})`).toBe(
expected,
);
expect(edge?.evidence.location).toMatchObject({
value: { kind: "source-range", source: mainPath },
});
if (expected !== null) {
expect(
edge?.properties.resolution_status,
`${name} (${mainPath})`,
).toBe("resolved");
} else {
expect(
edge?.properties.resolution_status,
`${name} (${mainPath})`,
).not.toBe("resolved");
}
if (rejectedTarget !== undefined) {
expect(
edge?.properties.resolution_status,
`${name} (${mainPath})`,
).toBe("rejected");
expect(edge?.evidence.limitations.join(" ")).toContain(
JSON.stringify(rejectedTarget),
);
expect(edge?.evidence.limitations.join(" ")).toContain(
"exports target",
);
expect(edge?.evidence.limitations.join(" ")).not.toContain(
"not valid package JSON",
);
expect(edge?.evidence.location).toMatchObject({
value: { kind: "source-range", source: mainPath },
});
}
}
},
);