mirror of
https://github.com/morluto/rea.git
synced 2026-10-23 14:22:30 -05:00
150 lines
4.8 KiB
TypeScript
150 lines
4.8 KiB
TypeScript
import { expect, it, onTestFinished, vi } from "vitest";
|
|
|
|
import { createJavaScriptArtifactReader } from "../../src/artifacts/javascript/JavaScriptArtifactReader.js";
|
|
import { analyzeJavaScriptArtifactFiles } from "../../src/application/javascript/JavaScriptArtifactAnalysis.js";
|
|
import { buildJavaScriptArtifactGraph } from "../../src/application/javascript/JavaScriptArtifactGraphBuilder.js";
|
|
import type {
|
|
JavaScriptArtifactFile,
|
|
JavaScriptArtifactFileSet,
|
|
} from "../../src/domain/javascript/javascriptArtifactFiles.js";
|
|
import { scanCanonicalArtifactInventory } from "../fixtures/artifactInventory.js";
|
|
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
|
|
import { writeFixtureFiles } from "../support/javascriptApplicationFixture.js";
|
|
import { readJavaScriptArtifactFiles } from "../support/javascriptApplicationScope.js";
|
|
|
|
const packageJsonText = '{"name":"fault-package"}';
|
|
const jsonText = '{"kind":"fault-json"}';
|
|
|
|
const artifactFile = (
|
|
path: string,
|
|
kind: "package-json" | "json",
|
|
text: string,
|
|
): JavaScriptArtifactFile => ({
|
|
path,
|
|
container_sha256: "container-digest",
|
|
sha256: `digest-${path}`,
|
|
bytes: Buffer.byteLength(text),
|
|
inventory_artifact_id: `artifact-${path}`,
|
|
kind,
|
|
unpacked: false,
|
|
text: { included: true, value: text },
|
|
});
|
|
|
|
const fileSet = (): JavaScriptArtifactFileSet => ({
|
|
files: [
|
|
artifactFile("package.json", "package-json", packageJsonText),
|
|
artifactFile("settings.json", "json", jsonText),
|
|
],
|
|
unavailable_relevant_files: [],
|
|
containers: [],
|
|
text_bytes_read:
|
|
Buffer.byteLength(packageJsonText) + Buffer.byteLength(jsonText),
|
|
invalid_utf8_files: 0,
|
|
});
|
|
|
|
it.each([
|
|
{
|
|
document: "package.json",
|
|
text: packageJsonText,
|
|
create: () => new TypeError("parser fault"),
|
|
},
|
|
{
|
|
document: "package.json",
|
|
text: packageJsonText,
|
|
create: () => new Error("parser fault"),
|
|
},
|
|
{
|
|
document: "ordinary JSON",
|
|
text: jsonText,
|
|
create: () => new TypeError("parser fault"),
|
|
},
|
|
{
|
|
document: "ordinary JSON",
|
|
text: jsonText,
|
|
create: () => new Error("parser fault"),
|
|
},
|
|
])(
|
|
"propagates unexpected JSON.parse faults from $document",
|
|
({ text, create }) => {
|
|
const files = fileSet();
|
|
const originalParse = JSON.parse;
|
|
const thrown = create();
|
|
vi.spyOn(JSON, "parse").mockImplementation((input) => {
|
|
if (input === text) throw thrown;
|
|
return originalParse(input);
|
|
});
|
|
onTestFinished(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
let caught: unknown;
|
|
try {
|
|
analyzeJavaScriptArtifactFiles(files);
|
|
} catch (cause: unknown) {
|
|
caught = cause;
|
|
}
|
|
expect(caught).toBe(thrown);
|
|
},
|
|
);
|
|
|
|
it("keeps malformed JSON as an invalid observation", () => {
|
|
const malformedPackage = artifactFile("package.json", "package-json", "{");
|
|
const malformedJson = artifactFile("settings.json", "json", "{");
|
|
const analysis = analyzeJavaScriptArtifactFiles({
|
|
...fileSet(),
|
|
files: [malformedPackage, malformedJson],
|
|
});
|
|
|
|
expect(analysis.packages).toMatchObject([{ status: "invalid" }]);
|
|
expect(analysis.json_modules).toMatchObject([{ status: "invalid" }]);
|
|
});
|
|
|
|
it("reuses parsed package and JSON facts while building the public graph", async () => {
|
|
const root = await createTestTempDirectory("rea-json-document-graph-");
|
|
await writeFixtureFiles(root, {
|
|
"main.cjs": 'require("./dep"); require("./config.json");',
|
|
"dep/package.json": '{"main":"index.cjs"}',
|
|
"dep/index.cjs": "module.exports = 1;",
|
|
"config.json": '{"enabled":true}',
|
|
});
|
|
const snapshot = await scanCanonicalArtifactInventory(root, {});
|
|
const reader = createJavaScriptArtifactReader(root, "directory");
|
|
try {
|
|
const files = await readJavaScriptArtifactFiles(reader, snapshot);
|
|
const analysis = analyzeJavaScriptArtifactFiles(files);
|
|
const depPackageText = '{"main":"index.cjs"}';
|
|
const configText = '{"enabled":true}';
|
|
const originalParse = JSON.parse;
|
|
vi.spyOn(JSON, "parse").mockImplementation((text) => {
|
|
if (text === depPackageText || text === configText)
|
|
throw new TypeError("unexpected JSON reparse");
|
|
return originalParse(text);
|
|
});
|
|
|
|
const graph = buildJavaScriptArtifactGraph(snapshot, files, analysis);
|
|
expect(
|
|
graph.edges.find(
|
|
({ relation, properties }) =>
|
|
relation === "imports" && properties.specifier === "./dep",
|
|
)?.properties,
|
|
).toMatchObject({
|
|
resolution_status: "resolved",
|
|
resolved_path: "dep/index.cjs",
|
|
});
|
|
expect(
|
|
graph.edges.find(
|
|
({ relation, properties }) =>
|
|
relation === "imports" &&
|
|
properties.specifier === "./config.json" &&
|
|
Object.hasOwn(properties, "target_json_status"),
|
|
)?.properties,
|
|
).toMatchObject({
|
|
target_file_kind: "json",
|
|
target_json_status: "included",
|
|
});
|
|
} finally {
|
|
vi.restoreAllMocks();
|
|
await reader.close();
|
|
}
|
|
});
|