Files
openclaw/src/plugins/web-provider-runtime-shared.test.ts
2026-05-02 07:40:15 +01:00

235 lines
7.7 KiB
TypeScript

import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
isPluginRegistryLoadInFlight: vi.fn(() => false),
loadOpenClawPlugins: vi.fn(),
resolveCompatibleRuntimePluginRegistry: vi.fn(),
resolvePluginRegistryLoadCacheKey: vi.fn((options: unknown) => JSON.stringify(options)),
resolveRuntimePluginRegistry: vi.fn(),
getActivePluginRegistry: vi.fn(() => null),
getActivePluginRegistryWorkspaceDir: vi.fn(() => undefined),
buildPluginRuntimeLoadOptionsFromValues: vi.fn(
(_values: unknown, overrides?: Record<string, unknown>) => ({
...overrides,
}),
),
createPluginRuntimeLoaderLogger: vi.fn(() => ({
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
})),
}));
vi.mock("./loader.js", () => ({
isPluginRegistryLoadInFlight: mocks.isPluginRegistryLoadInFlight,
loadOpenClawPlugins: mocks.loadOpenClawPlugins,
resolveCompatibleRuntimePluginRegistry: mocks.resolveCompatibleRuntimePluginRegistry,
resolvePluginRegistryLoadCacheKey: mocks.resolvePluginRegistryLoadCacheKey,
resolveRuntimePluginRegistry: mocks.resolveRuntimePluginRegistry,
}));
vi.mock("./runtime.js", () => ({
getActivePluginRegistry: mocks.getActivePluginRegistry,
getActivePluginRegistryWorkspaceDir: mocks.getActivePluginRegistryWorkspaceDir,
}));
vi.mock("./runtime/load-context.js", () => ({
buildPluginRuntimeLoadOptionsFromValues: mocks.buildPluginRuntimeLoadOptionsFromValues,
createPluginRuntimeLoaderLogger: mocks.createPluginRuntimeLoaderLogger,
}));
let resolvePluginWebProviders: typeof import("./web-provider-runtime-shared.js").resolvePluginWebProviders;
let resolveRuntimeWebProviders: typeof import("./web-provider-runtime-shared.js").resolveRuntimeWebProviders;
describe("web-provider-runtime-shared", () => {
beforeAll(async () => {
({ resolvePluginWebProviders, resolveRuntimeWebProviders } =
await import("./web-provider-runtime-shared.js"));
});
beforeEach(() => {
mocks.isPluginRegistryLoadInFlight.mockReset();
mocks.isPluginRegistryLoadInFlight.mockReturnValue(false);
mocks.loadOpenClawPlugins.mockReset();
mocks.resolveCompatibleRuntimePluginRegistry.mockReset();
mocks.resolvePluginRegistryLoadCacheKey.mockReset();
mocks.resolvePluginRegistryLoadCacheKey.mockImplementation((options: unknown) =>
JSON.stringify(options),
);
mocks.resolveRuntimePluginRegistry.mockReset();
mocks.getActivePluginRegistry.mockReset();
mocks.getActivePluginRegistry.mockReturnValue(null);
mocks.getActivePluginRegistryWorkspaceDir.mockReset();
mocks.getActivePluginRegistryWorkspaceDir.mockReturnValue(undefined);
mocks.buildPluginRuntimeLoadOptionsFromValues.mockReset();
mocks.buildPluginRuntimeLoadOptionsFromValues.mockImplementation(
(_values: unknown, overrides?: Record<string, unknown>) => ({
...overrides,
}),
);
});
it("preserves explicit empty scopes in runtime-compatible web provider loads", () => {
const mapRegistryProviders = vi.fn(() => []);
mocks.resolveCompatibleRuntimePluginRegistry.mockReturnValue({} as never);
resolvePluginWebProviders(
{
config: {},
onlyPluginIds: [],
},
{
resolveBundledResolutionConfig: () => ({
config: {},
activationSourceConfig: {},
autoEnabledReasons: {},
}),
resolveCandidatePluginIds: () => [],
mapRegistryProviders,
},
);
expect(mocks.resolveCompatibleRuntimePluginRegistry).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: [],
}),
);
expect(mapRegistryProviders).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: [],
}),
);
});
it("preserves explicit empty scopes in direct runtime web provider resolution", () => {
const mapRegistryProviders = vi.fn(() => []);
mocks.resolveRuntimePluginRegistry.mockReturnValue({} as never);
resolveRuntimeWebProviders(
{
config: {},
onlyPluginIds: [],
},
{
resolveBundledResolutionConfig: () => ({
config: {},
activationSourceConfig: {},
autoEnabledReasons: {},
}),
resolveCandidatePluginIds: () => [],
mapRegistryProviders,
},
);
expect(mocks.resolveRuntimePluginRegistry).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: [],
}),
);
expect(mapRegistryProviders).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: [],
}),
);
});
it("preserves explicit scopes when config is omitted in direct runtime resolution", () => {
const mapRegistryProviders = vi.fn(() => []);
mocks.resolveRuntimePluginRegistry.mockReturnValue({} as never);
resolveRuntimeWebProviders(
{
onlyPluginIds: ["alpha"],
},
{
resolveBundledResolutionConfig: () => ({
config: {},
activationSourceConfig: {},
autoEnabledReasons: {},
}),
resolveCandidatePluginIds: () => ["alpha"],
mapRegistryProviders,
},
);
expect(mocks.resolveRuntimePluginRegistry).toHaveBeenCalledWith(undefined);
expect(mapRegistryProviders).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: ["alpha"],
}),
);
});
it("reuses the active registry after deriving web provider candidates from resolved config", () => {
const activeRegistry = { source: "active" };
const resolvedConfig = { plugins: { entries: { brave: { enabled: true } } } };
const resolveCandidatePluginIds = vi.fn(() => ["brave"]);
const mapRegistryProviders = vi.fn(() => ["provider"]);
mocks.resolveCompatibleRuntimePluginRegistry.mockReturnValue(null);
mocks.getActivePluginRegistry.mockReturnValue(activeRegistry);
const providers = resolvePluginWebProviders(
{
config: { plugins: { entries: {} } },
env: { BRAVE_API_KEY: "key" },
onlyPluginIds: ["brave", "firecrawl"],
origin: "bundled",
workspaceDir: "/workspace",
},
{
resolveBundledResolutionConfig: () => ({
config: resolvedConfig,
activationSourceConfig: { plugins: { entries: {} } },
autoEnabledReasons: { brave: ["env"] },
}),
resolveCandidatePluginIds,
mapRegistryProviders,
},
);
expect(providers).toEqual(["provider"]);
expect(resolveCandidatePluginIds).toHaveBeenCalledWith({
config: resolvedConfig,
workspaceDir: "/workspace",
env: { BRAVE_API_KEY: "key" },
onlyPluginIds: ["brave", "firecrawl"],
origin: "bundled",
});
expect(mapRegistryProviders).toHaveBeenCalledWith({
registry: activeRegistry,
onlyPluginIds: ["brave"],
});
expect(mocks.loadOpenClawPlugins).not.toHaveBeenCalled();
});
it("preserves explicit empty candidate scopes when reusing the active registry", () => {
const activeRegistry = { source: "active" };
const mapRegistryProviders = vi.fn(() => []);
mocks.resolveCompatibleRuntimePluginRegistry.mockReturnValue(null);
mocks.getActivePluginRegistry.mockReturnValue(activeRegistry);
resolvePluginWebProviders(
{
config: {},
onlyPluginIds: [],
},
{
resolveBundledResolutionConfig: () => ({
config: {},
activationSourceConfig: {},
autoEnabledReasons: {},
}),
resolveCandidatePluginIds: () => [],
mapRegistryProviders,
},
);
expect(mapRegistryProviders).toHaveBeenCalledWith({
registry: activeRegistry,
onlyPluginIds: [],
});
expect(mocks.loadOpenClawPlugins).not.toHaveBeenCalled();
});
});