mirror of
https://github.com/morluto/rea.git
synced 2026-10-11 21:39:55 +00:00
test: reuse identical JavaScript analysis fixtures
This commit is contained in:
@@ -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 },
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user