refactor(browser): dedupe control-server test harness
This commit is contained in:
18
src/browser/chrome-user-data-dir.test-harness.ts
Normal file
18
src/browser/chrome-user-data-dir.test-harness.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll } from "vitest";
|
||||
|
||||
type ChromeUserDataDirRef = {
|
||||
dir: string;
|
||||
};
|
||||
|
||||
export function installChromeUserDataDirHooks(chromeUserDataDir: ChromeUserDataDirRef): void {
|
||||
beforeAll(async () => {
|
||||
chromeUserDataDir.dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-user-data-"));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(chromeUserDataDir.dir, { recursive: true, force: true });
|
||||
});
|
||||
}
|
||||
@@ -1,17 +1,8 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, vi } from "vitest";
|
||||
import { vi } from "vitest";
|
||||
import { installChromeUserDataDirHooks } from "./chrome-user-data-dir.test-harness.js";
|
||||
|
||||
const chromeUserDataDir = { dir: "/tmp/openclaw" };
|
||||
|
||||
beforeAll(async () => {
|
||||
chromeUserDataDir.dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-user-data-"));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(chromeUserDataDir.dir, { recursive: true, force: true });
|
||||
});
|
||||
installChromeUserDataDirHooks(chromeUserDataDir);
|
||||
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => true),
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, vi } from "vitest";
|
||||
import { afterEach, beforeEach, vi } from "vitest";
|
||||
import type { MockFn } from "../test-utils/vitest-mock-fn.js";
|
||||
import { installChromeUserDataDirHooks } from "./chrome-user-data-dir.test-harness.js";
|
||||
import { getFreePort } from "./test-port.js";
|
||||
|
||||
export { getFreePort } from "./test-port.js";
|
||||
@@ -124,14 +122,7 @@ export function getPwMocks(): Record<string, MockFn> {
|
||||
}
|
||||
|
||||
const chromeUserDataDir = vi.hoisted(() => ({ dir: "/tmp/openclaw" }));
|
||||
|
||||
beforeAll(async () => {
|
||||
chromeUserDataDir.dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-user-data-"));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(chromeUserDataDir.dir, { recursive: true, force: true });
|
||||
});
|
||||
installChromeUserDataDirHooks(chromeUserDataDir);
|
||||
|
||||
function makeProc(pid = 123) {
|
||||
const handlers = new Map<string, Array<(...args: unknown[]) => void>>();
|
||||
@@ -257,12 +248,52 @@ function mockClearAll(obj: Record<string, { mockClear: () => unknown }>) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function resetBrowserControlServerTestContext(): Promise<void> {
|
||||
state.reachable = false;
|
||||
state.cfgAttachOnly = false;
|
||||
state.createTargetId = null;
|
||||
|
||||
mockClearAll(pwMocks);
|
||||
mockClearAll(cdpMocks);
|
||||
|
||||
state.testPort = await getFreePort();
|
||||
state.cdpBaseUrl = `http://127.0.0.1:${state.testPort + 1}`;
|
||||
state.prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(state.testPort - 2);
|
||||
// Avoid flaky auth coupling: some suites temporarily set gateway env auth
|
||||
// which would make the browser control server require auth.
|
||||
state.prevGatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
state.prevGatewayPassword = process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
}
|
||||
|
||||
export function restoreGatewayAuthEnv(
|
||||
prevGatewayToken: string | undefined,
|
||||
prevGatewayPassword: string | undefined,
|
||||
): void {
|
||||
if (prevGatewayToken === undefined) {
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
} else {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = prevGatewayToken;
|
||||
}
|
||||
if (prevGatewayPassword === undefined) {
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
} else {
|
||||
process.env.OPENCLAW_GATEWAY_PASSWORD = prevGatewayPassword;
|
||||
}
|
||||
}
|
||||
|
||||
export async function cleanupBrowserControlServerTestContext(): Promise<void> {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
restoreGatewayPortEnv(state.prevGatewayPort);
|
||||
restoreGatewayAuthEnv(state.prevGatewayToken, state.prevGatewayPassword);
|
||||
await stopBrowserControlServer();
|
||||
}
|
||||
|
||||
export function installBrowserControlServerHooks() {
|
||||
beforeEach(async () => {
|
||||
state.reachable = false;
|
||||
state.cfgAttachOnly = false;
|
||||
state.createTargetId = null;
|
||||
|
||||
cdpMocks.createTargetViaCdp.mockImplementation(async () => {
|
||||
if (state.createTargetId) {
|
||||
return { targetId: state.createTargetId };
|
||||
@@ -270,19 +301,7 @@ export function installBrowserControlServerHooks() {
|
||||
throw new Error("cdp disabled");
|
||||
});
|
||||
|
||||
mockClearAll(pwMocks);
|
||||
mockClearAll(cdpMocks);
|
||||
|
||||
state.testPort = await getFreePort();
|
||||
state.cdpBaseUrl = `http://127.0.0.1:${state.testPort + 1}`;
|
||||
state.prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(state.testPort - 2);
|
||||
// Avoid flaky auth coupling: some suites temporarily set gateway env auth
|
||||
// which would make the browser control server require auth.
|
||||
state.prevGatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
state.prevGatewayPassword = process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
await resetBrowserControlServerTestContext();
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -338,19 +357,6 @@ export function installBrowserControlServerHooks() {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
restoreGatewayPortEnv(state.prevGatewayPort);
|
||||
if (state.prevGatewayToken === undefined) {
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
} else {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = state.prevGatewayToken;
|
||||
}
|
||||
if (state.prevGatewayPassword === undefined) {
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
} else {
|
||||
process.env.OPENCLAW_GATEWAY_PASSWORD = state.prevGatewayPassword;
|
||||
}
|
||||
await stopBrowserControlServer();
|
||||
await cleanupBrowserControlServerTestContext();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
import { fetch as realFetch } from "undici";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
cleanupBrowserControlServerTestContext,
|
||||
getBrowserControlServerBaseUrl,
|
||||
getBrowserControlServerTestState,
|
||||
getCdpMocks,
|
||||
getFreePort,
|
||||
installBrowserControlServerHooks,
|
||||
makeResponse,
|
||||
getPwMocks,
|
||||
restoreGatewayPortEnv,
|
||||
resetBrowserControlServerTestContext,
|
||||
startBrowserControlServerFromConfig,
|
||||
stopBrowserControlServer,
|
||||
} from "./server.control-server.test-harness.js";
|
||||
|
||||
const state = getBrowserControlServerTestState();
|
||||
const cdpMocks = getCdpMocks();
|
||||
const pwMocks = getPwMocks();
|
||||
|
||||
describe("browser control server", () => {
|
||||
installBrowserControlServerHooks();
|
||||
|
||||
@@ -51,25 +43,7 @@ describe("browser control server", () => {
|
||||
|
||||
describe("profile CRUD endpoints", () => {
|
||||
beforeEach(async () => {
|
||||
state.reachable = false;
|
||||
state.cfgAttachOnly = false;
|
||||
|
||||
for (const fn of Object.values(pwMocks)) {
|
||||
fn.mockClear();
|
||||
}
|
||||
for (const fn of Object.values(cdpMocks)) {
|
||||
fn.mockClear();
|
||||
}
|
||||
|
||||
state.testPort = await getFreePort();
|
||||
state.cdpBaseUrl = `http://127.0.0.1:${state.testPort + 1}`;
|
||||
state.prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(state.testPort - 2);
|
||||
|
||||
state.prevGatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
state.prevGatewayPassword = process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
await resetBrowserControlServerTestContext();
|
||||
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
@@ -84,20 +58,7 @@ describe("profile CRUD endpoints", () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
restoreGatewayPortEnv(state.prevGatewayPort);
|
||||
if (state.prevGatewayToken !== undefined) {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = state.prevGatewayToken;
|
||||
} else {
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
}
|
||||
if (state.prevGatewayPassword !== undefined) {
|
||||
process.env.OPENCLAW_GATEWAY_PASSWORD = state.prevGatewayPassword;
|
||||
} else {
|
||||
delete process.env.OPENCLAW_GATEWAY_PASSWORD;
|
||||
}
|
||||
await stopBrowserControlServer();
|
||||
await cleanupBrowserControlServerTestContext();
|
||||
});
|
||||
|
||||
it("validates profile create/delete endpoints", async () => {
|
||||
|
||||
Reference in New Issue
Block a user