Files
reverse-engineering-anything/src/application/javascript/ElectronObservationService.test.ts
T
morluto 5044e20171 test: focus diagnostics and evidence checks on behavior (#9303)
* test: focus configuration diagnostics on their owners

Preserve shape errors, selected paths, recovery guidance, and unchanged-file behavior across parser, setup, and uninstall boundaries.

* test: focus artifact and evidence checks on behavior

Retain format, identity, malformed-input, and cleanup coverage while removing fixed prose and closing the admitted test source.

* refactor(debugger): use configured session admission limits

* test: focus evidence and diagnostics on behavior

* fix(test): restore verifier export and formatting

* test(config): verify debugger limit ranges

* test(rizin): keep fixture executable authoritative

* test(rizin): isolate debugger fixture environment
2026-11-08 16:39:20 +00:00

277 lines
8.9 KiB
TypeScript

import { expect, it } from "vitest";
import {
AnalysisCancelledError,
AnalysisOutputError,
} from "../../domain/analysisErrorCore.js";
import { ProviderCleanupError } from "../../domain/providerCleanupError.js";
import { parseEvidence } from "../../domain/evidence.js";
import {
electronPageInspectionSchema,
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 {
inspectElectronPage,
listElectronTargets,
} from "./ElectronObservationService.js";
import {
expectDroppedPartial,
expectKeptPartial,
expectOwnerError,
} from "../../../tests/fixtures/ownerObservationExpectation.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",
observation_ms: 0,
});
const inspection = electronPageInspectionSchema.parse({
browser: {
product: "Electron",
protocol_version: "1.3",
revision: "fixture",
user_agent: "Electron fixture",
js_version: "V8 fixture",
},
target: {
target_id: "electron-page",
type: "page",
title: "Fixture",
file_path: "/app/index.html",
attached: false,
},
...emptyElectronPageCoverage(),
});
it("converts a retained raw Electron inspection into partial Evidence", async () => {
const failure = new AnalysisCancelledError("inspect_electron_page", {
partialObservation: {
kind: "electron-page-observation",
inspection,
cleanup: "transport-closed",
},
});
const result = await inspectElectronPage(pageProvider(failure), input);
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBe(failure);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_electron_page",
normalized_result: {
...inspection,
limitations: [
"REA closed its CDP transport; this does not imply target shutdown.",
],
},
limitations: expect.arrayContaining([
"REA closed its CDP transport; this does not imply target shutdown.",
]),
});
}
});
it("converts a raw inspection retained by provider cleanup failure", async () => {
const failure = new ProviderCleanupError(
"rea-cdp-electron",
["electron-page"],
{ reason: "target detach failed" },
{
operation: "inspect_electron_page",
partialObservation: {
kind: "electron-page-observation",
inspection,
cleanup: "incomplete",
},
},
);
const result = await inspectElectronPage(pageProvider(failure), input);
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: "inspect_electron_page",
normalized_result: {
...inspection,
limitations: ["CDP transport cleanup remains incomplete."],
},
limitations: expect.arrayContaining([
"CDP transport cleanup remains incomplete.",
]),
});
}
});
it("returns a typed output error for malformed Electron target output after abort", async () => {
const controller = new AbortController();
const malformed = {
browser: {
product: "Electron",
protocol_version: "1.3",
revision: "fixture",
user_agent: "Electron fixture",
js_version: "V8 fixture",
},
targets: [],
excluded: { unsupported_url: 0, non_page: 0 },
limitations: [() => undefined],
} as unknown as ReturnType<typeof electronTargetListSchema.parse>;
const provider: ElectronObservationPort = {
identity: () => identity,
listTargets: async () => {
controller.abort();
return { ok: true, value: malformed };
},
inspectPage: async () =>
err(new AnalysisCancelledError("inspect_electron_page")),
};
const result = await listElectronTargets(
provider,
{
cdp_endpoint: "http://127.0.0.1:9222",
},
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisOutputError);
});
it("retains completed target facts when cancellation arrives before Evidence publication", async () => {
const controller = new AbortController();
const reason = { requested: "stop after listing targets" };
const targets = electronTargetListSchema.parse({
browser: inspection.browser,
targets: [],
excluded: { unsupported_url: 0, non_page: 0 },
limitations: [],
});
const provider: ElectronObservationPort = {
identity: () => identity,
listTargets: async () => {
controller.abort(reason);
return ok(targets);
},
inspectPage: async () =>
err(new AnalysisCancelledError("inspect_electron_page")),
};
const result = await listElectronTargets(
provider,
{ cdp_endpoint: input.cdp_endpoint },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "list_electron_targets",
provider: identity,
parameters: { cdp_endpoint: input.cdp_endpoint },
confidence: "observed",
authority: "external-service",
environment: {
id: `${inspection.browser.product}@${inspection.browser.revision}`,
platform: "unknown",
architecture: "unknown",
isolation: "none",
},
limitations: expect.arrayContaining([
expect.stringMatching(/platform.*architecture.*not observed/iu),
]),
normalized_result: targets,
});
}
});
it.each(["list", "inspect"] as const)(
"preserves a pre-abort reason before Electron %s provider work",
async (kind) => {
const reason = new Error(`stop Electron ${kind}`);
const controller = new AbortController();
controller.abort(reason);
let providerCalls = 0;
const provider: ElectronObservationPort = {
identity: () => identity,
listTargets: async () => {
providerCalls += 1;
return err(new AnalysisCancelledError("list_electron_targets"));
},
inspectPage: async () => {
providerCalls += 1;
return err(new AnalysisCancelledError("inspect_electron_page"));
},
};
const result =
kind === "list"
? await listElectronTargets(
provider,
{ cdp_endpoint: input.cdp_endpoint },
{ signal: controller.signal },
)
: await inspectElectronPage(provider, input, {
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);
},
);
it("keeps cancellation when the retained Electron inspection is incomplete", async () => {
const reason = { requested: "stop before page inspection completed" };
// A JSON-safe but incomplete inspection cannot be converted into Evidence.
const partial = {
kind: "electron-page-observation",
inspection: { target_id: "electron-page" },
cleanup: "incomplete",
};
const failure = new AnalysisCancelledError("inspect_electron_page", {
cause: reason,
partialObservation: partial as never,
});
const result = await inspectElectronPage(pageProvider(failure), input);
expectKeptPartial(expectOwnerError(result, failure, reason), partial);
});
it.each([
{ inspection: { requests: Number.NaN }, cleanup: "incomplete" as const },
{
inspection: { scripts: [undefined] },
cleanup: "transport-closed" as const,
},
])(
"drops a non-JSON Electron inspection and keeps cancellation primary",
async (unsafe) => {
const reason = { requested: "stop before page inspection completed" };
const failure = new AnalysisCancelledError("inspect_electron_page", {
cause: reason,
partialObservation: {
kind: "electron-page-observation",
...unsafe,
} as never,
});
const result = await inspectElectronPage(pageProvider(failure), input);
expectDroppedPartial(
expectOwnerError(result, failure, reason),
"Electron provider retained a non-JSON incomplete observation.",
);
},
);