124 lines
4.0 KiB
TypeScript
124 lines
4.0 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import { listChannelPlugins } from "../channels/plugins/index.js";
|
|
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
|
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
|
import { createTestRegistry } from "../test-utils/channel-plugins.js";
|
|
import {
|
|
buildGatewayReloadPlan,
|
|
diffConfigPaths,
|
|
resolveGatewayReloadSettings,
|
|
} from "./config-reload.js";
|
|
|
|
describe("diffConfigPaths", () => {
|
|
it("captures nested config changes", () => {
|
|
const prev = { hooks: { gmail: { account: "a" } } };
|
|
const next = { hooks: { gmail: { account: "b" } } };
|
|
const paths = diffConfigPaths(prev, next);
|
|
expect(paths).toContain("hooks.gmail.account");
|
|
});
|
|
|
|
it("captures array changes", () => {
|
|
const prev = { messages: { groupChat: { mentionPatterns: ["a"] } } };
|
|
const next = { messages: { groupChat: { mentionPatterns: ["b"] } } };
|
|
const paths = diffConfigPaths(prev, next);
|
|
expect(paths).toContain("messages.groupChat.mentionPatterns");
|
|
});
|
|
});
|
|
|
|
describe("buildGatewayReloadPlan", () => {
|
|
const emptyRegistry = createTestRegistry([]);
|
|
const telegramPlugin: ChannelPlugin = {
|
|
id: "telegram",
|
|
meta: {
|
|
id: "telegram",
|
|
label: "Telegram",
|
|
selectionLabel: "Telegram",
|
|
docsPath: "/channels/telegram",
|
|
blurb: "test",
|
|
},
|
|
capabilities: { chatTypes: ["direct"] },
|
|
config: {
|
|
listAccountIds: () => [],
|
|
resolveAccount: () => ({}),
|
|
},
|
|
reload: { configPrefixes: ["channels.telegram"] },
|
|
};
|
|
const whatsappPlugin: ChannelPlugin = {
|
|
id: "whatsapp",
|
|
meta: {
|
|
id: "whatsapp",
|
|
label: "WhatsApp",
|
|
selectionLabel: "WhatsApp",
|
|
docsPath: "/channels/whatsapp",
|
|
blurb: "test",
|
|
},
|
|
capabilities: { chatTypes: ["direct"] },
|
|
config: {
|
|
listAccountIds: () => [],
|
|
resolveAccount: () => ({}),
|
|
},
|
|
reload: { configPrefixes: ["web"], noopPrefixes: ["channels.whatsapp"] },
|
|
};
|
|
const registry = createTestRegistry([
|
|
{ pluginId: "telegram", plugin: telegramPlugin, source: "test" },
|
|
{ pluginId: "whatsapp", plugin: whatsappPlugin, source: "test" },
|
|
]);
|
|
|
|
beforeEach(() => {
|
|
setActivePluginRegistry(registry);
|
|
});
|
|
|
|
afterEach(() => {
|
|
setActivePluginRegistry(emptyRegistry);
|
|
});
|
|
|
|
it("marks gateway changes as restart required", () => {
|
|
const plan = buildGatewayReloadPlan(["gateway.port"]);
|
|
expect(plan.restartGateway).toBe(true);
|
|
expect(plan.restartReasons).toContain("gateway.port");
|
|
});
|
|
|
|
it("restarts the Gmail watcher for hooks.gmail changes", () => {
|
|
const plan = buildGatewayReloadPlan(["hooks.gmail.account"]);
|
|
expect(plan.restartGateway).toBe(false);
|
|
expect(plan.restartGmailWatcher).toBe(true);
|
|
expect(plan.reloadHooks).toBe(true);
|
|
});
|
|
|
|
it("restarts providers when provider config prefixes change", () => {
|
|
const changedPaths = ["web.enabled", "channels.telegram.botToken"];
|
|
const plan = buildGatewayReloadPlan(changedPaths);
|
|
expect(plan.restartGateway).toBe(false);
|
|
const expected = new Set(
|
|
listChannelPlugins()
|
|
.filter((plugin) =>
|
|
(plugin.reload?.configPrefixes ?? []).some((prefix) =>
|
|
changedPaths.some((path) => path === prefix || path.startsWith(`${prefix}.`)),
|
|
),
|
|
)
|
|
.map((plugin) => plugin.id),
|
|
);
|
|
expect(expected.size).toBeGreaterThan(0);
|
|
expect(plan.restartChannels).toEqual(expected);
|
|
});
|
|
|
|
it("treats gateway.remote as no-op", () => {
|
|
const plan = buildGatewayReloadPlan(["gateway.remote.url"]);
|
|
expect(plan.restartGateway).toBe(false);
|
|
expect(plan.noopPaths).toContain("gateway.remote.url");
|
|
});
|
|
|
|
it("defaults unknown paths to restart", () => {
|
|
const plan = buildGatewayReloadPlan(["unknownField"]);
|
|
expect(plan.restartGateway).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("resolveGatewayReloadSettings", () => {
|
|
it("uses defaults when unset", () => {
|
|
const settings = resolveGatewayReloadSettings({});
|
|
expect(settings.mode).toBe("hybrid");
|
|
expect(settings.debounceMs).toBe(300);
|
|
});
|
|
});
|