Files
reverse-engineering-anything/tests/acceptance/applications/javascriptGraphqlWideSourceCli.test.ts
T
Kaoru0822 adf8bdf833 fix(javascript): preserve GraphQL Source ownership across spreads (#10338)
* fix(javascript): preserve GraphQL Source ownership across spreads

* fix(javascript): keep inline Sources owned by their enclosing Source
2026-11-13 06:07:24 -08:00

59 lines
2.4 KiB
TypeScript

import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
import { analyzeJavaScriptDirectory } from "../../support/cli/javascriptApplication.js";
cliTest.for(["CLI", "stdio MCP"] as const)(
"retains wide GraphQL Source ownership without dropping its file through %s",
async (surface, { cli }) => {
const root = await createTestTempDirectory("rea-graphql-wide-source-");
const path = join(root, "main.mjs");
// This exceeds the worker's 2 MiB V8 argument stack while staying within
// admitted source/AST limits. Duplicate properties are valid inert JS.
const source = `const source = {
locationOffset: { line: 1, column: 1 },
...{locationOffset: { line: 1, column: 1 },
${'body:"query Overwritten { x }",'.repeat(270_000)}},
body: "query Active { viewer { id } }",
note: "query Unrelated { viewer { id } }",
};`;
await writeFile(path, source);
const result = await analyzeJavaScriptDirectory(surface, cli, root);
expect(result.statistics).toMatchObject({
parsed_javascript_files: 1,
skipped_javascript_files: 0,
parse_failures: 0,
});
const operations = result.graph.nodes
.filter((node) => node.kind === "endpoint")
.flatMap((node) => node.observations)
.filter(({ properties }) => properties.mechanism === "graphql:query");
// Overwritten body copies stay owned by the Source; its unrelated string
// remains independently scannable, and the final body supplies the query.
expect(operations.map(({ properties }) => properties.value).sort()).toEqual(
["Active", "Unrelated"],
);
expect(result.graph.coverage.status).toBe("complete");
for (const operation of operations)
expect(operation.evidence).toMatchObject({
authority: "ast-static-analysis",
state: "observed",
artifact: { available: true },
location: {
available: true,
value: { kind: "source-range", source: "main.mjs" },
},
});
expect(
createHash("sha256")
.update(await readFile(path))
.digest("hex"),
).toBe(createHash("sha256").update(source).digest("hex"));
},
);