repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/chrome-cdp/__tests__/harness.test.ts
Rawimport { resolve } from "node:path";
import { initTheme, keyHint } from "@earendil-works/pi-coding-agent";
import { afterEach, beforeAll, describe, expect, it } from "vitest";
import { createTestSession, type TestSession } from "../../../test/harness";
const extensionPath = resolve(import.meta.dirname, "../index.ts");
describe("chrome-cdp Pi integration", () => {
let t: TestSession | undefined;
beforeAll(() => initTheme("default", false));
afterEach(() => {
t?.dispose();
t = undefined;
});
it("registers an inactive tool and toggles it without starting Chrome", async () => {
t = await createTestSession({ extensions: [extensionPath] });
const runner = t.session.extensionRunner;
const extension = runner.extensions[0];
expect(extension?.path).toBe(extensionPath);
const tool = extension?.tools.get("chrome_cdp")?.definition;
expect(tool?.description).toContain("Chrome DevTools Protocol");
expect(
tool?.promptGuidelines?.some((line) => line.includes("sessionId")),
).toBe(true);
expect(t.session.getActiveToolNames()).not.toContain("chrome_cdp");
const command = runner.getCommand("chrome");
expect(command).toBeDefined();
const ctx = {
...runner.createCommandContext(),
mode: "print" as const,
hasUI: false,
};
await command?.handler("", ctx);
expect(t.session.getActiveToolNames()).toContain("chrome_cdp");
await command?.handler("", ctx);
expect(t.session.getActiveToolNames()).not.toContain("chrome_cdp");
await command?.handler("close", ctx);
expect(t.session.getActiveToolNames()).not.toContain("chrome_cdp");
});
it("warns cheaply when Chrome binary is unavailable", async () => {
t = await createTestSession({
extensions: [extensionPath],
env: { PATH: "/nonexistent" },
});
const runner = t.session.extensionRunner;
const command = runner.getCommand("chrome");
const ctx = {
...runner.createCommandContext(),
mode: "print" as const,
hasUI: false,
};
await command?.handler("", ctx);
expect(t.session.getActiveToolNames()).toContain("chrome_cdp");
const notifications = t.events.uiCallsFor("notify");
expect(String(notifications.at(-2)?.args[0])).toContain(
"Chrome unavailable: Chrome not found",
);
expect(notifications.at(-2)?.args[1]).toBe("warning");
});
it("renders commands without exposing CDP parameters", async () => {
t = await createTestSession({ extensions: [extensionPath] });
const tool =
t.session.extensionRunner.extensions[0]?.tools.get(
"chrome_cdp",
)?.definition;
const theme = {
fg: (_color: string, value: string) => value,
bold: (value: string) => value,
};
const call = tool?.renderCall?.(
{
operations: [
{
kind: "cdp",
method: "Browser.getVersion",
params: { marker: "private-value" },
},
],
},
theme as never,
{ expanded: true } as never,
);
const text = call?.render(100).join("\n");
expect(text).toContain("Browser.getVersion");
expect(text).not.toContain("private-value");
});
it("labels batches, advertises expansion, and previews results only when expanded", async () => {
t = await createTestSession({ extensions: [extensionPath] });
const tool =
t.session.extensionRunner.extensions[0]?.tools.get(
"chrome_cdp",
)?.definition;
expect(tool).toBeDefined();
const theme = {
fg: (_color: string, value: string) => value,
bold: (value: string) => value,
};
const args = {
operations: [
{
kind: "cdp",
method: "Page.navigate",
params: { url: "https://private.example" },
},
{ kind: "wait", event: "Page.loadEventFired" },
],
};
const call = (expanded: boolean) =>
tool
?.renderCall?.(args as never, theme as never, { expanded } as never)
.render(100)
.join("\n");
expect(call(false)).toContain(" Chrome");
expect(call(false)).toContain("Page.navigate");
expect(call(false)).toContain("wait Page.loadEventFired");
expect(call(false)).toContain(keyHint("app.tools.expand", "to expand"));
expect(call(false)).not.toContain("private.example");
expect(call(true)).not.toContain("to expand");
const result = {
content: [
{
type: "text" as const,
text: JSON.stringify({
output: [
{
command: "Browser.getVersion",
raw: { id: 2, result: { product: "Chrome/154" } },
},
],
events: [],
}),
},
],
details: {
completed: 1,
total: 1,
eventCount: 0,
operations: ["Browser.getVersion"],
},
};
const rendered = (expanded: boolean) =>
tool
?.renderResult?.(
result,
{ expanded, isPartial: false } as never,
theme as never,
{ isError: false } as never,
)
.render(100)
.join("\n");
expect(rendered(false)).not.toContain("Chrome/154");
expect(rendered(true)).toContain("Chrome/154");
expect(rendered(true)).toContain("Browser.getVersion");
const status = {
...result,
details: {
...result.details,
operations: ["status"],
browser: "Chrome/154",
pages: 2,
},
};
const statusText = tool
?.renderResult?.(
status,
{ expanded: false, isPartial: false } as never,
theme as never,
{ isError: false } as never,
)
.render(100)
.join("\n");
expect(statusText).toContain("Chrome/154 · 2 pages");
});
});