108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
import { vi } from "vitest";
|
|
import { withFetchPreconnect } from "../test-utils/fetch-mock.js";
|
|
import type { BrowserServerState } from "./server-context.js";
|
|
import { createBrowserRouteContext } from "./server-context.js";
|
|
|
|
export const originalFetch = globalThis.fetch;
|
|
|
|
export function makeState(
|
|
profile: "remote" | "openclaw",
|
|
): BrowserServerState & { profiles: Map<string, { lastTargetId?: string | null }> } {
|
|
return {
|
|
// oxlint-disable-next-line typescript/no-explicit-any
|
|
server: null as any,
|
|
port: 0,
|
|
resolved: {
|
|
enabled: true,
|
|
controlPort: 18791,
|
|
cdpPortRangeStart: 18800,
|
|
cdpPortRangeEnd: 18899,
|
|
cdpProtocol: profile === "remote" ? "https" : "http",
|
|
cdpHost: profile === "remote" ? "browserless.example" : "127.0.0.1",
|
|
cdpIsLoopback: profile !== "remote",
|
|
remoteCdpTimeoutMs: 1500,
|
|
remoteCdpHandshakeTimeoutMs: 3000,
|
|
evaluateEnabled: false,
|
|
extraArgs: [],
|
|
color: "#FF4500",
|
|
headless: true,
|
|
noSandbox: false,
|
|
attachOnly: false,
|
|
ssrfPolicy: { allowPrivateNetwork: true },
|
|
defaultProfile: profile,
|
|
profiles: {
|
|
remote: {
|
|
cdpUrl: "https://browserless.example/chrome?token=abc",
|
|
cdpPort: 443,
|
|
color: "#00AA00",
|
|
},
|
|
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
|
},
|
|
},
|
|
profiles: new Map(),
|
|
};
|
|
}
|
|
|
|
export function makeUnexpectedFetchMock() {
|
|
return vi.fn(async () => {
|
|
throw new Error("unexpected fetch");
|
|
});
|
|
}
|
|
|
|
export function createRemoteRouteHarness(fetchMock?: (url: unknown) => Promise<Response>) {
|
|
const activeFetchMock = fetchMock ?? makeUnexpectedFetchMock();
|
|
global.fetch = withFetchPreconnect(activeFetchMock);
|
|
const state = makeState("remote");
|
|
const ctx = createBrowserRouteContext({ getState: () => state });
|
|
return { state, remote: ctx.forProfile("remote"), fetchMock: activeFetchMock };
|
|
}
|
|
|
|
export function createSequentialPageLister<T>(responses: T[]) {
|
|
return async () => {
|
|
const next = responses.shift();
|
|
if (!next) {
|
|
throw new Error("no more responses");
|
|
}
|
|
return next;
|
|
};
|
|
}
|
|
|
|
type JsonListEntry = {
|
|
id: string;
|
|
title: string;
|
|
url: string;
|
|
webSocketDebuggerUrl: string;
|
|
type: "page";
|
|
};
|
|
|
|
export function createJsonListFetchMock(entries: JsonListEntry[]) {
|
|
return async (url: unknown) => {
|
|
const u = String(url);
|
|
if (!u.includes("/json/list")) {
|
|
throw new Error(`unexpected fetch: ${u}`);
|
|
}
|
|
return {
|
|
ok: true,
|
|
json: async () => entries,
|
|
} as unknown as Response;
|
|
};
|
|
}
|
|
|
|
function makeManagedTab(id: string, ordinal: number): JsonListEntry {
|
|
return {
|
|
id,
|
|
title: String(ordinal),
|
|
url: `http://127.0.0.1:300${ordinal}`,
|
|
webSocketDebuggerUrl: `ws://127.0.0.1/devtools/page/${id}`,
|
|
type: "page",
|
|
};
|
|
}
|
|
|
|
export function makeManagedTabsWithNew(params?: { newFirst?: boolean }): JsonListEntry[] {
|
|
const oldTabs = Array.from({ length: 8 }, (_, index) =>
|
|
makeManagedTab(`OLD${index + 1}`, index + 1),
|
|
);
|
|
const newTab = makeManagedTab("NEW", 9);
|
|
return params?.newFirst ? [newTab, ...oldTabs] : [...oldTabs, newTab];
|
|
}
|