

























11import fs from "node:fs";
22import path from "node:path";
33import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";
4-import { beforeAll, describe, expect, it, vi } from "vitest";
4+import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
55import {
66browserPluginNodeHostCommands,
77browserPluginReload,
@@ -25,6 +25,7 @@ const runtimeApiMocks = vi.hoisted(() => ({
2525handleBrowserGatewayRequest: vi.fn(),
2626registerBrowserCli: vi.fn(),
2727runBrowserProxyCommand: vi.fn(async () => "ok"),
28+stopBrowserControlService: vi.fn(async () => undefined),
2829}));
29303031vi.mock("./register.runtime.js", async () => {
@@ -44,10 +45,22 @@ vi.mock("./src/cli/browser-cli.js", () => ({
4445registerBrowserCli: runtimeApiMocks.registerBrowserCli,
4546}));
464748+vi.mock("./src/control-service.js", () => ({
49+stopBrowserControlService: runtimeApiMocks.stopBrowserControlService,
50+}));
51+4752beforeAll(async () => {
4853await import("./register.runtime.js");
4954});
505556+beforeEach(() => {
57+vi.clearAllMocks();
58+});
59+60+afterEach(() => {
61+vi.unstubAllEnvs();
62+});
63+5164function createApi() {
5265const registerCli = vi.fn();
5366const registerGatewayMethod = vi.fn();
@@ -189,7 +202,7 @@ describe("browser plugin", () => {
189202expect(runtimeApiMocks.collectBrowserSecurityAuditFindings).toHaveBeenCalled();
190203});
191204192-it("lazy-loads the browser service on start", async () => {
205+it("registers a lazy browser control service", async () => {
193206const { api, registerService } = createApi();
194207registerBrowserPlugin(api);
195208@@ -203,10 +216,43 @@ describe("browser plugin", () => {
203216expect(typeof service?.stop).toBe("function");
204217expect(runtimeApiMocks.createBrowserPluginService).not.toHaveBeenCalled();
205218219+await service.start({ config: {}, stateDir: "/tmp/openclaw", logger: { warn: vi.fn() } });
220+expect(runtimeApiMocks.createBrowserPluginService).not.toHaveBeenCalled();
221+222+await service.stop({ config: {}, stateDir: "/tmp/openclaw", logger: { warn: vi.fn() } });
223+expect(runtimeApiMocks.stopBrowserControlService).toHaveBeenCalledOnce();
224+});
225+226+it("eager-loads the browser control service when explicitly requested", async () => {
227+vi.stubEnv("OPENCLAW_EAGER_BROWSER_CONTROL_SERVER", "1");
228+const { api, registerService } = createApi();
229+registerBrowserPlugin(api);
230+231+const service = mockCallArg(registerService) as {
232+id: string;
233+start: (...args: unknown[]) => unknown;
234+};
235+206236await service.start({ config: {}, stateDir: "/tmp/openclaw", logger: { warn: vi.fn() } });
207237expect(runtimeApiMocks.createBrowserPluginService).toHaveBeenCalledOnce();
208238});
209239240+for (const value of ["false", "", "disabled"]) {
241+it(`keeps browser control service env value ${JSON.stringify(value)} lazy`, async () => {
242+vi.stubEnv("OPENCLAW_EAGER_BROWSER_CONTROL_SERVER", value);
243+const { api, registerService } = createApi();
244+registerBrowserPlugin(api);
245+246+const service = mockCallArg(registerService) as {
247+id: string;
248+start: (...args: unknown[]) => unknown;
249+};
250+251+await service.start({ config: {}, stateDir: "/tmp/openclaw", logger: { warn: vi.fn() } });
252+expect(runtimeApiMocks.createBrowserPluginService).not.toHaveBeenCalled();
253+});
254+}
255+210256it("declares setup auto-enable reasons for browser config surfaces", () => {
211257const probe = registerBrowserAutoEnableProbe();
212258此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。