test(observation): share repeated observation fixtures
The incomplete-observation tests repeated the same provider setup and an empty Electron coverage tail, which pushed duplication over 3.5%. One coverage fixture and shared assertions bring the tree back under the threshold. Co-authored-by: morluto <morluto@users.noreply.github.com>
This commit is contained in:
9 files changed
+165
-214
No files matched your search
@@ -11,6 +11,7 @@ import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import {
|
||||
expectDroppedPartial,
|
||||
expectKeptPartial,
|
||||
expectOutputError,
|
||||
expectOwnerError,
|
||||
} from "./ownerObservationExpectation.fixture.js";
|
||||
import { BrowserObservationError } from "../domain/browserObservationError.js";
|
||||
@@ -80,11 +81,7 @@ it("does not let late cancellation hide invalid completed browser output", async
|
||||
provider(async () => ok(malformed)),
|
||||
input,
|
||||
);
|
||||
expect(output).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "AnalysisOutputError" },
|
||||
});
|
||||
if (!output.ok) expect(output.error).toBeInstanceOf(AnalysisOutputError);
|
||||
expectOutputError(output);
|
||||
|
||||
const controller = new AbortController();
|
||||
const late = await listBrowserTargets(
|
||||
@@ -95,11 +92,7 @@ it("does not let late cancellation hide invalid completed browser output", async
|
||||
input,
|
||||
{ signal: controller.signal },
|
||||
);
|
||||
expect(late).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "AnalysisOutputError" },
|
||||
});
|
||||
if (!late.ok) expect(late.error).toBeInstanceOf(AnalysisOutputError);
|
||||
expectOutputError(late);
|
||||
});
|
||||
|
||||
it("converts a raw page inspection retained after browser cleanup failure", async () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisOutputError,
|
||||
@@ -27,6 +28,34 @@ const scenario = browserScenarioInputSchema.parse({
|
||||
actions: [{ step_id: "settle", action: "wait_for_timeout", duration_ms: 1 }],
|
||||
});
|
||||
const capture = scriptScenarioFixture();
|
||||
const scenarioIdentity = {
|
||||
id: "scenario-fixture",
|
||||
name: "Scenario fixture",
|
||||
version: "1",
|
||||
};
|
||||
const runScenario = (
|
||||
failure: AnalysisError,
|
||||
id = { id: "fixture", name: "fixture", version: "1" },
|
||||
) =>
|
||||
captureBrowserScenario(
|
||||
{
|
||||
identity: () => id,
|
||||
captureScenario: async () => err(failure),
|
||||
},
|
||||
scenario,
|
||||
);
|
||||
const expectRetainedCapture = (
|
||||
result: Awaited<ReturnType<typeof runScenario>>,
|
||||
failure: AnalysisError,
|
||||
) => {
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) throw new Error("Expected the retained capture");
|
||||
expect(result.error).toBe(failure);
|
||||
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
|
||||
operation: "capture_browser_scenario",
|
||||
normalized_result: capture,
|
||||
});
|
||||
};
|
||||
|
||||
it("converts a retained raw scenario capture into partial Evidence", async () => {
|
||||
const failure = new AnalysisCancelledError("capture_browser_scenario", {
|
||||
@@ -35,23 +64,7 @@ it("converts a retained raw scenario capture into partial Evidence", async () =>
|
||||
capture,
|
||||
},
|
||||
});
|
||||
const provider: BrowserScenarioCapturePort = {
|
||||
identity: () => ({
|
||||
id: "scenario-fixture",
|
||||
name: "Scenario fixture",
|
||||
version: "1",
|
||||
}),
|
||||
captureScenario: async () => err(failure),
|
||||
};
|
||||
const result = await captureBrowserScenario(provider, scenario);
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error).toBe(failure);
|
||||
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
|
||||
operation: "capture_browser_scenario",
|
||||
normalized_result: capture,
|
||||
});
|
||||
}
|
||||
expectRetainedCapture(await runScenario(failure, scenarioIdentity), failure);
|
||||
});
|
||||
|
||||
it("converts a raw scenario capture retained after cleanup failure", async () => {
|
||||
@@ -69,24 +82,9 @@ it("converts a raw scenario capture retained after cleanup failure", async () =>
|
||||
},
|
||||
},
|
||||
);
|
||||
const provider: BrowserScenarioCapturePort = {
|
||||
identity: () => ({
|
||||
id: "scenario-fixture",
|
||||
name: "Scenario fixture",
|
||||
version: "1",
|
||||
}),
|
||||
captureScenario: async () => err(failure),
|
||||
};
|
||||
const result = await captureBrowserScenario(provider, scenario);
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error).toBe(failure);
|
||||
expect(result.error.cleanupIncomplete).toBe(true);
|
||||
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
|
||||
operation: "capture_browser_scenario",
|
||||
normalized_result: capture,
|
||||
});
|
||||
}
|
||||
const result = await runScenario(failure, scenarioIdentity);
|
||||
expectRetainedCapture(result, failure);
|
||||
if (!result.ok) expect(result.error.cleanupIncomplete).toBe(true);
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -137,11 +135,7 @@ it("keeps startup cancellation and its incomplete capture", async () => {
|
||||
cause: reason,
|
||||
partialObservation: partial,
|
||||
});
|
||||
const provider: BrowserScenarioCapturePort = {
|
||||
identity: () => ({ id: "fixture", name: "fixture", version: "1" }),
|
||||
captureScenario: async () => err(failure),
|
||||
};
|
||||
const result = await captureBrowserScenario(provider, scenario);
|
||||
const result = await runScenario(failure);
|
||||
expectKeptPartial(expectOwnerError(result, failure, reason), partial);
|
||||
});
|
||||
|
||||
@@ -157,11 +151,7 @@ it.each([{ steps: [undefined] }, { started_at: Number.NaN }])(
|
||||
cause: reason,
|
||||
partialObservation: partial,
|
||||
});
|
||||
const provider: BrowserScenarioCapturePort = {
|
||||
identity: () => ({ id: "fixture", name: "fixture", version: "1" }),
|
||||
captureScenario: async () => err(failure),
|
||||
};
|
||||
const result = await captureBrowserScenario(provider, scenario);
|
||||
const result = await runScenario(failure);
|
||||
expectDroppedPartial(
|
||||
expectOwnerError(result, failure, reason),
|
||||
"Browser scenario provider retained a non-JSON incomplete observation.",
|
||||
|
||||
@@ -98,17 +98,23 @@ it("preserves operation correction outside the input envelope", async () => {
|
||||
expect(execute).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("clears a non-JSON partial from the cleanup primary projection returns after retry", () => {
|
||||
const partial = { steps: [] as unknown[] };
|
||||
const primary = new AnalysisCancelledError("capture_browser_scenario", {
|
||||
const cancelledScenario = (partial: unknown) =>
|
||||
new AnalysisCancelledError("capture_browser_scenario", {
|
||||
cause: { requested: "stop during capture" },
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const composed = analysisErrorWithCleanupFailure(
|
||||
|
||||
const wrapScenarioCleanup = (primary: AnalysisCancelledError) =>
|
||||
analysisErrorWithCleanupFailure(
|
||||
primary,
|
||||
new ProviderCleanupError("fixture", ["browser"], {}),
|
||||
"capture_browser_scenario",
|
||||
);
|
||||
|
||||
it("clears a non-JSON partial from the cleanup primary projection returns after retry", () => {
|
||||
const partial = { steps: [] as unknown[] };
|
||||
const primary = cancelledScenario(partial);
|
||||
const composed = wrapScenarioCleanup(primary);
|
||||
partial.steps.push(undefined);
|
||||
const reason =
|
||||
"Browser scenario provider retained a non-JSON incomplete observation.";
|
||||
@@ -139,15 +145,8 @@ it("clears a non-JSON partial from the cleanup primary projection returns after
|
||||
|
||||
it("freezes one shared snapshot for a cleanup wrapper and its primary", () => {
|
||||
const partial = { steps: ["kept"] };
|
||||
const primary = new AnalysisCancelledError("capture_browser_scenario", {
|
||||
cause: { requested: "stop during capture" },
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const composed = analysisErrorWithCleanupFailure(
|
||||
primary,
|
||||
new ProviderCleanupError("fixture", ["browser"], {}),
|
||||
"capture_browser_scenario",
|
||||
);
|
||||
const primary = cancelledScenario(partial);
|
||||
const composed = wrapScenarioCleanup(primary);
|
||||
keepIncompleteObservation(
|
||||
composed,
|
||||
"capture_browser_scenario",
|
||||
@@ -163,10 +162,7 @@ it("freezes one shared snapshot for a cleanup wrapper and its primary", () => {
|
||||
|
||||
it("freezes a retained partial so a later mutation cannot break projection", () => {
|
||||
const partial = { steps: [] as unknown[] };
|
||||
const primary = new AnalysisCancelledError("capture_browser_scenario", {
|
||||
cause: { requested: "stop during capture" },
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const primary = cancelledScenario(partial);
|
||||
keepIncompleteObservation(
|
||||
primary,
|
||||
"capture_browser_scenario",
|
||||
|
||||
@@ -93,11 +93,7 @@ it("converts raw execution retained by provider cleanup failure into partial Evi
|
||||
{ operation: "observe_web_execution", partialObservation: execution },
|
||||
);
|
||||
const result = await new WebRuntimeService({
|
||||
identity: () => ({
|
||||
id: "web-runtime",
|
||||
name: "Runtime fixture",
|
||||
version: "1",
|
||||
}),
|
||||
identity: runtimeIdentity,
|
||||
observeExecution: async () => err(failure),
|
||||
inspectEventListeners: async () => err(failure),
|
||||
}).observe(args);
|
||||
@@ -172,16 +168,18 @@ it("retains completed execution Evidence on late abort and keeps invalid output
|
||||
if (!invalid.ok) expect(invalid.error).toBeInstanceOf(AnalysisOutputError);
|
||||
});
|
||||
|
||||
const runtimeIdentity = () => ({
|
||||
id: "web-runtime",
|
||||
name: "Runtime fixture",
|
||||
version: "1",
|
||||
});
|
||||
|
||||
const callRuntime = (
|
||||
operation: "observe" | "inspect",
|
||||
failure: AnalysisError,
|
||||
) => {
|
||||
const service = new WebRuntimeService({
|
||||
identity: () => ({
|
||||
id: "web-runtime",
|
||||
name: "Runtime fixture",
|
||||
version: "1",
|
||||
}),
|
||||
identity: runtimeIdentity,
|
||||
observeExecution: async () => err(failure),
|
||||
inspectEventListeners: async () => err(failure),
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { classifyBrowserCompleteness } from "../../domain/browserCompleteness.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisOutputError,
|
||||
@@ -12,6 +11,8 @@ import {
|
||||
electronTargetListSchema,
|
||||
inspectElectronPageInputSchema,
|
||||
} from "../../domain/javascript/electronObservation.js";
|
||||
import { emptyElectronPageCoverage } from "../../domain/javascript/electronPageInspection.fixture.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import { err, ok } from "../../domain/result.js";
|
||||
import type { ElectronObservationPort } from "./ElectronObservationPort.js";
|
||||
import {
|
||||
@@ -25,6 +26,12 @@ import {
|
||||
} from "../ownerObservationExpectation.fixture.js";
|
||||
|
||||
const identity = { id: "electron-fixture", name: "Fixture", version: "1" };
|
||||
const pageProvider = (failure: AnalysisError): ElectronObservationPort => ({
|
||||
identity: () => identity,
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_electron_targets")),
|
||||
inspectPage: async () => err(failure),
|
||||
});
|
||||
const input = inspectElectronPageInputSchema.parse({
|
||||
cdp_endpoint: "http://127.0.0.1:9222",
|
||||
target_id: "electron-page",
|
||||
@@ -45,33 +52,7 @@ const inspection = electronPageInspectionSchema.parse({
|
||||
file_path: "/app/index.html",
|
||||
attached: false,
|
||||
},
|
||||
capture_window: {
|
||||
started_at: "2026-01-01T00:00:00.000Z",
|
||||
ended_at: "2026-01-01T00:00:00.000Z",
|
||||
observation_ms: 0,
|
||||
},
|
||||
completeness: classifyBrowserCompleteness({
|
||||
policyFilteredSections: new Set(),
|
||||
attachLimitedSections: new Set(),
|
||||
truncatedSections: new Set(),
|
||||
unavailableSections: new Set(),
|
||||
excluded: [],
|
||||
droppedEvents: {
|
||||
scripts: 0,
|
||||
network_requests: 0,
|
||||
console_events: 0,
|
||||
websocket_connections: 0,
|
||||
websocket_frames: 0,
|
||||
webmcp_tools: 0,
|
||||
timeline_events: 0,
|
||||
},
|
||||
}),
|
||||
frames: [],
|
||||
dom: { total_nodes: 0, nodes: [] },
|
||||
scripts: { total: 0, items: [] },
|
||||
resources: [],
|
||||
workers: [],
|
||||
limitations: [],
|
||||
...emptyElectronPageCoverage(),
|
||||
});
|
||||
|
||||
it("converts a retained raw Electron inspection into partial Evidence", async () => {
|
||||
@@ -82,13 +63,7 @@ it("converts a retained raw Electron inspection into partial Evidence", async ()
|
||||
cleanup: "transport-closed",
|
||||
},
|
||||
});
|
||||
const provider: ElectronObservationPort = {
|
||||
identity: () => identity,
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_electron_targets")),
|
||||
inspectPage: async () => err(failure),
|
||||
};
|
||||
const result = await inspectElectronPage(provider, input);
|
||||
const result = await inspectElectronPage(pageProvider(failure), input);
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error).toBe(failure);
|
||||
@@ -121,13 +96,7 @@ it("converts a raw inspection retained by provider cleanup failure", async () =>
|
||||
},
|
||||
},
|
||||
);
|
||||
const provider: ElectronObservationPort = {
|
||||
identity: () => identity,
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_electron_targets")),
|
||||
inspectPage: async () => err(failure),
|
||||
};
|
||||
const result = await inspectElectronPage(provider, input);
|
||||
const result = await inspectElectronPage(pageProvider(failure), input);
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error).toBe(failure);
|
||||
@@ -261,13 +230,7 @@ it("keeps cancellation when the retained Electron inspection is incomplete", asy
|
||||
cause: reason,
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const provider: ElectronObservationPort = {
|
||||
identity: () => identity,
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_electron_targets")),
|
||||
inspectPage: async () => err(failure),
|
||||
};
|
||||
const result = await inspectElectronPage(provider, input);
|
||||
const result = await inspectElectronPage(pageProvider(failure), input);
|
||||
expectKeptPartial(expectOwnerError(result, failure, reason), partial);
|
||||
});
|
||||
|
||||
@@ -288,13 +251,7 @@ it.each([
|
||||
...unsafe,
|
||||
} as never,
|
||||
});
|
||||
const provider: ElectronObservationPort = {
|
||||
identity: () => identity,
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_electron_targets")),
|
||||
inspectPage: async () => err(failure),
|
||||
};
|
||||
const result = await inspectElectronPage(provider, input);
|
||||
const result = await inspectElectronPage(pageProvider(failure), input);
|
||||
expectDroppedPartial(
|
||||
expectOwnerError(result, failure, reason),
|
||||
"Electron provider retained a non-JSON incomplete observation.",
|
||||
|
||||
@@ -17,9 +17,33 @@ import {
|
||||
import {
|
||||
expectDroppedPartial,
|
||||
expectKeptPartial,
|
||||
expectOutputError,
|
||||
expectOwnerError,
|
||||
expectPreemptedCancellation,
|
||||
} from "../ownerObservationExpectation.fixture.js";
|
||||
|
||||
const observeCancelled = async (partial: unknown) => {
|
||||
const reason = { requested: "stop before runtime observation completed" };
|
||||
const failure = new AnalysisCancelledError("observe_javascript_runtime", {
|
||||
cause: reason,
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const result = await observeJavaScriptRuntime(
|
||||
{
|
||||
identity: () => ({ id: "test", name: "Test", version: "1" }),
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_javascript_runtime_targets")),
|
||||
observe: async () => err(failure),
|
||||
},
|
||||
{
|
||||
inspector_endpoint: "http://127.0.0.1:9229",
|
||||
target_id: "target",
|
||||
observation_ms: 0,
|
||||
},
|
||||
);
|
||||
return { result, failure, reason };
|
||||
};
|
||||
|
||||
it("preserves failed Inspector cleanup when cancellation occurs during observation", async () => {
|
||||
const controller = new AbortController();
|
||||
const failure = new BrowserObservationError(
|
||||
@@ -131,11 +155,7 @@ it("does not let late cancellation hide an invalid completed Inspector report",
|
||||
},
|
||||
{ inspector_endpoint: "http://127.0.0.1:9229" },
|
||||
);
|
||||
expect(output).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "AnalysisOutputError" },
|
||||
});
|
||||
if (!output.ok) expect(output.error).toBeInstanceOf(AnalysisOutputError);
|
||||
expectOutputError(output);
|
||||
|
||||
const controller = new AbortController();
|
||||
const late = await listJavaScriptRuntimeTargets(
|
||||
@@ -152,11 +172,7 @@ it("does not let late cancellation hide an invalid completed Inspector report",
|
||||
{ inspector_endpoint: "http://127.0.0.1:9229" },
|
||||
{ signal: controller.signal },
|
||||
);
|
||||
expect(late).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "AnalysisOutputError" },
|
||||
});
|
||||
if (!late.ok) expect(late.error).toBeInstanceOf(AnalysisOutputError);
|
||||
expectOutputError(late);
|
||||
});
|
||||
|
||||
it("converts a raw runtime observation retained by cleanup failure", async () => {
|
||||
@@ -314,55 +330,20 @@ it.each(["list", "observe"] as const)(
|
||||
{ signal: controller.signal },
|
||||
);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
|
||||
expect(result.error.cause).toBe(reason);
|
||||
}
|
||||
expect(providerCalls).toBe(0);
|
||||
expectPreemptedCancellation(result, reason, providerCalls);
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps cancellation when the retained runtime observation is incomplete", async () => {
|
||||
const reason = { requested: "stop before runtime observation completed" };
|
||||
const partial = { runtime: "partial", scripts: [] };
|
||||
const failure = new AnalysisCancelledError("observe_javascript_runtime", {
|
||||
cause: reason,
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const provider: JavaScriptRuntimeObservationPort = {
|
||||
identity: () => ({ id: "test", name: "Test", version: "1" }),
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_javascript_runtime_targets")),
|
||||
observe: async () => err(failure),
|
||||
};
|
||||
const result = await observeJavaScriptRuntime(provider, {
|
||||
inspector_endpoint: "http://127.0.0.1:9229",
|
||||
target_id: "target",
|
||||
observation_ms: 0,
|
||||
});
|
||||
const { result, failure, reason } = await observeCancelled(partial);
|
||||
expectKeptPartial(expectOwnerError(result, failure, reason), partial);
|
||||
});
|
||||
|
||||
it.each([{ scripts: [undefined] }, { elapsed_ms: Number.NaN }])(
|
||||
"drops a non-JSON runtime partial and keeps cancellation primary",
|
||||
async (partial) => {
|
||||
const reason = { requested: "stop before runtime observation completed" };
|
||||
const failure = new AnalysisCancelledError("observe_javascript_runtime", {
|
||||
cause: reason,
|
||||
partialObservation: partial as never,
|
||||
});
|
||||
const provider: JavaScriptRuntimeObservationPort = {
|
||||
identity: () => ({ id: "test", name: "Test", version: "1" }),
|
||||
listTargets: async () =>
|
||||
err(new AnalysisCancelledError("list_javascript_runtime_targets")),
|
||||
observe: async () => err(failure),
|
||||
};
|
||||
const result = await observeJavaScriptRuntime(provider, {
|
||||
inspector_endpoint: "http://127.0.0.1:9229",
|
||||
target_id: "target",
|
||||
observation_ms: 0,
|
||||
});
|
||||
const { result, failure, reason } = await observeCancelled(partial);
|
||||
expectDroppedPartial(
|
||||
expectOwnerError(result, failure, reason),
|
||||
"Inspector retained a non-JSON incomplete observation.",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { expect } from "vitest";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisOutputError,
|
||||
} from "../domain/analysisErrorCore.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
|
||||
@@ -30,6 +34,30 @@ export const expectKeptPartial = (
|
||||
});
|
||||
};
|
||||
|
||||
/** A completed value failed output validation, including after a late abort. */
|
||||
export const expectOutputError = (
|
||||
result: Result<unknown, AnalysisError>,
|
||||
): void => {
|
||||
expect(result).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "AnalysisOutputError" },
|
||||
});
|
||||
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisOutputError);
|
||||
};
|
||||
|
||||
/** Cancellation won before the provider ran. */
|
||||
export const expectPreemptedCancellation = (
|
||||
result: Result<unknown, AnalysisError>,
|
||||
cause: unknown,
|
||||
providerCalls: number,
|
||||
): void => {
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) throw new Error("Expected cancellation");
|
||||
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
|
||||
expect(result.error.cause).toBe(cause);
|
||||
expect(providerCalls).toBe(0);
|
||||
};
|
||||
|
||||
/** A non-JSON partial is cleared and recorded as a secondary output failure. */
|
||||
export const expectDroppedPartial = (
|
||||
error: AnalysisError,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { classifyBrowserCompleteness } from "../browserCompleteness.js";
|
||||
|
||||
/** Empty coverage tail shared by Electron page fixtures. */
|
||||
export const emptyElectronPageCoverage = (observationMs = 0) => ({
|
||||
capture_window: {
|
||||
started_at: "2026-01-01T00:00:00.000Z",
|
||||
ended_at: new Date(
|
||||
Date.parse("2026-01-01T00:00:00.000Z") + observationMs,
|
||||
).toISOString(),
|
||||
observation_ms: observationMs,
|
||||
},
|
||||
completeness: classifyBrowserCompleteness({
|
||||
policyFilteredSections: new Set(),
|
||||
attachLimitedSections: new Set(),
|
||||
truncatedSections: new Set(),
|
||||
unavailableSections: new Set(),
|
||||
excluded: [],
|
||||
droppedEvents: {
|
||||
scripts: 0,
|
||||
network_requests: 0,
|
||||
console_events: 0,
|
||||
websocket_connections: 0,
|
||||
websocket_frames: 0,
|
||||
webmcp_tools: 0,
|
||||
timeline_events: 0,
|
||||
},
|
||||
}),
|
||||
frames: [],
|
||||
dom: { total_nodes: 0, nodes: [] },
|
||||
scripts: { total: 0, items: [] },
|
||||
resources: [],
|
||||
workers: [],
|
||||
limitations: [],
|
||||
});
|
||||
@@ -29,7 +29,7 @@ import { parseMcpToolError } from "../../fixtures/mcpToolError.js";
|
||||
import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js";
|
||||
import { toolAvailabilityInventory } from "../../../src/contracts/toolOutputSchemaPrimitives.js";
|
||||
import { AnalysisCancelledError } from "../../../src/domain/analysisErrorCore.js";
|
||||
import { classifyBrowserCompleteness } from "../../../src/domain/browserCompleteness.js";
|
||||
import { emptyElectronPageCoverage } from "../../../src/domain/javascript/electronPageInspection.fixture.js";
|
||||
import type { ElectronPageInspection } from "../../../src/domain/javascript/electronObservation.js";
|
||||
import { err } from "../../../src/domain/result.js";
|
||||
|
||||
@@ -115,33 +115,7 @@ it("records completed Electron facts after final detach as server Evidence", asy
|
||||
file_path: "/tmp/index.html",
|
||||
attached: true,
|
||||
},
|
||||
capture_window: {
|
||||
started_at: "2026-01-01T00:00:00.000Z",
|
||||
ended_at: "2026-01-01T00:00:00.001Z",
|
||||
observation_ms: 1,
|
||||
},
|
||||
completeness: classifyBrowserCompleteness({
|
||||
policyFilteredSections: new Set(),
|
||||
attachLimitedSections: new Set(),
|
||||
truncatedSections: new Set(),
|
||||
unavailableSections: new Set(),
|
||||
excluded: [],
|
||||
droppedEvents: {
|
||||
scripts: 0,
|
||||
network_requests: 0,
|
||||
console_events: 0,
|
||||
websocket_connections: 0,
|
||||
websocket_frames: 0,
|
||||
webmcp_tools: 0,
|
||||
timeline_events: 0,
|
||||
},
|
||||
}),
|
||||
frames: [],
|
||||
dom: { total_nodes: 0, nodes: [] },
|
||||
scripts: { total: 0, items: [] },
|
||||
resources: [],
|
||||
workers: [],
|
||||
limitations: [],
|
||||
...emptyElectronPageCoverage(1),
|
||||
};
|
||||
const provider: ElectronObservationPort = {
|
||||
identity: () => ({
|
||||
|
||||
Reference in new issue
Block a user