mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-14 02:31:24 +00:00
228 lines
6.9 KiB
TypeScript
228 lines
6.9 KiB
TypeScript
import { expect } from "vitest";
|
|
import { requireBundledChannelPlugin } from "../../../src/channels/plugins/bundled.js";
|
|
import type { ChannelPlugin } from "../../../src/channels/plugins/types.js";
|
|
import type { OpenClawConfig } from "../../../src/config/config.js";
|
|
|
|
type SetupContractEntry = {
|
|
id: string;
|
|
plugin: Pick<ChannelPlugin, "id" | "config" | "setup">;
|
|
cases: Array<{
|
|
name: string;
|
|
cfg: OpenClawConfig;
|
|
accountId?: string;
|
|
input: Record<string, unknown>;
|
|
expectedAccountId?: string;
|
|
expectedValidation?: string | null;
|
|
beforeTest?: () => void;
|
|
assertPatchedConfig?: (cfg: OpenClawConfig) => void;
|
|
assertResolvedAccount?: (account: unknown, cfg: OpenClawConfig) => void;
|
|
}>;
|
|
};
|
|
|
|
type StatusContractEntry = {
|
|
id: string;
|
|
plugin: Pick<ChannelPlugin, "id" | "config" | "status">;
|
|
cases: Array<{
|
|
name: string;
|
|
cfg: OpenClawConfig;
|
|
accountId?: string;
|
|
runtime?: Record<string, unknown>;
|
|
probe?: unknown;
|
|
beforeTest?: () => void;
|
|
assertSnapshot?: (snapshot: Record<string, unknown>) => void;
|
|
assertSummary?: (summary: Record<string, unknown>) => void;
|
|
}>;
|
|
};
|
|
|
|
let setupContractRegistryCache: SetupContractEntry[] | undefined;
|
|
let statusContractRegistryCache: StatusContractEntry[] | undefined;
|
|
|
|
export function getSetupContractRegistry(): SetupContractEntry[] {
|
|
setupContractRegistryCache ??= [
|
|
{
|
|
id: "slack",
|
|
plugin: requireBundledChannelPlugin("slack"),
|
|
cases: [
|
|
{
|
|
name: "default account stores tokens and enables the channel",
|
|
cfg: {} as OpenClawConfig,
|
|
input: {
|
|
botToken: "xoxb-test",
|
|
appToken: "xapp-test",
|
|
},
|
|
expectedAccountId: "default",
|
|
assertPatchedConfig: (cfg) => {
|
|
expect(cfg.channels?.slack?.enabled).toBe(true);
|
|
expect(cfg.channels?.slack?.botToken).toBe("xoxb-test");
|
|
expect(cfg.channels?.slack?.appToken).toBe("xapp-test");
|
|
},
|
|
},
|
|
{
|
|
name: "non-default env setup is rejected",
|
|
cfg: {} as OpenClawConfig,
|
|
accountId: "ops",
|
|
input: {
|
|
useEnv: true,
|
|
},
|
|
expectedAccountId: "ops",
|
|
expectedValidation: "Slack env tokens can only be used for the default account.",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: "mattermost",
|
|
plugin: requireBundledChannelPlugin("mattermost"),
|
|
cases: [
|
|
{
|
|
name: "default account stores token and normalized base URL",
|
|
cfg: {} as OpenClawConfig,
|
|
input: {
|
|
botToken: "test-token",
|
|
httpUrl: "https://chat.example.com/",
|
|
},
|
|
expectedAccountId: "default",
|
|
assertPatchedConfig: (cfg) => {
|
|
expect(cfg.channels?.mattermost?.enabled).toBe(true);
|
|
expect(cfg.channels?.mattermost?.botToken).toBe("test-token");
|
|
expect(cfg.channels?.mattermost?.baseUrl).toBe("https://chat.example.com");
|
|
},
|
|
},
|
|
{
|
|
name: "missing credentials are rejected",
|
|
cfg: {} as OpenClawConfig,
|
|
input: {
|
|
httpUrl: "",
|
|
},
|
|
expectedAccountId: "default",
|
|
expectedValidation: "Mattermost requires --bot-token and --http-url (or --use-env).",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: "line",
|
|
plugin: requireBundledChannelPlugin("line"),
|
|
cases: [
|
|
{
|
|
name: "default account stores token and secret",
|
|
cfg: {} as OpenClawConfig,
|
|
input: {
|
|
channelAccessToken: "line-token",
|
|
channelSecret: "line-secret",
|
|
},
|
|
expectedAccountId: "default",
|
|
assertPatchedConfig: (cfg) => {
|
|
expect(cfg.channels?.line?.enabled).toBe(true);
|
|
expect(cfg.channels?.line?.channelAccessToken).toBe("line-token");
|
|
expect(cfg.channels?.line?.channelSecret).toBe("line-secret");
|
|
},
|
|
},
|
|
{
|
|
name: "non-default env setup is rejected",
|
|
cfg: {} as OpenClawConfig,
|
|
accountId: "ops",
|
|
input: {
|
|
useEnv: true,
|
|
},
|
|
expectedAccountId: "ops",
|
|
expectedValidation: "LINE_CHANNEL_ACCESS_TOKEN can only be used for the default account.",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
return setupContractRegistryCache;
|
|
}
|
|
|
|
export function getStatusContractRegistry(): StatusContractEntry[] {
|
|
statusContractRegistryCache ??= [
|
|
{
|
|
id: "slack",
|
|
plugin: requireBundledChannelPlugin("slack"),
|
|
cases: [
|
|
{
|
|
name: "configured account produces a configured status snapshot",
|
|
cfg: {
|
|
channels: {
|
|
slack: {
|
|
botToken: "xoxb-test",
|
|
appToken: "xapp-test",
|
|
},
|
|
},
|
|
} as OpenClawConfig,
|
|
runtime: {
|
|
accountId: "default",
|
|
connected: true,
|
|
running: true,
|
|
},
|
|
probe: { ok: true },
|
|
assertSnapshot: (snapshot) => {
|
|
expect(snapshot.accountId).toBe("default");
|
|
expect(snapshot.enabled).toBe(true);
|
|
expect(snapshot.configured).toBe(true);
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: "mattermost",
|
|
plugin: requireBundledChannelPlugin("mattermost"),
|
|
cases: [
|
|
{
|
|
name: "configured account preserves connectivity details in the snapshot",
|
|
cfg: {
|
|
channels: {
|
|
mattermost: {
|
|
enabled: true,
|
|
botToken: "test-token",
|
|
baseUrl: "https://chat.example.com",
|
|
},
|
|
},
|
|
} as OpenClawConfig,
|
|
runtime: {
|
|
accountId: "default",
|
|
connected: true,
|
|
lastConnectedAt: 1234,
|
|
},
|
|
probe: { ok: true },
|
|
assertSnapshot: (snapshot) => {
|
|
expect(snapshot.accountId).toBe("default");
|
|
expect(snapshot.enabled).toBe(true);
|
|
expect(snapshot.configured).toBe(true);
|
|
expect(snapshot.connected).toBe(true);
|
|
expect(snapshot.baseUrl).toBe("https://chat.example.com");
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: "line",
|
|
plugin: requireBundledChannelPlugin("line"),
|
|
cases: [
|
|
{
|
|
name: "configured account produces a webhook status snapshot",
|
|
cfg: {
|
|
channels: {
|
|
line: {
|
|
enabled: true,
|
|
channelAccessToken: "line-token",
|
|
channelSecret: "line-secret",
|
|
},
|
|
},
|
|
} as OpenClawConfig,
|
|
runtime: {
|
|
accountId: "default",
|
|
running: true,
|
|
},
|
|
probe: { ok: true },
|
|
assertSnapshot: (snapshot) => {
|
|
expect(snapshot.accountId).toBe("default");
|
|
expect(snapshot.enabled).toBe(true);
|
|
expect(snapshot.configured).toBe(true);
|
|
expect(snapshot.mode).toBe("webhook");
|
|
},
|
|
},
|
|
],
|
|
},
|
|
];
|
|
return statusContractRegistryCache;
|
|
}
|