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:
Cursor Agentandmorluto committed 2026-10-20 20:11:03 +00:00
1 parent 2775bf4e41
commit d077d879cc
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",
+8 -10
View File
@@ -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: [],
});
+2 -28
View File
@@ -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: () => ({