61 lines
2.8 KiB
TypeScript
61 lines
2.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { exploreUrl, scanUrl } from "../src/engine.js";
|
|
|
|
const fixturePath = path.resolve("tests/fixtures/context-risk.html");
|
|
|
|
async function withTempOutput<T>(name: string, callback: (out: string) => Promise<T>): Promise<T> {
|
|
const dir = await mkdtemp(path.join(tmpdir(), "action-topology-engine-test-"));
|
|
try {
|
|
return await callback(path.join(dir, `${name}.json`));
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
function hasEdgeForAccessibleName(
|
|
graph: {
|
|
edges: Array<{ elementId: string }>;
|
|
elements: Array<{ elementId: string; accessibleName: string | null }>;
|
|
},
|
|
accessibleName: string,
|
|
): boolean {
|
|
return graph.edges.some((edge) => {
|
|
const element = graph.elements.find((item) => item.elementId === edge.elementId);
|
|
return element?.accessibleName === accessibleName;
|
|
});
|
|
}
|
|
|
|
test("scan captures a state-local inventory without clicking high-risk actions", async () => {
|
|
const graph = await withTempOutput("scan", (out) => scanUrl({ url: fixturePath, out }));
|
|
assert.equal(graph.states.length, 1);
|
|
assert.equal(graph.edges.length, 0);
|
|
assert.equal(graph.elements.some((element) => element.accessibleName === "Open settings"), true);
|
|
assert.equal(graph.elements.some((element) => element.accessibleName === "Delete account"), false);
|
|
});
|
|
|
|
test("graph metadata records generation context and policy versions", async () => {
|
|
const graph = await withTempOutput("metadata", (out) => scanUrl({ url: fixturePath, out }));
|
|
assert.equal(graph.schemaVersion, "0.2");
|
|
assert.equal(graph.metadata.engineVersion, "0.2.0");
|
|
assert.equal(graph.metadata.runtimeContext.browserName, "chromium");
|
|
assert.equal(graph.metadata.runtimeContext.viewport.width, 1440);
|
|
assert.equal(graph.metadata.runtimeContext.viewport.height, 1000);
|
|
assert.equal(graph.metadata.riskPolicyVersion, "risk-policy-v0.2");
|
|
assert.equal(graph.metadata.locatorScoringVersion, "locator-scoring-v0.2");
|
|
assert.equal(typeof graph.metadata.crawlSessionId, "string");
|
|
assert.equal(graph.metadata.inputUrl, fixturePath);
|
|
assert.equal(typeof graph.metadata.inputFingerprint, "string");
|
|
});
|
|
|
|
test("explore records low-risk edges and keeps high-risk submit actions out of default execution", async () => {
|
|
const graph = await withTempOutput("explore", (out) => exploreUrl({ url: fixturePath, maxActions: 8, out }));
|
|
assert.equal(graph.edges.some((edge) => edge.riskLevel === "low" && edge.toStateId), true);
|
|
assert.equal(hasEdgeForAccessibleName(graph, "Delete account"), false);
|
|
assert.equal(hasEdgeForAccessibleName(graph, "Submit search"), false);
|
|
assert.equal(graph.states.length >= 2, true);
|
|
});
|