From fd93b7f2ab8643e89f9134f22f38f68452a07436 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 22 Apr 2026 17:13:42 +0100 Subject: [PATCH] perf(test): avoid bundled setup in auto-enable tests --- extensions/acpx/index.test.ts | 31 +++++++ extensions/browser/index.test.ts | 33 ++++++++ extensions/xai/index.test.ts | 41 ++++++++++ src/config/plugin-auto-enable.core.test.ts | 29 ++++--- .../plugin-auto-enable.providers.test.ts | 80 ++++++++++++++++--- 5 files changed, 194 insertions(+), 20 deletions(-) diff --git a/extensions/acpx/index.test.ts b/extensions/acpx/index.test.ts index 60dd72c32df..0da2957c91e 100644 --- a/extensions/acpx/index.test.ts +++ b/extensions/acpx/index.test.ts @@ -1,4 +1,7 @@ +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; +import setupPlugin from "./setup-api.js"; const { createAcpxRuntimeServiceMock, tryDispatchAcpReplyHookMock } = vi.hoisted(() => ({ createAcpxRuntimeServiceMock: vi.fn(), @@ -15,6 +18,24 @@ vi.mock("./runtime-api.js", () => ({ import plugin from "./index.js"; +type AcpxAutoEnableProbe = Parameters[0]; + +function registerAcpxAutoEnableProbe(): AcpxAutoEnableProbe { + const probes: AcpxAutoEnableProbe[] = []; + setupPlugin.register( + createTestPluginApi({ + registerAutoEnableProbe(probe) { + probes.push(probe); + }, + }), + ); + const probe = probes[0]; + if (!probe) { + throw new Error("expected ACPX setup plugin to register an auto-enable probe"); + } + return probe; +} + describe("acpx plugin", () => { beforeEach(() => { vi.clearAllMocks(); @@ -38,4 +59,14 @@ describe("acpx plugin", () => { expect(api.registerService).toHaveBeenCalledWith(service); expect(api.on).toHaveBeenCalledWith("reply_dispatch", tryDispatchAcpReplyHookMock); }); + + it("declares setup auto-enable reasons for ACPX-owned ACP config", () => { + const probe = registerAcpxAutoEnableProbe(); + + expect(probe({ config: { acp: { enabled: true } }, env: {} })).toBe("ACP runtime configured"); + expect(probe({ config: { acp: { backend: "acpx" } }, env: {} })).toBe("ACP runtime configured"); + expect(probe({ config: { acp: { enabled: true, backend: "custom-runtime" } }, env: {} })).toBe( + null, + ); + }); }); diff --git a/extensions/browser/index.test.ts b/extensions/browser/index.test.ts index 5d679e11cc7..29181aa4f53 100644 --- a/extensions/browser/index.test.ts +++ b/extensions/browser/index.test.ts @@ -7,6 +7,9 @@ import { registerBrowserPlugin, } from "./plugin-registration.js"; import type { OpenClawPluginApi } from "./runtime-api.js"; +import setupPlugin from "./setup-api.js"; + +type BrowserAutoEnableProbe = Parameters[0]; const runtimeApiMocks = vi.hoisted(() => ({ createBrowserPluginService: vi.fn(() => ({ id: "browser-control", start: vi.fn() })), @@ -51,6 +54,22 @@ function createApi() { return { api, registerCli, registerGatewayMethod, registerService, registerTool }; } +function registerBrowserAutoEnableProbe(): BrowserAutoEnableProbe { + const probes: BrowserAutoEnableProbe[] = []; + setupPlugin.register( + createTestPluginApi({ + registerAutoEnableProbe(probe) { + probes.push(probe); + }, + }), + ); + const probe = probes[0]; + if (!probe) { + throw new Error("expected browser setup plugin to register an auto-enable probe"); + } + return probe; +} + describe("browser plugin", () => { it("exposes static browser metadata on the plugin definition", () => { expect(browserPluginReload).toEqual({ restartPrefixes: ["browser"] }); @@ -86,4 +105,18 @@ describe("browser plugin", () => { agentSessionKey: "agent:main:webchat:direct:123", }); }); + + it("declares setup auto-enable reasons for browser config surfaces", () => { + const probe = registerBrowserAutoEnableProbe(); + + expect(probe({ config: { browser: { defaultProfile: "openclaw" } }, env: {} })).toBe( + "browser configured", + ); + expect(probe({ config: { tools: { alsoAllow: ["browser"] } }, env: {} })).toBe( + "browser tool referenced", + ); + expect( + probe({ config: { browser: { defaultProfile: "openclaw", enabled: false } }, env: {} }), + ).toBeNull(); + }); }); diff --git a/extensions/xai/index.test.ts b/extensions/xai/index.test.ts index 8ef1cc4d225..5963e09ac9b 100644 --- a/extensions/xai/index.test.ts +++ b/extensions/xai/index.test.ts @@ -1,6 +1,9 @@ +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; import { describe, expect, it } from "vitest"; +import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; +import setupPlugin from "./setup-api.js"; import { createXaiPayloadCaptureStream, expectXaiFastToolStreamShaping, @@ -27,7 +30,45 @@ function createProviderModel(overrides: { }; } +type XaiAutoEnableProbe = Parameters[0]; + +function registerXaiAutoEnableProbe(): XaiAutoEnableProbe { + const probes: XaiAutoEnableProbe[] = []; + setupPlugin.register( + createTestPluginApi({ + registerAutoEnableProbe(probe) { + probes.push(probe); + }, + }), + ); + const probe = probes[0]; + if (!probe) { + throw new Error("expected xAI setup plugin to register an auto-enable probe"); + } + return probe; +} + describe("xai provider plugin", () => { + it("declares setup auto-enable reasons for plugin-owned tool config", () => { + const probe = registerXaiAutoEnableProbe(); + + expect( + probe({ + config: { plugins: { entries: { xai: { config: { xSearch: { enabled: true } } } } } }, + env: {}, + }), + ).toBe("xai tool configured"); + expect( + probe({ + config: { + plugins: { entries: { xai: { config: { codeExecution: { enabled: true } } } } }, + }, + env: {}, + }), + ).toBe("xai tool configured"); + expect(probe({ config: {}, env: {} })).toBeNull(); + }); + it("owns replay policy for xAI OpenAI-compatible transports", async () => { const provider = await registerSingleProviderPlugin(plugin); diff --git a/src/config/plugin-auto-enable.core.test.ts b/src/config/plugin-auto-enable.core.test.ts index c1e64e76ade..44a30201bfe 100644 --- a/src/config/plugin-auto-enable.core.test.ts +++ b/src/config/plugin-auto-enable.core.test.ts @@ -2,6 +2,7 @@ import { afterAll, describe, expect, it } from "vitest"; import { applyPluginAutoEnable, detectPluginAutoEnableCandidates, + materializePluginAutoEnableCandidates, resolvePluginAutoEnableCandidateReason, } from "./plugin-auto-enable.js"; import { @@ -97,16 +98,20 @@ describe("applyPluginAutoEnable core", () => { expect(Object.getPrototypeOf(result.autoEnabledReasons)).toBeNull(); }); - it("auto-enables browser when browser config exists under a restrictive plugins.allow", () => { - const result = applyPluginAutoEnable({ + it("materializes setup auto-enable candidates under a restrictive plugins.allow", () => { + const result = materializePluginAutoEnableCandidates({ config: { - browser: { - defaultProfile: "openclaw", - }, plugins: { allow: ["telegram"], }, }, + candidates: [ + { + pluginId: "browser", + kind: "setup-auto-enable", + reason: "browser configured", + }, + ], env, }); @@ -115,16 +120,20 @@ describe("applyPluginAutoEnable core", () => { expect(result.changes).toContain("browser configured, enabled automatically."); }); - it("auto-enables browser when tools.alsoAllow references browser", () => { - const result = applyPluginAutoEnable({ + it("materializes setup auto-enable tool-reference reasons", () => { + const result = materializePluginAutoEnableCandidates({ config: { - tools: { - alsoAllow: ["browser"], - }, plugins: { allow: ["telegram"], }, }, + candidates: [ + { + pluginId: "browser", + kind: "setup-auto-enable", + reason: "browser tool referenced", + }, + ], env, }); diff --git a/src/config/plugin-auto-enable.providers.test.ts b/src/config/plugin-auto-enable.providers.test.ts index 92187a44e9a..1426d40d1d3 100644 --- a/src/config/plugin-auto-enable.providers.test.ts +++ b/src/config/plugin-auto-enable.providers.test.ts @@ -1,5 +1,8 @@ import { afterAll, describe, expect, it } from "vitest"; -import { applyPluginAutoEnable } from "./plugin-auto-enable.js"; +import { + applyPluginAutoEnable, + materializePluginAutoEnableCandidates, +} from "./plugin-auto-enable.js"; import { makeIsolatedEnv, makeRegistry, @@ -26,12 +29,19 @@ describe("applyPluginAutoEnable providers", () => { }, }, env, + manifestRegistry: makeRegistry([ + { + id: "google", + channels: [], + autoEnableWhenConfiguredProviders: ["google-gemini-cli"], + }, + ]), }); expect(result.config.plugins?.entries?.google?.enabled).toBe(true); }); - it("auto-enables bundled provider plugins when plugin-owned web search config exists", () => { + it("auto-enables provider plugins when plugin-owned web search config exists", () => { const result = applyPluginAutoEnable({ config: { plugins: { @@ -47,14 +57,24 @@ describe("applyPluginAutoEnable providers", () => { }, }, env, + manifestRegistry: makeRegistry([ + { + id: "xai", + channels: [], + providers: ["xai"], + contracts: { + webSearchProviders: ["grok"], + }, + }, + ]), }); expect(result.config.plugins?.entries?.xai?.enabled).toBe(true); expect(result.changes).toContain("xai web search configured, enabled automatically."); }); - it("auto-enables xai when the plugin-owned x_search tool is configured", () => { - const result = applyPluginAutoEnable({ + it("materializes xai setup auto-enable when the plugin-owned x_search tool is configured", () => { + const result = materializePluginAutoEnableCandidates({ config: { plugins: { entries: { @@ -68,15 +88,23 @@ describe("applyPluginAutoEnable providers", () => { }, }, }, + candidates: [ + { + pluginId: "xai", + kind: "setup-auto-enable", + reason: "xai tool configured", + }, + ], env, + manifestRegistry: makeRegistry([{ id: "xai", channels: [] }]), }); expect(result.config.plugins?.entries?.xai?.enabled).toBe(true); expect(result.changes).toContain("xai tool configured, enabled automatically."); }); - it("auto-enables xai when the plugin-owned codeExecution config is configured", () => { - const result = applyPluginAutoEnable({ + it("materializes xai setup auto-enable when the plugin-owned codeExecution config is configured", () => { + const result = materializePluginAutoEnableCandidates({ config: { plugins: { entries: { @@ -91,7 +119,15 @@ describe("applyPluginAutoEnable providers", () => { }, }, }, + candidates: [ + { + pluginId: "xai", + kind: "setup-auto-enable", + reason: "xai tool configured", + }, + ], env, + manifestRegistry: makeRegistry([{ id: "xai", channels: [] }]), }); expect(result.config.plugins?.entries?.xai?.enabled).toBe(true); @@ -111,6 +147,13 @@ describe("applyPluginAutoEnable providers", () => { }, }, env, + manifestRegistry: makeRegistry([ + { + id: "minimax", + channels: [], + autoEnableWhenConfiguredProviders: ["minimax-portal"], + }, + ]), }); expect(result.config.plugins?.entries?.minimax?.enabled).toBe(true); @@ -130,6 +173,13 @@ describe("applyPluginAutoEnable providers", () => { }, }, env, + manifestRegistry: makeRegistry([ + { + id: "minimax", + channels: [], + autoEnableWhenConfiguredProviders: ["minimax"], + }, + ]), }); expect(result.config.plugins?.entries?.minimax?.enabled).toBe(true); @@ -148,6 +198,7 @@ describe("applyPluginAutoEnable providers", () => { }, }, env, + manifestRegistry: makeRegistry([]), }); expect(result.config.plugins?.entries?.openai).toBeUndefined(); @@ -249,13 +300,20 @@ describe("applyPluginAutoEnable providers", () => { expect(result.changes).toContain("acme tool configured, enabled automatically."); }); - it("auto-enables acpx plugin when ACP is configured", () => { - const result = applyPluginAutoEnable({ + it("materializes acpx setup auto-enable when ACP is configured", () => { + const result = materializePluginAutoEnableCandidates({ config: { acp: { enabled: true, }, }, + candidates: [ + { + pluginId: "acpx", + kind: "setup-auto-enable", + reason: "ACP runtime configured", + }, + ], env, }); @@ -263,17 +321,19 @@ describe("applyPluginAutoEnable providers", () => { expect(result.changes.join("\n")).toContain("ACP runtime configured, enabled automatically."); }); - it("does not auto-enable acpx when a different ACP backend is configured", () => { - const result = applyPluginAutoEnable({ + it("does not materialize acpx when no setup auto-enable candidate is present", () => { + const result = materializePluginAutoEnableCandidates({ config: { acp: { enabled: true, backend: "custom-runtime", }, }, + candidates: [], env, }); expect(result.config.plugins?.entries?.acpx?.enabled).toBeUndefined(); + expect(result.changes).toEqual([]); }); });