Files
openclaw/src/plugins/runtime.channel-pin.test.ts
2026-03-24 22:16:26 -07:00

122 lines
4.5 KiB
TypeScript

import { afterEach, describe, expect, it } from "vitest";
import { getChannelPlugin } from "../channels/plugins/registry.js";
import { createEmptyPluginRegistry } from "./registry-empty.js";
import {
getActivePluginChannelRegistryVersion,
getActivePluginRegistryVersion,
getActivePluginChannelRegistry,
pinActivePluginChannelRegistry,
releasePinnedPluginChannelRegistry,
requireActivePluginChannelRegistry,
resetPluginRuntimeStateForTest,
setActivePluginRegistry,
} from "./runtime.js";
describe("channel registry pinning", () => {
afterEach(() => {
resetPluginRuntimeStateForTest();
});
it("returns the active registry when not pinned", () => {
const registry = createEmptyPluginRegistry();
setActivePluginRegistry(registry);
expect(getActivePluginChannelRegistry()).toBe(registry);
});
it("preserves pinned channel registry across setActivePluginRegistry calls", () => {
const startup = createEmptyPluginRegistry();
startup.channels = [{ plugin: { id: "slack" } }] as never;
setActivePluginRegistry(startup);
pinActivePluginChannelRegistry(startup);
// A subsequent registry swap (e.g., config-schema load) must not evict channels.
const replacement = createEmptyPluginRegistry();
setActivePluginRegistry(replacement);
expect(getActivePluginChannelRegistry()).toBe(startup);
expect(getActivePluginChannelRegistry()!.channels).toHaveLength(1);
});
it("re-pin invalidates cached channel lookups", () => {
const setup = createEmptyPluginRegistry();
const setupPlugin = { id: "slack", meta: {} } as never;
setup.channels = [{ plugin: setupPlugin }] as never;
setActivePluginRegistry(setup);
pinActivePluginChannelRegistry(setup);
expect(getChannelPlugin("slack")).toBe(setupPlugin);
const full = createEmptyPluginRegistry();
const fullPlugin = { id: "slack", meta: {} } as never;
full.channels = [{ plugin: fullPlugin }] as never;
setActivePluginRegistry(full);
expect(getChannelPlugin("slack")).toBe(setupPlugin);
const activeVersionBeforeRepin = getActivePluginRegistryVersion();
const channelVersionBeforeRepin = getActivePluginChannelRegistryVersion();
pinActivePluginChannelRegistry(full);
expect(getActivePluginRegistryVersion()).toBe(activeVersionBeforeRepin);
expect(getActivePluginChannelRegistryVersion()).toBe(channelVersionBeforeRepin + 1);
expect(getChannelPlugin("slack")).toBe(fullPlugin);
});
it("updates channel registry on swap when not pinned", () => {
const first = createEmptyPluginRegistry();
setActivePluginRegistry(first);
expect(getActivePluginChannelRegistry()).toBe(first);
const second = createEmptyPluginRegistry();
setActivePluginRegistry(second);
expect(getActivePluginChannelRegistry()).toBe(second);
});
it("release restores live-tracking behavior", () => {
const startup = createEmptyPluginRegistry();
setActivePluginRegistry(startup);
pinActivePluginChannelRegistry(startup);
const replacement = createEmptyPluginRegistry();
setActivePluginRegistry(replacement);
expect(getActivePluginChannelRegistry()).toBe(startup);
releasePinnedPluginChannelRegistry(startup);
// After release, the channel registry should follow the active registry.
expect(getActivePluginChannelRegistry()).toBe(replacement);
});
it("release is a no-op when the pinned registry does not match", () => {
const startup = createEmptyPluginRegistry();
setActivePluginRegistry(startup);
pinActivePluginChannelRegistry(startup);
const unrelated = createEmptyPluginRegistry();
releasePinnedPluginChannelRegistry(unrelated);
// Pin is still held — unrelated release was ignored.
const replacement = createEmptyPluginRegistry();
setActivePluginRegistry(replacement);
expect(getActivePluginChannelRegistry()).toBe(startup);
});
it("requireActivePluginChannelRegistry creates a registry when none exists", () => {
resetPluginRuntimeStateForTest();
const registry = requireActivePluginChannelRegistry();
expect(registry).toBeDefined();
expect(registry.channels).toEqual([]);
});
it("resetPluginRuntimeStateForTest clears channel pin", () => {
const startup = createEmptyPluginRegistry();
setActivePluginRegistry(startup);
pinActivePluginChannelRegistry(startup);
resetPluginRuntimeStateForTest();
const fresh = createEmptyPluginRegistry();
setActivePluginRegistry(fresh);
expect(getActivePluginChannelRegistry()).toBe(fresh);
});
});