mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
235 lines
7.7 KiB
TypeScript
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();
|
|
});
|
|
});
|