mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
refactor(browser): move bundle fixture composition out of runtime
This commit is contained in:
1 parent
7958e15892
commit
6021efd371
4 files changed
+75
-77
No files matched your search
@@ -17,6 +17,7 @@ import {
|
||||
import { BrowserObservationError } from "../domain/browserObservationError.js";
|
||||
import { err, ok } from "../domain/result.js";
|
||||
import { passiveNetworkCapture } from "../../tests/fixtures/passiveNetworkCapture.js";
|
||||
import { analyzeWebBundleFixture } from "../../tests/support/browser/analyzeWebBundleFixture.js";
|
||||
import { inspectWebPage } from "./BrowserObservationService.js";
|
||||
import { analyzeWebBundleInputSchema } from "../domain/webBundleAnalysis.js";
|
||||
import { inspectWebPageInputSchema } from "../domain/browserObservation.js";
|
||||
@@ -163,11 +164,9 @@ it("retains captured page Evidence when bundle analysis fails after capture", as
|
||||
});
|
||||
|
||||
it("retains completed bundle facts as bundle Evidence after cancellation", async () => {
|
||||
const { analyzeCapturedWebBundle } =
|
||||
await import("../domain/webBundleAnalyzer.js");
|
||||
const { AnalysisCancelledError } =
|
||||
await import("../domain/analysisErrorCore.js");
|
||||
const bundle = analyzeCapturedWebBundle(passiveNetworkCapture());
|
||||
const bundle = analyzeWebBundleFixture(passiveNetworkCapture());
|
||||
const reason = { requested: "stop after completed script" };
|
||||
const failure = new AnalysisCancelledError("analyze_web_bundle", {
|
||||
cause: reason,
|
||||
|
||||
@@ -6,10 +6,8 @@ import { describe, expect, it } from "vitest";
|
||||
import { createWebPageInspection } from "../../tests/support/browser/webPageInspection.js";
|
||||
|
||||
import { analyzeJavaScriptStaticSource } from "./javascript/javascriptStaticAnalysis.js";
|
||||
import {
|
||||
analyzeCapturedWebBundle,
|
||||
analyzeCapturedWebScript,
|
||||
} from "./webBundleAnalyzer.js";
|
||||
import { analyzeCapturedWebScript } from "./webBundleAnalyzer.js";
|
||||
import { analyzeWebBundleFixture } from "../../tests/support/browser/analyzeWebBundleFixture.js";
|
||||
import { buildCapturedWebBundleAnalysis } from "./webBundleAnalyzerResult.js";
|
||||
import { webBundleAnalysisSchema } from "./webBundleAnalysis.js";
|
||||
import { isIncludedScript } from "./webBundleAnalyzerState.js";
|
||||
@@ -19,7 +17,7 @@ import { createWebTextArtifact } from "./webContentArtifact.js";
|
||||
const origin = "https://app.example.test";
|
||||
|
||||
it("retains standalone GraphQL Source operations in captured scripts", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const source = {
|
||||
body: "query GetUser { user { id } }",
|
||||
@@ -57,7 +55,7 @@ it.each([
|
||||
if (good === undefined) throw new Error("Missing valid script fixture");
|
||||
captured.scripts.items.push({ ...good, script_key: "valid-script" });
|
||||
captured.scripts.total += 1;
|
||||
const result = analyzeCapturedWebBundle(captured);
|
||||
const result = analyzeWebBundleFixture(captured);
|
||||
expect(result.completeness).toMatchObject({
|
||||
status: "partial",
|
||||
parsed_scripts: parsed,
|
||||
@@ -98,7 +96,7 @@ it.each([
|
||||
"shares Map receiver certainty with application analysis: %s",
|
||||
(source, candidate) => {
|
||||
const input = source + " fetch('/network');";
|
||||
const result = analyzeCapturedWebBundle(inspection(input));
|
||||
const result = analyzeWebBundleFixture(inspection(input));
|
||||
expect(result.observations.endpoints.map(({ value }) => value)).toEqual([
|
||||
"/network",
|
||||
]);
|
||||
@@ -140,7 +138,7 @@ it("discloses widened returned-reference effects only for the affected script",
|
||||
if (independent === undefined) throw new Error("Missing independent script");
|
||||
captured.scripts.items.push({ ...independent, script_key: "independent" });
|
||||
captured.scripts.total += 1;
|
||||
const result = analyzeCapturedWebBundle(captured);
|
||||
const result = analyzeWebBundleFixture(captured);
|
||||
expect(result.completeness).toMatchObject({
|
||||
status: "partial",
|
||||
parsed_scripts: 2,
|
||||
@@ -225,7 +223,7 @@ it.each([
|
||||
])(
|
||||
"preserves WebMCP facts through $label",
|
||||
({ source, name, description, properties, coverage }) => {
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
|
||||
expect(result.observations.webmcp_declarations).toEqual([
|
||||
expect.objectContaining({
|
||||
@@ -270,7 +268,7 @@ it.each([
|
||||
])(
|
||||
"preserves rightmost uncertainty for $label",
|
||||
({ source, name, description, properties, coverage }) => {
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
|
||||
expect(result.observations.webmcp_declarations).toEqual([
|
||||
expect.objectContaining({
|
||||
@@ -375,7 +373,7 @@ it.each([
|
||||
])(
|
||||
"preserves WebMCP schema ownership for $label",
|
||||
({ source, name, properties, coverage }) => {
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
|
||||
expect(result.observations.webmcp_declarations).toEqual([
|
||||
expect.objectContaining({
|
||||
@@ -408,7 +406,7 @@ describe("web bundle analyzer", () => {
|
||||
});
|
||||
const __webpack_require__ = () => createApp(routes, lazy);
|
||||
`;
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
|
||||
expect(result.observations.chunks.edges).toEqual(
|
||||
expect.arrayContaining([
|
||||
@@ -451,14 +449,14 @@ describe("web bundle analyzer", () => {
|
||||
|
||||
it("reports parser gaps without imposing a finding cap", () => {
|
||||
const malformed = inspection("function broken( {");
|
||||
const failed = analyzeCapturedWebBundle(malformed);
|
||||
const failed = analyzeWebBundleFixture(malformed);
|
||||
expect(failed.completeness).toMatchObject({
|
||||
status: "partial",
|
||||
parse_failures: 1,
|
||||
});
|
||||
expect(failed.unknowns[0]?.dimension).toBe("javascript_ast");
|
||||
|
||||
const analyzed = analyzeCapturedWebBundle(
|
||||
const analyzed = analyzeWebBundleFixture(
|
||||
inspection("fetch('/one'); fetch('/two'); fetch('/three');"),
|
||||
);
|
||||
expect(analyzed.observations.endpoints).toHaveLength(3);
|
||||
@@ -467,7 +465,7 @@ describe("web bundle analyzer", () => {
|
||||
|
||||
it("analyzes AST nodes after the former fixed node ceiling", () => {
|
||||
const source = `${";".repeat(250_001)}fetch('/last');`;
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
|
||||
expect(result.observations.endpoints).toContainEqual(
|
||||
expect.objectContaining({ value: "/last" }),
|
||||
@@ -481,7 +479,7 @@ describe("web bundle analyzer", () => {
|
||||
const name = "tool".repeat(100);
|
||||
const description = "untrusted declaration ".repeat(150);
|
||||
const propertyName = "property".repeat(100);
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
import "${specifier}";
|
||||
document.modelContext.registerTool({
|
||||
@@ -505,7 +503,7 @@ describe("web bundle analyzer", () => {
|
||||
|
||||
describe("web bundle source-map coverage", () => {
|
||||
it("reports unavailable source maps as partial without dropping requested maps", () => {
|
||||
const analysis = analyzeCapturedWebBundle(inspection("export {};"), {
|
||||
const analysis = analyzeWebBundleFixture(inspection("export {};"), {
|
||||
status: "unavailable",
|
||||
requested: 1,
|
||||
processed: 1,
|
||||
@@ -534,7 +532,7 @@ describe("web bundle source-map coverage", () => {
|
||||
});
|
||||
|
||||
it("keeps map-less captured source complete when no maps were requested", () => {
|
||||
const analysis = analyzeCapturedWebBundle(inspection("export {};"), {
|
||||
const analysis = analyzeWebBundleFixture(inspection("export {};"), {
|
||||
status: "not_requested",
|
||||
requested: 0,
|
||||
processed: 0,
|
||||
@@ -546,7 +544,7 @@ describe("web bundle source-map coverage", () => {
|
||||
});
|
||||
|
||||
it("rejects inconsistent source-map coverage counts", () => {
|
||||
const result = analyzeCapturedWebBundle(inspection("export {};"));
|
||||
const result = analyzeWebBundleFixture(inspection("export {};"));
|
||||
expect(
|
||||
webBundleAnalysisSchema.safeParse({
|
||||
...result,
|
||||
@@ -564,7 +562,7 @@ describe("web bundle source-map coverage", () => {
|
||||
|
||||
describe("web bundle static-analysis parity", () => {
|
||||
it("recognizes endpoints through nested dynamic receivers like static analysis", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection('window[recv].fetch("/nested-fetch");'),
|
||||
);
|
||||
expect(result.observations.endpoints).toContainEqual(
|
||||
@@ -573,7 +571,7 @@ describe("web bundle static-analysis parity", () => {
|
||||
});
|
||||
|
||||
it("reads open endpoints only from XMLHttpRequest method and URL pairs", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
xhr.open("GET", "/xhr-get");
|
||||
xhr.open("post", "https://xhr.example.test/submit");
|
||||
@@ -632,7 +630,7 @@ describe("web bundle API classification parity", () => {
|
||||
indexedDB.open("GET", "/storage-named-xhr");
|
||||
`;
|
||||
expect(
|
||||
analyzeCapturedWebBundle(inspection(source)).observations.endpoints.map(
|
||||
analyzeWebBundleFixture(inspection(source)).observations.endpoints.map(
|
||||
({ value }) => value,
|
||||
),
|
||||
).toEqual(["/storage-named-xhr"]);
|
||||
@@ -649,7 +647,7 @@ describe("web bundle API classification parity", () => {
|
||||
});
|
||||
|
||||
it("uses lexical receiver facts for overloaded open calls", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const popup = window;
|
||||
popup.open(url, "/preview");
|
||||
@@ -676,7 +674,7 @@ describe("web bundle API classification parity", () => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr?.open(method, "/api");
|
||||
`;
|
||||
const bundle = analyzeCapturedWebBundle(inspection(source));
|
||||
const bundle = analyzeWebBundleFixture(inspection(source));
|
||||
expect(bundle.observations.endpoints.map(({ value }) => value)).toEqual([
|
||||
"/api",
|
||||
]);
|
||||
@@ -690,7 +688,7 @@ describe("web bundle API classification parity", () => {
|
||||
});
|
||||
|
||||
it("keeps HTTP-method-named reads of provable keyed collections out of endpoints", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
axios.get("https://api.example.test/users");
|
||||
api.get("users");
|
||||
@@ -728,7 +726,7 @@ describe("web bundle API classification parity", () => {
|
||||
});
|
||||
|
||||
it("keeps undici header-store reads out of endpoint observations", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
response.headersList.get("location", true);
|
||||
request.headersList.delete("authorization");
|
||||
@@ -829,7 +827,7 @@ describe("web bundle explicit request reference forms", () => {
|
||||
"POST",
|
||||
"X",
|
||||
].sort();
|
||||
const web = analyzeCapturedWebBundle(inspection(source));
|
||||
const web = analyzeWebBundleFixture(inspection(source));
|
||||
expect(web.observations.endpoints.map(({ value }) => value).sort()).toEqual(
|
||||
expected,
|
||||
);
|
||||
@@ -869,7 +867,7 @@ describe("web bundle endpoint candidate classification", () => {
|
||||
xhr.open(method, "login");
|
||||
xhr.open("GET", "ping");
|
||||
`;
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
expect(
|
||||
result.observations.endpoints.map(({ value }) => value).sort(),
|
||||
).toEqual(["login", "ping"]);
|
||||
@@ -919,7 +917,7 @@ describe("web bundle endpoint candidate classification", () => {
|
||||
const first = captured.scripts.items[0];
|
||||
if (first === undefined) throw new Error("Missing captured script fixture");
|
||||
const secondKey = `scr_${"2".repeat(64)}`;
|
||||
const result = analyzeCapturedWebBundle({
|
||||
const result = analyzeWebBundleFixture({
|
||||
...captured,
|
||||
scripts: {
|
||||
total: 2,
|
||||
@@ -1011,7 +1009,7 @@ describe("web bundle configuration and navigation parity", () => {
|
||||
"shadowed",
|
||||
"users",
|
||||
];
|
||||
const web = analyzeCapturedWebBundle(inspection(source));
|
||||
const web = analyzeWebBundleFixture(inspection(source));
|
||||
expect(web.observations.endpoints).toEqual([]);
|
||||
expect(
|
||||
web.inferences
|
||||
@@ -1036,7 +1034,7 @@ describe("web bundle configuration and navigation parity", () => {
|
||||
api.get("users");
|
||||
`;
|
||||
const analyze = (source: string) => {
|
||||
const web = analyzeCapturedWebBundle(inspection(source));
|
||||
const web = analyzeWebBundleFixture(inspection(source));
|
||||
const staticAnalysis = analyzeJavaScriptStaticSource(source);
|
||||
return {
|
||||
web: {
|
||||
@@ -1090,7 +1088,7 @@ describe("web bundle configuration and navigation parity", () => {
|
||||
});
|
||||
|
||||
it("recognizes loadURL endpoints like static analysis", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection('window.win.loadURL("https://embedded.test/app");'),
|
||||
);
|
||||
expect(result.observations.endpoints).toContainEqual(
|
||||
@@ -1102,17 +1100,17 @@ describe("web bundle configuration and navigation parity", () => {
|
||||
describe("web bundle artifact metadata", () => {
|
||||
it("retains only a validated HTTP target origin", () => {
|
||||
expect(
|
||||
analyzeCapturedWebBundle(inspection("export {};")).capture.target_origin,
|
||||
analyzeWebBundleFixture(inspection("export {};")).capture.target_origin,
|
||||
).toBe(origin);
|
||||
|
||||
const nonHttp = inspection("export {};");
|
||||
nonHttp.target.url = "ftp://host/app";
|
||||
nonHttp.target.origin = "ftp://host";
|
||||
expect(analyzeCapturedWebBundle(nonHttp).capture.target_origin).toBeNull();
|
||||
expect(analyzeWebBundleFixture(nonHttp).capture.target_origin).toBeNull();
|
||||
});
|
||||
|
||||
it("preserves long provider media types in artifact summaries", () => {
|
||||
const result = analyzeCapturedWebBundle(inspection("export {};"));
|
||||
const result = analyzeWebBundleFixture(inspection("export {};"));
|
||||
const mediaType = `application/${"x".repeat(300)}`;
|
||||
const artifact = result.capture.source_artifacts[0] ?? {
|
||||
sha256: "0".repeat(64),
|
||||
@@ -1137,7 +1135,7 @@ describe("web bundle artifact metadata", () => {
|
||||
describe("deep captured web bundle syntax", () => {
|
||||
it("retains evidence after a parser-admitted deep property chain", () => {
|
||||
const source = `const value = root${".next".repeat(12_000)};\nimport "./last.js";\nfetch("/after");`;
|
||||
const result = analyzeCapturedWebBundle(inspection(source));
|
||||
const result = analyzeWebBundleFixture(inspection(source));
|
||||
expect(result.completeness).toMatchObject({
|
||||
status: "complete",
|
||||
parsed_scripts: 1,
|
||||
@@ -1530,7 +1528,7 @@ it("rejects a failed parse that claims visited nodes or derived facts", () => {
|
||||
});
|
||||
|
||||
it("recognizes expression-free template literals as route properties", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const routes = [
|
||||
{ path: \`score-board\`, component: ScoreBoard },
|
||||
@@ -1547,7 +1545,7 @@ it("recognizes expression-free template literals as route properties", () => {
|
||||
});
|
||||
|
||||
it("uses the shared parser for decorated captured scripts", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`@sealed class Widget {} fetch('/decorated');`),
|
||||
);
|
||||
|
||||
@@ -1562,7 +1560,7 @@ it("uses the shared parser for decorated captured scripts", () => {
|
||||
});
|
||||
|
||||
it("keeps bare module locations unresolved without inventing URL-relative paths", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
import "package-name";
|
||||
import("@scope/package");
|
||||
@@ -1590,7 +1588,7 @@ it("keeps bare module locations unresolved without inventing URL-relative paths"
|
||||
});
|
||||
|
||||
it("retains each literal importScripts argument in source order", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(
|
||||
'importScripts("first.js", dynamicValue, "second.js", "first.js");',
|
||||
),
|
||||
@@ -1604,7 +1602,7 @@ it("retains each literal importScripts argument in source order", () => {
|
||||
|
||||
describe("web metadata key semantics", () => {
|
||||
it("keeps computed metadata keys and overwrite order conservative", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const path = "description";
|
||||
const routes = [{ [path]: "/not-a-route" }, { ["path"]: "/real" }];
|
||||
@@ -1649,7 +1647,7 @@ describe("web metadata key semantics", () => {
|
||||
});
|
||||
|
||||
it("projects only exact input schema property names", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
document.modelContext.registerTool({
|
||||
name: "literal",
|
||||
@@ -1730,7 +1728,7 @@ describe("web metadata key semantics", () => {
|
||||
});
|
||||
|
||||
it("keeps missing coverage absent when parsing historical observations", () => {
|
||||
const analyzed = analyzeCapturedWebBundle(
|
||||
const analyzed = analyzeWebBundleFixture(
|
||||
inspection(
|
||||
`document.modelContext.registerTool({ name: "legacy", inputSchema: { properties: {} } });`,
|
||||
),
|
||||
@@ -1757,7 +1755,7 @@ describe("web metadata key semantics", () => {
|
||||
});
|
||||
|
||||
it("retains WebMCP declarations through optional member and call chaining", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
document.modelContext?.registerTool({ name: "optional member" });
|
||||
document.modelContext.registerTool?.({ name: "optional call" });
|
||||
@@ -1777,7 +1775,7 @@ it("retains WebMCP declarations through optional member and call chaining", () =
|
||||
});
|
||||
|
||||
it("reads expression-free template dynamic imports as chunk edges", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
import(\`./lazy.js\`);
|
||||
import("./quoted.js");
|
||||
@@ -1799,7 +1797,7 @@ it("reads expression-free template dynamic imports as chunk edges", () => {
|
||||
});
|
||||
|
||||
it("does not infer call names from dynamic computed identifiers", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const fetch = "render";
|
||||
const require = "render";
|
||||
@@ -1816,7 +1814,7 @@ it("does not infer call names from dynamic computed identifiers", () => {
|
||||
});
|
||||
|
||||
it("retains direct and literal computed call names", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
window.fetch("/direct");
|
||||
window["fetch"]("/literal");
|
||||
@@ -1841,7 +1839,7 @@ it("retains direct and literal computed call names", () => {
|
||||
});
|
||||
|
||||
it("requires WebMCP receiver and method names to occupy exact member segments", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
navigator.modelContext.registerTool({ name: "navigator" });
|
||||
local.modelContext.registerTool({ name: "exact nested" });
|
||||
@@ -1862,7 +1860,7 @@ it("requires WebMCP receiver and method names to occupy exact member segments",
|
||||
});
|
||||
|
||||
it("recognizes tRPC procedures and named GraphQL operations in captured scripts", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
const n = createTRPCClient({ links: [httpBatchLink({ url: "/api/trpc" })] });
|
||||
e.invoice.list.useQuery({ competencia: "2026-09" });
|
||||
@@ -1892,7 +1890,7 @@ it("keeps RPC lexical identity and bundled factory recognition in captured scrip
|
||||
"\nquery " +
|
||||
longOperation +
|
||||
" { users { id } }";
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
function first() { const c = createTRPCClient({}); }
|
||||
function unrelated(c) { c.users.query("select 1"); }
|
||||
@@ -1915,7 +1913,7 @@ it("keeps RPC lexical identity and bundled factory recognition in captured scrip
|
||||
});
|
||||
|
||||
it("retains distinct WebMCP descriptions and names while deduplicating equivalent properties", () => {
|
||||
const result = analyzeCapturedWebBundle(
|
||||
const result = analyzeWebBundleFixture(
|
||||
inspection(`
|
||||
document.modelContext.registerTool({ name: "lookup", description: "first", inputSchema: { properties: { alpha: {} } } });
|
||||
document.modelContext.registerTool({ name: "lookup", description: "second", inputSchema: { properties: { alpha: {} } } });
|
||||
@@ -2008,7 +2006,7 @@ it("keeps known capture omissions in compact route summaries and queryable gap f
|
||||
count: null,
|
||||
},
|
||||
);
|
||||
const report = analyzeCapturedWebBundle(captured),
|
||||
const report = analyzeWebBundleFixture(captured),
|
||||
parent = {
|
||||
evidenceId: `ev_${"a".repeat(64)}`,
|
||||
operation: "analyze_web_bundle",
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import type { WebPageInspection } from "./browserObservationSchemas.js";
|
||||
import { analyzeScript } from "./webBundleAnalyzerInspection.js";
|
||||
import {
|
||||
createWebBundleAnalysisAccumulator,
|
||||
isIncludedScript,
|
||||
type IncludedScript,
|
||||
} from "./webBundleAnalyzerState.js";
|
||||
import { buildCapturedWebBundleAnalysis } from "./webBundleAnalyzerResult.js";
|
||||
import type { WebBundleAnalysis } from "./webBundleAnalysis.js";
|
||||
import {
|
||||
webBundleScriptAnalysisSchema,
|
||||
type WebBundleScriptAnalysis,
|
||||
@@ -36,21 +32,3 @@ export const analyzeCapturedWebScript = (
|
||||
inferences: accumulator.inferences,
|
||||
});
|
||||
};
|
||||
|
||||
/** Analyze selected captured JavaScript source without execution. */
|
||||
export const analyzeCapturedWebBundle = (
|
||||
inspection: WebPageInspection,
|
||||
sourceMaps: WebBundleAnalysis["observations"]["source_maps"] = {
|
||||
status: "not_requested",
|
||||
requested: 0,
|
||||
processed: 0,
|
||||
items: [],
|
||||
},
|
||||
): WebBundleAnalysis => {
|
||||
const sourceScripts = inspection.scripts.items.filter(isIncludedScript);
|
||||
return buildCapturedWebBundleAnalysis(
|
||||
inspection,
|
||||
sourceMaps,
|
||||
sourceScripts.map(analyzeCapturedWebScript),
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { WebPageInspection } from "../../../src/domain/browserObservationSchemas.js";
|
||||
import type { WebBundleAnalysis } from "../../../src/domain/webBundleAnalysis.js";
|
||||
import { analyzeCapturedWebScript } from "../../../src/domain/webBundleAnalyzer.js";
|
||||
import { buildCapturedWebBundleAnalysis } from "../../../src/domain/webBundleAnalyzerResult.js";
|
||||
import { isIncludedScript } from "../../../src/domain/webBundleAnalyzerState.js";
|
||||
|
||||
/** Compose the production script parser and result merger for semantic fixtures. */
|
||||
export const analyzeWebBundleFixture = (
|
||||
inspection: WebPageInspection,
|
||||
sourceMaps: WebBundleAnalysis["observations"]["source_maps"] = {
|
||||
status: "not_requested",
|
||||
requested: 0,
|
||||
processed: 0,
|
||||
items: [],
|
||||
},
|
||||
): WebBundleAnalysis => {
|
||||
const sourceScripts = inspection.scripts.items.filter(isIncludedScript);
|
||||
return buildCapturedWebBundleAnalysis(
|
||||
inspection,
|
||||
sourceMaps,
|
||||
sourceScripts.map(analyzeCapturedWebScript),
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user