Files
paseo/packages/protocol/src/messages.browser-automation.test.ts
T
Mohamed BoudraandGitHub 9c220c2451 Browser tools: full accessibility snapshot, trusted input, dialogs, evaluate, and tab controls (#1881)
* feat(browser): replace flat snapshot with ARIA tree and page-side refs

* feat(browser): trusted CDP input with actionability waits

* feat(browser): auto-handle javascript dialogs

* feat(browser): add browser_evaluate

* feat(browser): add scroll, resize, and close_tab tools

* fix(browser): review fixes for snapshot/input/dialog seams

* fix(browser): address review findings on dialog capture, truncation, and keypress targets

* fix(harness): drop resize check that cannot run under parked compositor surfaces

* fix(browser): second review round — snapshot fidelity, key input, dialog scoping
2026-07-04 01:38:07 +02:00

173 lines
4.8 KiB
TypeScript

import { describe, expect, test } from "vitest";
import { BROWSER_AUTOMATION_COMMAND_NAMES } from "./browser-automation/rpc-schemas.js";
import { CLIENT_CAPS } from "./client-capabilities.js";
import {
MutableDaemonConfigPatchSchema,
MutableDaemonConfigSchema,
SessionInboundMessageSchema,
SessionOutboundMessageSchema,
WSHelloMessageSchema,
} from "./messages.js";
describe("browser automation protocol integration", () => {
const browserId = "11111111-1111-4111-8111-111111111111";
test("browser host capability parses supported commands in hello", () => {
expect(
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-1",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {
supportedCommands: [...BROWSER_AUTOMATION_COMMAND_NAMES],
hostKind: "desktop app",
},
},
}).capabilities,
).toMatchObject({
[CLIENT_CAPS.browserHost]: {
supportedCommands: [...BROWSER_AUTOMATION_COMMAND_NAMES],
hostKind: "desktop app",
},
});
});
test("browser host capability requires at least one supported command", () => {
expect(() =>
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-1",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {
supportedCommands: [],
hostKind: "desktop app",
},
},
}),
).toThrow();
expect(() =>
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-2",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {},
},
}),
).toThrow();
expect(() =>
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-3",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {
supportedCommands: ["future_command"],
},
},
}),
).toThrow();
});
test("browser host capability ignores unknown future commands when known commands remain", () => {
expect(
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-1",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {
supportedCommands: ["list_tabs", "future_command", "list_tabs"],
hostKind: "desktop app",
},
},
}).capabilities,
).toMatchObject({
[CLIENT_CAPS.browserHost]: {
supportedCommands: ["list_tabs"],
hostKind: "desktop app",
},
});
});
test("browser host capability accepts new tool commands as supported commands", () => {
expect(
WSHelloMessageSchema.parse({
type: "hello",
clientId: "client-1",
clientType: "mobile",
protocolVersion: 1,
capabilities: {
[CLIENT_CAPS.browserHost]: {
supportedCommands: ["evaluate", "scroll", "resize", "close_tab"],
hostKind: "desktop app",
},
},
}).capabilities,
).toMatchObject({
[CLIENT_CAPS.browserHost]: {
supportedCommands: ["evaluate", "scroll", "resize", "close_tab"],
hostKind: "desktop app",
},
});
});
test("hello remains valid when no browser host capability is advertised", () => {
expect(
WSHelloMessageSchema.parse({
type: "hello",
clientId: "old-client",
clientType: "mobile",
protocolVersion: 1,
}).capabilities,
).toBeUndefined();
});
test("daemon to browser host execute request is an outbound session message", () => {
const parsed = SessionOutboundMessageSchema.parse({
type: "browser.automation.execute.request",
requestId: "req-1",
command: { command: "snapshot", args: { browserId } },
});
expect(parsed.type).toBe("browser.automation.execute.request");
});
test("browser host to daemon execute response is an inbound session message", () => {
const parsed = SessionInboundMessageSchema.parse({
type: "browser.automation.execute.response",
payload: {
requestId: "req-1",
ok: true,
result: { command: "list_tabs", tabs: [] },
},
});
expect(parsed.type).toBe("browser.automation.execute.response");
});
test("mutable daemon config defaults browser tools off and accepts opt-in patches", () => {
expect(
MutableDaemonConfigSchema.parse({
mcp: { injectIntoAgents: false },
}).browserTools,
).toEqual({ enabled: false });
expect(
MutableDaemonConfigPatchSchema.parse({
browserTools: { enabled: true },
}).browserTools,
).toEqual({ enabled: true });
});
});