Files
openclaw/extensions/discord/src/shared.test.ts
Gio Della-Libera 6623444f8d fix(discord): report unresolved token refs at startup (#82009)
Treat configured-but-unresolved Discord token refs as configured so gateway startup reaches the explicit SecretRef resolution error instead of silently classifying the account as unconfigured. Also cover runtime snapshot resolution for active Discord token refs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 08:22:47 +01:00

187 lines
5.4 KiB
TypeScript

import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createDiscordPluginBase, discordConfigAdapter } from "./shared.js";
afterEach(() => {
vi.unstubAllEnvs();
});
describe("createDiscordPluginBase", () => {
it("owns Discord native command name overrides", () => {
const plugin = createDiscordPluginBase({ setup: {} as never });
expect(
plugin.commands?.resolveNativeCommandName?.({
commandKey: "tts",
defaultName: "tts",
}),
).toBe("voice");
expect(
plugin.commands?.resolveNativeCommandName?.({
commandKey: "status",
defaultName: "status",
}),
).toBe("status");
});
it("exposes security checks on the setup surface", () => {
const plugin = createDiscordPluginBase({ setup: {} as never });
expect(plugin.security?.resolveDmPolicy).toBeTypeOf("function");
expect(plugin.security?.collectWarnings).toBeTypeOf("function");
expect(plugin.security?.collectAuditFindings).toBeTypeOf("function");
});
it("hydrates announce delivery targets from stored session routing", () => {
const plugin = createDiscordPluginBase({ setup: {} as never });
expect(plugin.meta.preferSessionLookupForAnnounceTarget).toBe(true);
});
it("reports duplicate-token accounts as disabled to gateway startup", () => {
vi.stubEnv("DISCORD_BOT_TOKEN", "same-token");
const plugin = createDiscordPluginBase({ setup: {} as never });
const cfg = {
channels: {
discord: {
accounts: {
work: {
token: "same-token",
},
},
},
},
};
const defaultAccount = plugin.config.resolveAccount(cfg, "default");
const workAccount = plugin.config.resolveAccount(cfg, "work");
expect(plugin.config.isEnabled?.(defaultAccount, cfg)).toBe(false);
expect(plugin.config.disabledReason?.(defaultAccount, cfg)).toBe(
'duplicate bot token; using account "work"',
);
expect(plugin.config.isEnabled?.(workAccount, cfg)).toBe(true);
});
it("describes unresolved SecretRef tokens as startup-configured so startup reports the resolver error", () => {
const plugin = createDiscordPluginBase({ setup: {} as never });
const cfg = {
channels: {
discord: {
token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },
},
},
} as unknown as OpenClawConfig;
const account = plugin.config.resolveAccount(cfg, "default");
const described = plugin.config.describeAccount?.(account, cfg);
expect(account.token).toBe("");
expect(account.tokenSource).toBe("config");
expect(account.tokenStatus).toBe("configured_unavailable");
expect(plugin.config.isConfigured?.(account, cfg)).toBe(true);
expect(described?.configured).toBe(true);
expect(described?.tokenStatus).toBe("configured_unavailable");
});
});
describe("discordConfigAdapter", () => {
it("resolves top-level allowFrom before legacy dm.allowFrom", () => {
const cfg = {
channels: {
discord: {
accounts: {
default: {
allowFrom: ["123"],
dm: { allowFrom: ["456"] },
},
},
},
},
} as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "default" })).toEqual(["123"]);
});
it("falls back to legacy dm.allowFrom", () => {
const cfg = {
channels: {
discord: {
accounts: {
default: {
dm: { allowFrom: ["456"] },
},
},
},
},
} as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "default" })).toEqual(["456"]);
});
it("prefers account legacy dm.allowFrom over inherited root allowFrom", () => {
const cfg = {
channels: {
discord: {
allowFrom: ["root"],
accounts: {
work: {
dm: { allowFrom: ["account-legacy"] },
},
},
},
},
} as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "work" })).toEqual([
"account-legacy",
]);
});
it("coerces numeric allowFrom entries at the config boundary", () => {
const cfg = {
channels: {
discord: {
accounts: {
default: {
allowFrom: [123456789],
},
},
},
},
} as unknown as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "default" })).toEqual([
"123456789",
]);
});
it("keeps read-only accessors from resolving token SecretRefs", () => {
const cfg = {
secrets: {
providers: {
discord_token: {
source: "file",
path: "/tmp/openclaw-missing-discord-token",
mode: "singleValue",
},
},
},
channels: {
discord: {
token: { source: "file", provider: "discord_token", id: "value" },
allowFrom: ["1128540374256849009"],
defaultTo: "1498959610751750304",
},
},
} as OpenClawConfig;
expect(discordConfigAdapter.resolveAllowFrom?.({ cfg, accountId: "default" })).toEqual([
"1128540374256849009",
]);
expect(discordConfigAdapter.resolveDefaultTo?.({ cfg, accountId: "default" })).toBe(
"1498959610751750304",
);
});
});