test: dedupe plugin runtime registry suites

This commit is contained in:
Peter Steinberger 2026-03-28 04:43:25 +00:00
parent 25fea00bc7
commit fc84dd398b
4 changed files with 75 additions and 40 deletions

View File

@ -57,17 +57,33 @@ function expectMemoryEmbeddingProviderIds(expectedIds: readonly string[]) {
expect(listMemoryEmbeddingProviders().map((adapter) => adapter.id)).toEqual([...expectedIds]);
}
function expectMemoryEmbeddingProviderState(params: {
expectedIds: readonly string[];
expectedCurrent?: { id: string; adapter: MemoryEmbeddingProviderAdapter };
}) {
if (params.expectedCurrent) {
expect(getMemoryEmbeddingProvider(params.expectedCurrent.id)).toBe(
params.expectedCurrent.adapter,
);
}
expectMemoryEmbeddingProviderIds(params.expectedIds);
}
afterEach(() => {
clearMemoryEmbeddingProviders();
});
describe("memory embedding provider registry", () => {
it("registers and lists adapters in insertion order", () => {
registerMemoryEmbeddingProvider(createAdapter("alpha"));
registerMemoryEmbeddingProvider(createAdapter("beta"));
const alpha = createAdapter("alpha");
const beta = createAdapter("beta");
registerMemoryEmbeddingProvider(alpha);
registerMemoryEmbeddingProvider(beta);
expect(getMemoryEmbeddingProvider("alpha")?.id).toBe("alpha");
expectMemoryEmbeddingProviderIds(["alpha", "beta"]);
expectMemoryEmbeddingProviderState({
expectedIds: ["alpha", "beta"],
expectedCurrent: { id: "alpha", adapter: alpha },
});
});
it("restores a previous snapshot", () => {

View File

@ -49,6 +49,14 @@ function expectMemoryRuntimeLoaded(autoEnabledConfig: unknown) {
});
}
function setAutoEnabledMemoryRuntime() {
const { rawConfig, autoEnabledConfig } = createMemoryAutoEnableFixture();
const runtime = createMemoryRuntimeFixture();
applyPluginAutoEnableMock.mockReturnValue({ config: autoEnabledConfig, changes: [] });
getMemoryRuntimeMock.mockReturnValueOnce(undefined).mockReturnValue(runtime);
return { rawConfig, autoEnabledConfig, runtime };
}
describe("memory runtime auto-enable loading", () => {
beforeEach(async () => {
vi.resetModules();
@ -66,17 +74,33 @@ describe("memory runtime auto-enable loading", () => {
} = await import("./memory-runtime.js"));
});
it("loads memory runtime from the auto-enabled config snapshot", async () => {
const { rawConfig, autoEnabledConfig } = createMemoryAutoEnableFixture();
const runtime = createMemoryRuntimeFixture();
applyPluginAutoEnableMock.mockReturnValue({ config: autoEnabledConfig, changes: [] });
getMemoryRuntimeMock.mockReturnValueOnce(undefined).mockReturnValue(runtime);
it.each([
{
name: "loads memory runtime from the auto-enabled config snapshot",
run: async (rawConfig: unknown) =>
getActiveMemorySearchManager({
cfg: rawConfig as never,
agentId: "main",
}),
expectedResult: undefined,
},
{
name: "reuses the same auto-enabled load path for backend config resolution",
run: async (rawConfig: unknown) =>
resolveActiveMemoryBackendConfig({
cfg: rawConfig as never,
agentId: "main",
}),
expectedResult: { backend: "builtin" },
},
] as const)("$name", async ({ run, expectedResult }) => {
const { rawConfig, autoEnabledConfig } = setAutoEnabledMemoryRuntime();
await getActiveMemorySearchManager({
cfg: rawConfig as never,
agentId: "main",
});
const result = await run(rawConfig);
if (expectedResult !== undefined) {
expect(result).toEqual(expectedResult);
}
expect(applyPluginAutoEnableMock).toHaveBeenCalledWith({
config: rawConfig,
env: process.env,
@ -84,21 +108,6 @@ describe("memory runtime auto-enable loading", () => {
expectMemoryRuntimeLoaded(autoEnabledConfig);
});
it("reuses the same auto-enabled load path for backend config resolution", () => {
const { rawConfig, autoEnabledConfig } = createMemoryAutoEnableFixture();
const runtime = createMemoryRuntimeFixture();
applyPluginAutoEnableMock.mockReturnValue({ config: autoEnabledConfig, changes: [] });
getMemoryRuntimeMock.mockReturnValueOnce(undefined).mockReturnValue(runtime);
const result = resolveActiveMemoryBackendConfig({
cfg: rawConfig as never,
agentId: "main",
});
expect(result).toEqual({ backend: "builtin" });
expectMemoryRuntimeLoaded(autoEnabledConfig);
});
it("does not bootstrap the memory runtime just to close managers", async () => {
const rawConfig = {
plugins: {},

View File

@ -38,6 +38,16 @@ function expectActiveChannelRegistry(registry: ReturnType<typeof createEmptyPlug
expect(getActivePluginChannelRegistry()).toBe(registry);
}
function expectPinnedChannelRegistry(
startupRegistry: ReturnType<typeof createEmptyPluginRegistry>,
replacementRegistry: ReturnType<typeof createEmptyPluginRegistry>,
) {
setActivePluginRegistry(startupRegistry);
pinActivePluginChannelRegistry(startupRegistry);
setActivePluginRegistry(replacementRegistry);
expectActiveChannelRegistry(startupRegistry);
}
describe("channel registry pinning", () => {
afterEach(() => {
resetPluginRuntimeStateForTest();
@ -51,14 +61,9 @@ describe("channel registry pinning", () => {
it("preserves pinned channel registry across setActivePluginRegistry calls", () => {
const { registry: startup } = createRegistryWithChannel();
setActivePluginRegistry(startup);
pinActivePluginChannelRegistry(startup);
// A subsequent registry swap (e.g., config-schema load) must not evict channels.
const replacement = createEmptyPluginRegistry();
setActivePluginRegistry(replacement);
expectActiveChannelRegistry(startup);
expectPinnedChannelRegistry(startup, replacement);
expect(getActivePluginChannelRegistry()!.channels).toHaveLength(1);
});

View File

@ -49,6 +49,16 @@ function expectActiveRouteRegistryResolution(params: {
);
}
function expectPinnedRouteRegistry(
startupRegistry: ReturnType<typeof createEmptyPluginRegistry>,
laterRegistry: ReturnType<typeof createEmptyPluginRegistry>,
) {
setActivePluginRegistry(startupRegistry);
pinActivePluginHttpRouteRegistry(startupRegistry);
setActivePluginRegistry(laterRegistry);
expect(resolveActivePluginHttpRouteRegistry(laterRegistry)).toBe(startupRegistry);
}
describe("plugin runtime route registry", () => {
afterEach(() => {
releasePinnedPluginHttpRouteRegistry();
@ -63,12 +73,7 @@ describe("plugin runtime route registry", () => {
it("keeps the pinned route registry when the active plugin registry changes", () => {
const { startupRegistry, laterRegistry } = createRuntimeRegistryPair();
setActivePluginRegistry(startupRegistry);
pinActivePluginHttpRouteRegistry(startupRegistry);
setActivePluginRegistry(laterRegistry);
expect(resolveActivePluginHttpRouteRegistry(laterRegistry)).toBe(startupRegistry);
expectPinnedRouteRegistry(startupRegistry, laterRegistry);
});
it("tracks route registry repins separately from the active registry version", () => {