mirror of
https://github.com/software-mansion/argent.git
synced 2026-09-14 19:27:14 +08:00
083947111b
## Summary Adds network inspection for Chromium (CDP) devices by extending the **existing** RN network tools rather than adding a new one — so there's one network-viewing surface across platforms. - **`view-network-logs`** and **`view-network-request-details`** now also accept a `chromium-cdp-<port>` `device_id`. They dispatch on the device id (the same pattern the ported `debugger-*` tools and `gesture-tap` use): RN → the Metro-injected `fetch` interceptor; Chromium → the browser's native CDP `Network` recording for the **active tab**. Same flags, same output shape. - Both widen their capability from RN-only to `DEBUGGER_TOOL_CAPABILITY` (apple + android + chromium). ## How the Chromium side works A lean **`NetworkManager`** (`chromium-server/network.ts`) keeps a passive, always-on capped ring buffer fed by the page's CDP `Network` events, re-attached on tab switch so it follows the active tab. No in-app injection (the browser exposes `Network` natively). `view-network-request-details` fetches the response body on demand via `Network.getResponseBody`, and reuses the existing header-redaction. **Read-only**, matching the `view-network-*` contract. Per review, the earlier cut's standalone `chromium-network` tool and its Fetch-based **routing / abort / mock / HAR** were **removed** — the read capability on the existing tools is sufficient. > Rebased onto `main` after #334 (tabs) merged — diff is network-only. ## Test plan - [x] `NetworkManager`: recording (fields/duration/headers/failed, oldest-first), `get()`, `reattach` (Network.enable), `dispose` (disable + detach). - [x] Chromium branch of both view tools: capability now admits chromium, `services()` routing, paginated render matching the RN format, no-traffic message, header redaction, body via `Network.getResponseBody`, not-found. - [x] Updated the RN locked-tools registry test (these two are no longer RN-locked; 15→13) + a positive assertion they now admit Chromium. RN integration tests unchanged/passing. - [x] Full suite **1136 pass**; `tsc --build` + `typecheck:tests` + prettier clean; tool-description gate **9.25 ≥ 9.0**. - [x] **Live (Chrome for Testing)**: `view-network-logs --device_id chromium-cdp-9222` → `=== NETWORK LOGS (page 1/1, 1 total) === {id: …} "GET example.com" 200 Document`; `view-network-request-details` → full request/response headers + body via `getResponseBody`.
147 lines
6.6 KiB
TypeScript
147 lines
6.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import {
|
|
DEBUGGER_TOOL_CAPABILITY,
|
|
RN_ONLY_TOOL_CAPABILITY,
|
|
debuggerServiceRef,
|
|
} from "../src/tools/debugger/debugger-service-ref";
|
|
import { CHROMIUM_JS_RUNTIME_DEBUGGER_NAMESPACE } from "../src/blueprints/chromium-js-runtime-debugger";
|
|
import { assertSupported, UnsupportedOperationError } from "../src/utils/capability";
|
|
import { resolveDevice } from "../src/utils/device-info";
|
|
|
|
// All tools that must reject Chromium at the HTTP capability gate. Pull the
|
|
// ToolDefinition directly so any future drift (someone re-adds an `chromium:`
|
|
// block on one of these) breaks this single test instead of slipping into a
|
|
// release. Kept exhaustive on purpose — a per-tool assertion is cheap and the
|
|
// list is the contract.
|
|
import { debuggerComponentTreeTool } from "../src/tools/debugger/debugger-component-tree";
|
|
import { debuggerReloadMetroTool } from "../src/tools/debugger/debugger-reload-metro";
|
|
import { debuggerInspectElementTool } from "../src/tools/debugger/debugger-inspect-element";
|
|
import { networkLogsTool } from "../src/tools/network/network-logs";
|
|
import { networkRequestTool } from "../src/tools/network/network-request";
|
|
import { reactProfilerAnalyzeTool } from "../src/tools/profiler/react/react-profiler-analyze";
|
|
import { reactProfilerComponentSourceTool } from "../src/tools/profiler/react/react-profiler-component-source";
|
|
import { reactProfilerCpuSummaryTool } from "../src/tools/profiler/react/react-profiler-cpu-summary";
|
|
import { reactProfilerFiberTreeTool } from "../src/tools/profiler/react/react-profiler-fiber-tree";
|
|
import { reactProfilerRendersTool } from "../src/tools/profiler/react/react-profiler-renders";
|
|
import { profilerCpuQueryTool } from "../src/tools/profiler/query/profiler-cpu-query";
|
|
import { profilerCommitQueryTool } from "../src/tools/profiler/query/profiler-commit-query";
|
|
import { profilerStackQueryTool } from "../src/tools/profiler/query/profiler-stack-query";
|
|
import { profilerLoadTool } from "../src/tools/profiler/query/profiler-load";
|
|
import { profilerCombinedReportTool } from "../src/tools/profiler/combined/profiler-combined-report";
|
|
|
|
const CHROMIUM_ID = "chromium-cdp-19222";
|
|
const IOS_ID = "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA";
|
|
const ANDROID_ID = "emulator-5554";
|
|
|
|
describe("debuggerServiceRef — platform dispatch", () => {
|
|
it("routes a Chromium device id to the ChromiumJsRuntimeDebugger blueprint", () => {
|
|
const ref = debuggerServiceRef({ port: 8081, device_id: CHROMIUM_ID });
|
|
expect(ref).toMatchObject({
|
|
urn: `${CHROMIUM_JS_RUNTIME_DEBUGGER_NAMESPACE}:${CHROMIUM_ID}`,
|
|
options: { device: resolveDevice(CHROMIUM_ID) },
|
|
});
|
|
});
|
|
|
|
it("routes an iOS UDID to the Metro-driven JsRuntimeDebugger blueprint", () => {
|
|
const ref = debuggerServiceRef({ port: 8081, device_id: IOS_ID });
|
|
expect(ref).toBe(`JsRuntimeDebugger:8081:${IOS_ID}`);
|
|
});
|
|
|
|
it("routes an Android serial to the Metro-driven JsRuntimeDebugger blueprint", () => {
|
|
const ref = debuggerServiceRef({ port: 8082, device_id: ANDROID_ID });
|
|
expect(ref).toBe(`JsRuntimeDebugger:8082:${ANDROID_ID}`);
|
|
});
|
|
|
|
it("tolerates a missing device_id — falls back to Metro URN so existing callers don't crash", () => {
|
|
// Mirrors the original template-literal behavior: `JsRuntimeDebugger:8081:undefined`
|
|
// is ugly but doesn't blow up at the dispatch site. Pre-chromium tests
|
|
// hit this path and relied on it.
|
|
const ref = debuggerServiceRef({ port: 8081 });
|
|
expect(typeof ref).toBe("string");
|
|
expect(ref as string).toMatch(/^JsRuntimeDebugger:8081:/);
|
|
});
|
|
});
|
|
|
|
describe("debugger tool capability gating — chromium", () => {
|
|
const chromiumDevice = resolveDevice(CHROMIUM_ID);
|
|
const iosDevice = resolveDevice(IOS_ID);
|
|
|
|
it("DEBUGGER_TOOL_CAPABILITY admits a Chromium device (ported tools)", () => {
|
|
expect(() =>
|
|
assertSupported("debugger-evaluate", DEBUGGER_TOOL_CAPABILITY, chromiumDevice)
|
|
).not.toThrow();
|
|
});
|
|
|
|
it("DEBUGGER_TOOL_CAPABILITY still admits iOS — port did not regress mobile support", () => {
|
|
expect(() =>
|
|
assertSupported("debugger-evaluate", DEBUGGER_TOOL_CAPABILITY, iosDevice)
|
|
).not.toThrow();
|
|
});
|
|
|
|
it("RN_ONLY_TOOL_CAPABILITY rejects a Chromium device (locked-out tools)", () => {
|
|
expect(() =>
|
|
assertSupported("debugger-component-tree", RN_ONLY_TOOL_CAPABILITY, chromiumDevice)
|
|
).toThrow(UnsupportedOperationError);
|
|
});
|
|
|
|
it("RN_ONLY_TOOL_CAPABILITY's rejection message names the tool and platform", () => {
|
|
try {
|
|
assertSupported("react-profiler-renders", RN_ONLY_TOOL_CAPABILITY, chromiumDevice);
|
|
throw new Error("expected throw");
|
|
} catch (err) {
|
|
const msg = (err as Error).message;
|
|
expect(msg).toContain("react-profiler-renders");
|
|
expect(msg).toContain("chromium");
|
|
expect(msg).toContain("app");
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("RN-only tool registry — every locked tool actually rejects Chromium", () => {
|
|
const chromiumDevice = resolveDevice("chromium-cdp-19222");
|
|
|
|
// Source of truth for what must stay locked. If a tool is added/removed
|
|
// here, the maintainer is making an explicit Chromium-support decision.
|
|
const LOCKED_TOOLS = [
|
|
debuggerComponentTreeTool,
|
|
debuggerReloadMetroTool,
|
|
debuggerInspectElementTool,
|
|
reactProfilerAnalyzeTool,
|
|
reactProfilerComponentSourceTool,
|
|
reactProfilerCpuSummaryTool,
|
|
reactProfilerFiberTreeTool,
|
|
reactProfilerRendersTool,
|
|
profilerCpuQueryTool,
|
|
profilerCommitQueryTool,
|
|
profilerStackQueryTool,
|
|
profilerLoadTool,
|
|
profilerCombinedReportTool,
|
|
];
|
|
|
|
it.each(LOCKED_TOOLS.map((t) => [t.id, t] as const))(
|
|
"%s declares a capability and rejects Chromium",
|
|
(_id, tool) => {
|
|
expect(tool.capability).toBeDefined();
|
|
expect(() => assertSupported(tool.id, tool.capability!, chromiumDevice)).toThrow(
|
|
UnsupportedOperationError
|
|
);
|
|
}
|
|
);
|
|
|
|
it("matches the spec count — exactly 13 device-bound RN/iOS tools are locked", () => {
|
|
// Add to LOCKED_TOOLS above when locking a new tool; this guards against
|
|
// silent omissions. react-profiler-{start,stop,status} are factory-built
|
|
// and not exported as plain ToolDefinitions, so they're absent here even
|
|
// though they're locked — counted separately in the PR description.
|
|
// view-network-logs / view-network-request-details were UNLOCKED for
|
|
// Chromium (served via the Chromium server's Network recording) — see below.
|
|
expect(LOCKED_TOOLS).toHaveLength(13);
|
|
});
|
|
|
|
it("view-network-logs / view-network-request-details now ALSO support Chromium", () => {
|
|
for (const tool of [networkLogsTool, networkRequestTool]) {
|
|
expect(() => assertSupported(tool.id, tool.capability!, chromiumDevice)).not.toThrow();
|
|
}
|
|
});
|
|
});
|