From d2dc3cfc34e87d008b4b09abbbd3593eacdd2741 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 24 Oct 2026 04:24:00 +0800 Subject: [PATCH] refactor(tests): separate fixtures and registration groups --- .../PlaywrightBrowserScenarioProvider.test.ts | 72 ++++++++++--------- .../javascript/javascriptRpcEndpoints.test.ts | 2 + .../mcp/browserComparisonInput.test.ts | 61 +++++++++------- .../javascriptRuntimeObservationMcp.test.ts | 17 ++++- tests/boundary/mcp/promptMcp.test.ts | 13 +++- .../native/lldbCallTracerFailures.test.ts | 48 +++++++------ 6 files changed, 128 insertions(+), 85 deletions(-) diff --git a/src/browser/PlaywrightBrowserScenarioProvider.test.ts b/src/browser/PlaywrightBrowserScenarioProvider.test.ts index 850d6ef84f..07b095636e 100644 --- a/src/browser/PlaywrightBrowserScenarioProvider.test.ts +++ b/src/browser/PlaywrightBrowserScenarioProvider.test.ts @@ -238,45 +238,47 @@ class FakeSession implements BrowserScenarioSessionPort { } } +const capturedResponseBodyEvents = (): readonly BrowserScenarioEvent[] => [ + { + sequence: 1, + step_index: 0, + kind: "response", + transaction_id: "request-1", + redirected_from_transaction_id: null, + method: "GET", + url: sanitizeBrowserUrl("https://app.example.test/main.js"), + resource_type: "script", + header_names: [], + status: 200, + failure: null, + }, + { + sequence: 2, + step_index: 0, + kind: "network-content", + transaction_id: "request-1", + source_event_sequence: 1, + phase: "response", + headers: { state: "not_requested" }, + body: { + state: "captured", + representation: "playwright-response-body-bytes", + encoding: "base64", + content: "", + bytes: 0, + sha256: + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + media_type: "text/javascript", + redacted: false, + }, + }, +]; + describe("PlaywrightBrowserScenarioProvider", () => { it("reports response-body provenance uncertainty without marking event coverage missing", async () => { const session = new FakeSession("launch"); const selected = scenario(); - session.eventItems = [ - { - sequence: 1, - step_index: 0, - kind: "response", - transaction_id: "request-1", - redirected_from_transaction_id: null, - method: "GET", - url: sanitizeBrowserUrl("https://app.example.test/main.js"), - resource_type: "script", - header_names: [], - status: 200, - failure: null, - }, - { - sequence: 2, - step_index: 0, - kind: "network-content", - transaction_id: "request-1", - source_event_sequence: 1, - phase: "response", - headers: { state: "not_requested" }, - body: { - state: "captured", - representation: "playwright-response-body-bytes", - encoding: "base64", - content: "", - bytes: 0, - sha256: - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - media_type: "text/javascript", - redacted: false, - }, - }, - ]; + session.eventItems = capturedResponseBodyEvents(); const input = browserScenarioSchema.parse({ ...selected, capture: { diff --git a/src/domain/javascript/javascriptRpcEndpoints.test.ts b/src/domain/javascript/javascriptRpcEndpoints.test.ts index cb5e97cef5..65d15db1d6 100644 --- a/src/domain/javascript/javascriptRpcEndpoints.test.ts +++ b/src/domain/javascript/javascriptRpcEndpoints.test.ts @@ -156,7 +156,9 @@ describe("tRPC procedure recognition", () => { }, ]); }); +}); +describe("tRPC procedure recognition", () => { it("recognizes vanilla client calls and link URLs only in sources carrying a tRPC marker", () => { expect( rpcEndpoints(` diff --git a/tests/boundary/mcp/browserComparisonInput.test.ts b/tests/boundary/mcp/browserComparisonInput.test.ts index eac705bb15..4930e81b43 100644 --- a/tests/boundary/mcp/browserComparisonInput.test.ts +++ b/tests/boundary/mcp/browserComparisonInput.test.ts @@ -55,6 +55,39 @@ async function capturePassivePair( }; } +function invalidComparisonInputs( + passive: Awaited>, + scenario: (typeof contract.examples)[number]["input"], +) { + const scenarioCapture = browserScenarioCaptureSchema.parse( + scenario.before_scenario, + ); + return [ + {}, + { before: passive.before }, + { before: { inspection: {} }, after: passive.after }, + { + before: passive.before, + after: { ...passive.after, webmcp: {} }, + }, + { before_scenario: {}, after_scenario: {} }, + { before_scenario: scenario.before_scenario }, + { ...passive, unexpected: true }, + { + ...scenario, + before_scenario: { ...scenarioCapture, steps: [{}] }, + }, + { + ...scenario, + normalization: { + rules: [ + { rule_id: "bad", artifacts: [], match: "x", replacement: "y" }, + ], + }, + }, + ]; +} + describe("browser comparison input boundary", () => { it("advertises producer captures and agrees with SDK validation on both comparison families", async () => { const browser = await startFakeCdpBrowser({ sensitiveShapes: true }); @@ -105,33 +138,7 @@ describe("browser comparison input boundary", () => { const withoutNormalization = Object.fromEntries( Object.entries(scenario).filter(([key]) => key !== "normalization"), ); - const scenarioCapture = browserScenarioCaptureSchema.parse( - scenario.before_scenario, - ); - const invalid = [ - {}, - { before: passive.before }, - { before: { inspection: {} }, after: passive.after }, - { - before: passive.before, - after: { ...passive.after, webmcp: {} }, - }, - { before_scenario: {}, after_scenario: {} }, - { before_scenario: scenario.before_scenario }, - { ...passive, unexpected: true }, - { - ...scenario, - before_scenario: { ...scenarioCapture, steps: [{}] }, - }, - { - ...scenario, - normalization: { - rules: [ - { rule_id: "bad", artifacts: [], match: "x", replacement: "y" }, - ], - }, - }, - ]; + const invalid = invalidComparisonInputs(passive, scenario); // Strict clients reject combinators and dependentRequired, so the // projection states the groups in its description and leaves group // completeness and exclusion to the canonical runtime parser. diff --git a/tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts b/tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts index 5def338696..c01768fa0e 100644 --- a/tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts +++ b/tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts @@ -37,6 +37,14 @@ describe("JavaScript runtime observation MCP tools", () => { ); }); + registerRuntimeParameterContract(resources); + registerRuntimeMetadataContract(); + registerRetainedRuntimeEvidence(resources, temporary); +}); + +function registerRuntimeParameterContract( + resources: Array<{ close(): Promise }>, +): void { test("attributes V8 role and target disagreements to the parameter that differs", async () => { const session = createTestBinarySession(() => { throw new Error("No provider expected"); @@ -118,7 +126,9 @@ describe("JavaScript runtime observation MCP tools", () => { } await client.ping(); }); +} +function registerRuntimeMetadataContract(): void { test("accepts long caller windows and complete observation metadata", () => { const repeated = (count: number): string[] => Array.from({ length: count }, (_, index) => `item-${index}`); @@ -190,7 +200,12 @@ describe("JavaScript runtime observation MCP tools", () => { }), ).toMatchObject({ unknowns, limitations }); }); +} +function registerRetainedRuntimeEvidence( + resources: Array<{ close(): Promise }>, + temporary: string[], +): void { test("lists and observes one target as retained Evidence", async () => { const root = await createTestTempDirectory("rea-v8-mcp-"); temporary.push(root); @@ -255,7 +270,7 @@ describe("JavaScript runtime observation MCP tools", () => { expect(direct.ok).toBe(true); if (direct.ok) expect(evidenceId).toBe(direct.value.evidence_id); }); -}); +} const assertSdkObservationSchema = async ( client: Client, diff --git a/tests/boundary/mcp/promptMcp.test.ts b/tests/boundary/mcp/promptMcp.test.ts index 43fc83dfa3..2d9d101c76 100644 --- a/tests/boundary/mcp/promptMcp.test.ts +++ b/tests/boundary/mcp/promptMcp.test.ts @@ -61,6 +61,12 @@ afterEach(async () => { }); describe("guided prompts over MCP", () => { + registerPromptDiscoveryParameterContract(); + registerPromptRenderingContracts(); + registerPromptInputContracts(); +}); + +function registerPromptDiscoveryParameterContract(): void { it("classifies malformed discovery parameters separately from handler failures", async () => { const session = fixtureSession(); const server = createServer({ kind: "session", session }); @@ -126,6 +132,9 @@ describe("guided prompts over MCP", () => { error: { code: -32603, message: "injected internal failure" }, }); }); +} + +function registerPromptRenderingContracts(): void { it("lists and renders all workflows without changing the tool inventory", async () => { const session = fixtureSession(); const client = await connect(createServer({ kind: "session", session })); @@ -232,7 +241,9 @@ describe("guided prompts over MCP", () => { expect(content.text).not.toContain("Run the caller-provided scenario"); expect(executions).toBe(0); }); +} +function registerPromptInputContracts(): void { it("rejects invalid prompt requests and safely handles non-completable arguments", async () => { let executions = 0; const session = fixtureSession(() => { @@ -283,7 +294,7 @@ describe("guided prompts over MCP", () => { }); expect(executions).toBe(0); }); -}); +} it("preserves caller-selected paths and verbatim crash signals", async () => { const directory = await createTestTempDirectory("rea-prompt-exact-context-"); diff --git a/tests/boundary/providers/native/lldbCallTracerFailures.test.ts b/tests/boundary/providers/native/lldbCallTracerFailures.test.ts index 59d2a2c76f..1a1de0c009 100644 --- a/tests/boundary/providers/native/lldbCallTracerFailures.test.ts +++ b/tests/boundary/providers/native/lldbCallTracerFailures.test.ts @@ -605,25 +605,21 @@ describe("LLDB process exit while output is still open", () => { ); }); -describe("LLDB process exit at output-close loop completion", () => { - for (const abort of [false, true]) - it.skipIf(process.platform === "win32")( - `retains completed trace facts after output closure (cancelled=${String(abort)})`, - async () => { - const fixtureRoot = await mkdtemp( - join(tmpdir(), "rea-lldb-complete-output-"), - ); - const fakeLldb = join(fixtureRoot, "fake-lldb"); - const completed = { - ...successfulTracerOutput, - target_output: { - ...successfulTracerOutput.target_output, - stdout_bytes: 2, - }, - }; - await writeFile( - fakeLldb, - `#!${process.execPath} +const completedOutputCloseFixture = async () => { + const fixtureRoot = await mkdtemp( + join(tmpdir(), "rea-lldb-complete-output-"), + ); + const fakeLldb = join(fixtureRoot, "fake-lldb"); + const completed = { + ...successfulTracerOutput, + target_output: { + ...successfulTracerOutput.target_output, + stdout_bytes: 2, + }, + }; + await writeFile( + fakeLldb, + `#!${process.execPath} const fs = require("node:fs"); const { spawnSync } = require("node:child_process"); const command = process.argv.at(-1); @@ -639,8 +635,18 @@ fs.writeFileSync(config.observation_path, JSON.stringify({ kind: "event", event: fs.writeFileSync(config.result_path, JSON.stringify(result)); process.exit(0); `, - { mode: 0o700 }, - ); + { mode: 0o700 }, + ); + return { fixtureRoot, fakeLldb, completed }; +}; + +describe("LLDB process exit at output-close loop completion", () => { + for (const abort of [false, true]) + it.skipIf(process.platform === "win32")( + `retains completed trace facts after output closure (cancelled=${String(abort)})`, + async () => { + const { fixtureRoot, fakeLldb, completed } = + await completedOutputCloseFixture(); const controller = new AbortController(); const reason = { requested: "stop after completed output closure" }; let interrupted = false;