mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-09 08:11:09 +00:00
test: split plugin loader coverage by concern
This commit is contained in:
committed by
Peter Steinberger
parent
b53dcb9380
commit
db76dbc546
189
src/plugins/loader.runtime-registry.test.ts
Normal file
189
src/plugins/loader.runtime-registry.test.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { __testing, clearPluginLoaderCache, resolveRuntimePluginRegistry } from "./loader.js";
|
||||
import { resetPluginLoaderTestStateForTest } from "./loader.test-fixtures.js";
|
||||
import {
|
||||
getMemoryEmbeddingProvider,
|
||||
registerMemoryEmbeddingProvider,
|
||||
} from "./memory-embedding-providers.js";
|
||||
import {
|
||||
buildMemoryPromptSection,
|
||||
getMemoryRuntime,
|
||||
registerMemoryFlushPlanResolver,
|
||||
registerMemoryPromptSection,
|
||||
registerMemoryRuntime,
|
||||
resolveMemoryFlushPlan,
|
||||
} from "./memory-state.js";
|
||||
import { createEmptyPluginRegistry } from "./registry.js";
|
||||
import { setActivePluginRegistry } from "./runtime.js";
|
||||
|
||||
afterEach(() => {
|
||||
resetPluginLoaderTestStateForTest();
|
||||
});
|
||||
|
||||
describe("getCompatibleActivePluginRegistry", () => {
|
||||
it("reuses the active registry only when the load context cache key matches", () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
const loadOptions = {
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["demo"],
|
||||
load: { paths: ["/tmp/demo.js"] },
|
||||
},
|
||||
},
|
||||
workspaceDir: "/tmp/workspace-a",
|
||||
runtimeOptions: {
|
||||
allowGatewaySubagentBinding: true,
|
||||
},
|
||||
};
|
||||
const { cacheKey } = __testing.resolvePluginLoadCacheContext(loadOptions);
|
||||
setActivePluginRegistry(registry, cacheKey);
|
||||
|
||||
expect(__testing.getCompatibleActivePluginRegistry(loadOptions)).toBe(registry);
|
||||
expect(
|
||||
__testing.getCompatibleActivePluginRegistry({
|
||||
...loadOptions,
|
||||
workspaceDir: "/tmp/workspace-b",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
__testing.getCompatibleActivePluginRegistry({
|
||||
...loadOptions,
|
||||
onlyPluginIds: ["demo"],
|
||||
}),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
__testing.getCompatibleActivePluginRegistry({
|
||||
...loadOptions,
|
||||
runtimeOptions: undefined,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not embed activation secrets in the loader cache key", () => {
|
||||
const { cacheKey } = __testing.resolvePluginLoadCacheContext({
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["telegram"],
|
||||
},
|
||||
},
|
||||
activationSourceConfig: {
|
||||
plugins: {
|
||||
allow: ["telegram"],
|
||||
},
|
||||
channels: {
|
||||
telegram: {
|
||||
enabled: true,
|
||||
botToken: "secret-token",
|
||||
},
|
||||
},
|
||||
},
|
||||
autoEnabledReasons: {
|
||||
telegram: ["telegram configured"],
|
||||
},
|
||||
});
|
||||
|
||||
expect(cacheKey).not.toContain("secret-token");
|
||||
expect(cacheKey).not.toContain("botToken");
|
||||
expect(cacheKey).not.toContain("telegram configured");
|
||||
});
|
||||
|
||||
it("falls back to the current active runtime when no compatibility-shaping inputs are supplied", () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
setActivePluginRegistry(registry, "startup-registry");
|
||||
|
||||
expect(__testing.getCompatibleActivePluginRegistry()).toBe(registry);
|
||||
});
|
||||
|
||||
it("does not reuse the active registry when core gateway method names differ", () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
const loadOptions = {
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["demo"],
|
||||
load: { paths: ["/tmp/demo.js"] },
|
||||
},
|
||||
},
|
||||
workspaceDir: "/tmp/workspace-a",
|
||||
coreGatewayHandlers: {
|
||||
"sessions.get": () => undefined,
|
||||
},
|
||||
};
|
||||
const { cacheKey } = __testing.resolvePluginLoadCacheContext(loadOptions);
|
||||
setActivePluginRegistry(registry, cacheKey);
|
||||
|
||||
expect(__testing.getCompatibleActivePluginRegistry(loadOptions)).toBe(registry);
|
||||
expect(
|
||||
__testing.getCompatibleActivePluginRegistry({
|
||||
...loadOptions,
|
||||
coreGatewayHandlers: {
|
||||
"sessions.get": () => undefined,
|
||||
"sessions.list": () => undefined,
|
||||
},
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveRuntimePluginRegistry", () => {
|
||||
it("reuses the compatible active registry before attempting a fresh load", () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
const loadOptions = {
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["demo"],
|
||||
},
|
||||
},
|
||||
workspaceDir: "/tmp/workspace-a",
|
||||
};
|
||||
const { cacheKey } = __testing.resolvePluginLoadCacheContext(loadOptions);
|
||||
setActivePluginRegistry(registry, cacheKey);
|
||||
|
||||
expect(resolveRuntimePluginRegistry(loadOptions)).toBe(registry);
|
||||
});
|
||||
|
||||
it("falls back to the current active runtime when no explicit load context is provided", () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
setActivePluginRegistry(registry, "startup-registry");
|
||||
|
||||
expect(resolveRuntimePluginRegistry()).toBe(registry);
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearPluginLoaderCache", () => {
|
||||
it("resets registered memory plugin registries", () => {
|
||||
registerMemoryEmbeddingProvider({
|
||||
id: "stale",
|
||||
create: async () => ({ provider: null }),
|
||||
});
|
||||
registerMemoryPromptSection(() => ["stale memory section"]);
|
||||
registerMemoryFlushPlanResolver(() => ({
|
||||
softThresholdTokens: 1,
|
||||
forceFlushTranscriptBytes: 2,
|
||||
reserveTokensFloor: 3,
|
||||
prompt: "stale",
|
||||
systemPrompt: "stale",
|
||||
relativePath: "memory/stale.md",
|
||||
}));
|
||||
registerMemoryRuntime({
|
||||
async getMemorySearchManager() {
|
||||
return { manager: null };
|
||||
},
|
||||
resolveMemoryBackendConfig() {
|
||||
return { backend: "builtin" as const };
|
||||
},
|
||||
});
|
||||
expect(buildMemoryPromptSection({ availableTools: new Set() })).toEqual([
|
||||
"stale memory section",
|
||||
]);
|
||||
expect(resolveMemoryFlushPlan({})?.relativePath).toBe("memory/stale.md");
|
||||
expect(getMemoryRuntime()).toBeDefined();
|
||||
expect(getMemoryEmbeddingProvider("stale")).toBeDefined();
|
||||
|
||||
clearPluginLoaderCache();
|
||||
|
||||
expect(buildMemoryPromptSection({ availableTools: new Set() })).toEqual([]);
|
||||
expect(resolveMemoryFlushPlan({})).toBeNull();
|
||||
expect(getMemoryRuntime()).toBeUndefined();
|
||||
expect(getMemoryEmbeddingProvider("stale")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user