openclaw/src/browser/server-context.loopback-direct-ws.test.ts

101 lines
3.4 KiB
TypeScript
Raw Normal View History

import { afterEach, describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../test-utils/fetch-mock.js";
import * as cdpModule from "./cdp.js";
import { createBrowserRouteContext } from "./server-context.js";
import { makeState, originalFetch } from "./server-context.remote-tab-ops.harness.js";
afterEach(() => {
globalThis.fetch = originalFetch;
vi.restoreAllMocks();
});
describe("browser server-context loopback direct WebSocket profiles", () => {
it("uses an HTTP /json/list base when opening tabs", async () => {
const createTargetViaCdp = vi
.spyOn(cdpModule, "createTargetViaCdp")
.mockResolvedValue({ targetId: "CREATED" });
const fetchMock = vi.fn(async (url: unknown) => {
const u = String(url);
expect(u).toBe("http://127.0.0.1:18800/json/list?token=abc");
return {
ok: true,
json: async () => [
{
id: "CREATED",
title: "New Tab",
url: "http://127.0.0.1:8080",
webSocketDebuggerUrl: "ws://127.0.0.1/devtools/page/CREATED",
type: "page",
},
],
} as unknown as Response;
});
global.fetch = withFetchPreconnect(fetchMock);
const state = makeState("openclaw");
state.resolved.profiles.openclaw = {
cdpUrl: "ws://127.0.0.1:18800/devtools/browser/SESSION?token=abc",
color: "#FF4500",
};
const ctx = createBrowserRouteContext({ getState: () => state });
const openclaw = ctx.forProfile("openclaw");
const opened = await openclaw.openTab("http://127.0.0.1:8080");
expect(opened.targetId).toBe("CREATED");
expect(createTargetViaCdp).toHaveBeenCalledWith({
cdpUrl: "ws://127.0.0.1:18800/devtools/browser/SESSION?token=abc",
url: "http://127.0.0.1:8080",
ssrfPolicy: { allowPrivateNetwork: true },
});
});
it("uses an HTTP /json base for focus and close", async () => {
const fetchMock = vi.fn(async (url: unknown) => {
const u = String(url);
if (u === "http://127.0.0.1:18800/json/list?token=abc") {
return {
ok: true,
json: async () => [
{
id: "T1",
title: "Tab 1",
url: "https://example.com",
webSocketDebuggerUrl: "ws://127.0.0.1/devtools/page/T1",
type: "page",
},
],
} as unknown as Response;
}
if (u === "http://127.0.0.1:18800/json/activate/T1?token=abc") {
return { ok: true, json: async () => ({}) } as unknown as Response;
}
if (u === "http://127.0.0.1:18800/json/close/T1?token=abc") {
return { ok: true, json: async () => ({}) } as unknown as Response;
}
throw new Error(`unexpected fetch: ${u}`);
});
global.fetch = withFetchPreconnect(fetchMock);
const state = makeState("openclaw");
state.resolved.profiles.openclaw = {
cdpUrl: "ws://127.0.0.1:18800/devtools/browser/SESSION?token=abc",
color: "#FF4500",
};
const ctx = createBrowserRouteContext({ getState: () => state });
const openclaw = ctx.forProfile("openclaw");
await openclaw.focusTab("T1");
await openclaw.closeTab("T1");
expect(fetchMock).toHaveBeenCalledWith(
"http://127.0.0.1:18800/json/activate/T1?token=abc",
expect.any(Object),
);
expect(fetchMock).toHaveBeenCalledWith(
"http://127.0.0.1:18800/json/close/T1?token=abc",
expect.any(Object),
);
});
});