mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-30 04:40:18 +08:00
358 lines
11 KiB
JavaScript
358 lines
11 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
|
|
import {
|
|
buildMessagingPlatformFormValues,
|
|
listPlatformAccounts,
|
|
mergeOpenClawMessagingPlatformConfig,
|
|
resolveMessagingCredentialValueForSave,
|
|
normalizeMessagingPlatformForm,
|
|
} from '../scripts/dev-api.js'
|
|
|
|
test('渠道保存会为 Telegram 补齐新版 OpenClaw 必填访问策略', () => {
|
|
const form = normalizeMessagingPlatformForm('telegram', {
|
|
botToken: '123:token',
|
|
})
|
|
|
|
assert.equal(form.botToken, '123:token')
|
|
assert.equal(form.dmPolicy, 'pairing')
|
|
assert.equal(form.groupPolicy, 'allowlist')
|
|
})
|
|
|
|
test('渠道保存会把旧 UI 策略值转换为 OpenClaw 支持的枚举', () => {
|
|
const form = normalizeMessagingPlatformForm('slack', {
|
|
mode: 'socket',
|
|
botToken: 'xoxb-token',
|
|
appToken: 'xapp-token',
|
|
dmPolicy: 'allow',
|
|
groupPolicy: 'mentioned',
|
|
})
|
|
|
|
assert.equal(form.dmPolicy, 'open')
|
|
assert.deepEqual(form.allowFrom, ['*'])
|
|
assert.equal(form.groupPolicy, 'open')
|
|
assert.equal(form.requireMention, true)
|
|
assert.equal(form.webhookPath, '/slack/events')
|
|
assert.equal(form.userTokenReadOnly, false)
|
|
})
|
|
|
|
test('渠道保存不会向不支持顶层 requireMention 的平台写入非法字段', () => {
|
|
const form = normalizeMessagingPlatformForm('signal', {
|
|
account: '+15551234567',
|
|
dmPolicy: 'deny',
|
|
groupPolicy: 'mentioned',
|
|
})
|
|
|
|
assert.equal(form.dmPolicy, 'disabled')
|
|
assert.equal(form.groupPolicy, 'open')
|
|
assert.equal(Object.hasOwn(form, 'requireMention'), false)
|
|
})
|
|
|
|
test('渠道保存会为飞书补齐新版内核要求的默认字段', () => {
|
|
const form = normalizeMessagingPlatformForm('feishu', {
|
|
appId: 'cli_a',
|
|
appSecret: 'secret',
|
|
domain: '',
|
|
})
|
|
|
|
assert.equal(form.domain, 'feishu')
|
|
assert.equal(form.connectionMode, 'websocket')
|
|
assert.equal(form.webhookPath, '/feishu/events')
|
|
assert.equal(form.dmPolicy, 'pairing')
|
|
assert.equal(form.groupPolicy, 'allowlist')
|
|
assert.equal(form.reactionNotifications, 'off')
|
|
assert.equal(form.typingIndicator, true)
|
|
assert.equal(form.resolveSenderNames, true)
|
|
})
|
|
|
|
test('渠道读取会把新版访问策略字段回显为表单可编辑值', () => {
|
|
const values = buildMessagingPlatformFormValues('telegram', {
|
|
botToken: '123:token',
|
|
dmPolicy: 'allowlist',
|
|
groupPolicy: 'disabled',
|
|
allowFrom: ['u-1', 'u-2'],
|
|
})
|
|
|
|
assert.equal(values.botToken, '123:token')
|
|
assert.equal(values.dmPolicy, 'allowlist')
|
|
assert.equal(values.groupPolicy, 'disabled')
|
|
assert.equal(values.allowFrom, 'u-1, u-2')
|
|
assert.equal(values.allowedUsers, 'u-1, u-2')
|
|
})
|
|
|
|
test('渠道读取会合并飞书账号凭证和根节点共享策略字段', () => {
|
|
const values = buildMessagingPlatformFormValues(
|
|
'feishu',
|
|
{
|
|
appId: 'cli_a',
|
|
appSecret: 'secret',
|
|
},
|
|
{
|
|
channelRoot: {
|
|
domain: 'lark',
|
|
connectionMode: 'websocket',
|
|
webhookPath: '/feishu/events',
|
|
dmPolicy: 'pairing',
|
|
groupPolicy: 'allowlist',
|
|
reactionNotifications: 'off',
|
|
typingIndicator: true,
|
|
resolveSenderNames: false,
|
|
},
|
|
},
|
|
)
|
|
|
|
assert.equal(values.appId, 'cli_a')
|
|
assert.equal(values.appSecret, 'secret')
|
|
assert.equal(values.domain, 'lark')
|
|
assert.equal(values.connectionMode, 'websocket')
|
|
assert.equal(values.webhookPath, '/feishu/events')
|
|
assert.equal(values.dmPolicy, 'pairing')
|
|
assert.equal(values.groupPolicy, 'allowlist')
|
|
assert.equal(values.reactionNotifications, 'off')
|
|
assert.equal(values.typingIndicator, 'true')
|
|
assert.equal(values.resolveSenderNames, 'false')
|
|
})
|
|
|
|
test('渠道读取飞书多账号时不会用根节点旧凭证覆盖账号凭证', () => {
|
|
const values = buildMessagingPlatformFormValues(
|
|
'feishu',
|
|
{
|
|
appId: 'account_app',
|
|
appSecret: 'account_secret',
|
|
dmPolicy: 'pairing',
|
|
},
|
|
{
|
|
channelRoot: {
|
|
appId: 'root_app',
|
|
appSecret: 'root_secret',
|
|
domain: 'lark',
|
|
groupPolicy: 'allowlist',
|
|
},
|
|
},
|
|
)
|
|
|
|
assert.equal(values.appId, 'account_app')
|
|
assert.equal(values.appSecret, 'account_secret')
|
|
assert.equal(values.domain, 'lark')
|
|
assert.equal(values.dmPolicy, 'pairing')
|
|
assert.equal(values.groupPolicy, 'allowlist')
|
|
})
|
|
|
|
test('渠道读取会把 open + requireMention 反向回显为仅提及时策略', () => {
|
|
const values = buildMessagingPlatformFormValues('slack', {
|
|
mode: 'socket',
|
|
botToken: 'xoxb-token',
|
|
appToken: 'xapp-token',
|
|
groupPolicy: 'open',
|
|
requireMention: true,
|
|
})
|
|
|
|
assert.equal(values.groupPolicy, 'mentioned')
|
|
assert.equal(values.requireMention, 'true')
|
|
})
|
|
|
|
test('Discord 渠道读取会回显 applicationId', () => {
|
|
const values = buildMessagingPlatformFormValues('discord', {
|
|
token: 'discord-token',
|
|
applicationId: '123456789012345678',
|
|
})
|
|
|
|
assert.equal(values.token, 'discord-token')
|
|
assert.equal(values.applicationId, '123456789012345678')
|
|
})
|
|
|
|
test('渠道保存会在用户改回所有群组时显式清除仅提及开关', () => {
|
|
const form = normalizeMessagingPlatformForm('slack', {
|
|
mode: 'socket',
|
|
botToken: 'xoxb-token',
|
|
appToken: 'xapp-token',
|
|
groupPolicy: 'open',
|
|
})
|
|
|
|
assert.equal(form.groupPolicy, 'open')
|
|
assert.equal(form.requireMention, false)
|
|
})
|
|
|
|
test('渠道读取会把 SecretRef 密钥显示为安全占位并携带原始对象', () => {
|
|
const secretRef = { source: 'env', provider: 'default', id: 'TELEGRAM_BOT_TOKEN' }
|
|
const values = buildMessagingPlatformFormValues('telegram', {
|
|
botToken: secretRef,
|
|
dmPolicy: 'pairing',
|
|
groupPolicy: 'allowlist',
|
|
})
|
|
|
|
assert.equal(values.botToken, 'SecretRef(env:default:TELEGRAM_BOT_TOKEN)')
|
|
assert.deepEqual(values.__secretRefs, { botToken: secretRef })
|
|
})
|
|
|
|
test('渠道保存时用户未改动 SecretRef 占位会保留原始密钥引用', () => {
|
|
const secretRef = { source: 'env', provider: 'default', id: 'SLACK_BOT_TOKEN' }
|
|
const value = resolveMessagingCredentialValueForSave({
|
|
form: { botToken: 'SecretRef(env:default:SLACK_BOT_TOKEN)' },
|
|
current: { botToken: secretRef },
|
|
key: 'botToken',
|
|
})
|
|
|
|
assert.deepEqual(value, secretRef)
|
|
})
|
|
|
|
test('渠道保存时用户输入新密钥会替换旧 SecretRef', () => {
|
|
const secretRef = { source: 'env', provider: 'default', id: 'DISCORD_BOT_TOKEN' }
|
|
const value = resolveMessagingCredentialValueForSave({
|
|
form: { token: 'new-discord-token' },
|
|
current: { token: secretRef },
|
|
key: 'token',
|
|
})
|
|
|
|
assert.equal(value, 'new-discord-token')
|
|
})
|
|
|
|
test('渠道账号列表会把 SecretRef 标识显示为安全占位', () => {
|
|
const accounts = listPlatformAccounts({
|
|
accounts: {
|
|
prod: {
|
|
appId: { source: 'env', provider: 'default', id: 'FEISHU_APP_ID' },
|
|
},
|
|
backup: {
|
|
clientId: { source: 'env', provider: 'default', id: 'DINGTALK_CLIENT_ID' },
|
|
},
|
|
},
|
|
})
|
|
|
|
assert.deepEqual(accounts, [
|
|
{ accountId: 'backup', appId: 'SecretRef(env:default:DINGTALK_CLIENT_ID)' },
|
|
{ accountId: 'prod', appId: 'SecretRef(env:default:FEISHU_APP_ID)' },
|
|
])
|
|
})
|
|
|
|
test('渠道保存时 clientId 未改动 SecretRef 占位会保留原始引用', () => {
|
|
const secretRef = { source: 'env', provider: 'default', id: 'DINGTALK_CLIENT_ID' }
|
|
const value = resolveMessagingCredentialValueForSave({
|
|
form: { clientId: 'SecretRef(env:default:DINGTALK_CLIENT_ID)' },
|
|
current: { clientId: secretRef },
|
|
key: 'clientId',
|
|
})
|
|
|
|
assert.deepEqual(value, secretRef)
|
|
})
|
|
|
|
test('OpenClaw 渠道保存带账号标识时会写入 accounts 而不是覆盖根配置', () => {
|
|
const cfg = {
|
|
channels: {
|
|
telegram: {
|
|
enabled: true,
|
|
botToken: 'root-token',
|
|
dmPolicy: 'pairing',
|
|
groupPolicy: 'allowlist',
|
|
},
|
|
discord: {
|
|
enabled: true,
|
|
token: 'root-discord',
|
|
groupPolicy: 'allowlist',
|
|
},
|
|
slack: {
|
|
enabled: true,
|
|
mode: 'socket',
|
|
botToken: 'root-slack',
|
|
appToken: 'root-app',
|
|
},
|
|
},
|
|
}
|
|
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'telegram',
|
|
accountId: 'alerts',
|
|
form: { botToken: 'alerts-token', dmPolicy: 'allowlist', groupPolicy: 'disabled' },
|
|
})
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'discord',
|
|
accountId: 'ops',
|
|
form: { token: 'ops-discord', guildId: 'guild-1', channelId: 'channel-1' },
|
|
})
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'slack',
|
|
accountId: 'team-a',
|
|
form: { mode: 'socket', botToken: 'team-slack', appToken: 'team-app' },
|
|
})
|
|
|
|
assert.equal(cfg.channels.telegram.botToken, 'root-token')
|
|
assert.equal(cfg.channels.telegram.accounts.alerts.botToken, 'alerts-token')
|
|
assert.equal(cfg.channels.telegram.accounts.alerts.dmPolicy, 'allowlist')
|
|
assert.equal(cfg.channels.discord.token, 'root-discord')
|
|
assert.equal(cfg.channels.discord.accounts.ops.token, 'ops-discord')
|
|
assert.equal(cfg.channels.discord.accounts.ops.guilds['guild-1'].channels['channel-1'].allow, true)
|
|
assert.equal(cfg.channels.slack.botToken, 'root-slack')
|
|
assert.equal(cfg.channels.slack.accounts['team-a'].botToken, 'team-slack')
|
|
assert.equal(cfg.channels.slack.accounts['team-a'].appToken, 'team-app')
|
|
})
|
|
|
|
test('Discord 渠道保存会保留运行时需要的 applicationId', () => {
|
|
const cfg = { channels: {} }
|
|
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'discord',
|
|
form: {
|
|
token: 'discord-token',
|
|
applicationId: '123456789012345678',
|
|
},
|
|
})
|
|
|
|
assert.equal(cfg.channels.discord.token, 'discord-token')
|
|
assert.equal(cfg.channels.discord.applicationId, '123456789012345678')
|
|
})
|
|
|
|
test('OpenClaw 渠道保存第一个命名账号时会固定 defaultAccount', () => {
|
|
const cfg = { channels: {} }
|
|
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'telegram',
|
|
accountId: 'alerts',
|
|
form: { botToken: 'alerts-token' },
|
|
})
|
|
mergeOpenClawMessagingPlatformConfig(cfg, {
|
|
platform: 'telegram',
|
|
accountId: 'ops',
|
|
form: { botToken: 'ops-token' },
|
|
})
|
|
|
|
assert.equal(cfg.channels.telegram.defaultAccount, 'alerts')
|
|
assert.equal(cfg.channels.telegram.accounts.alerts.botToken, 'alerts-token')
|
|
assert.equal(cfg.channels.telegram.accounts.ops.botToken, 'ops-token')
|
|
})
|
|
|
|
test('OpenClaw 渠道保存命名账号时不会覆盖已有默认账号或根凭证默认账号', () => {
|
|
const explicitDefault = {
|
|
channels: {
|
|
discord: {
|
|
defaultAccount: 'ops',
|
|
accounts: { ops: { token: 'ops-token' } },
|
|
},
|
|
},
|
|
}
|
|
mergeOpenClawMessagingPlatformConfig(explicitDefault, {
|
|
platform: 'discord',
|
|
accountId: 'alerts',
|
|
form: { token: 'alerts-token' },
|
|
})
|
|
|
|
const rootDefault = {
|
|
channels: {
|
|
slack: {
|
|
mode: 'socket',
|
|
botToken: 'root-bot',
|
|
appToken: 'root-app',
|
|
},
|
|
},
|
|
}
|
|
mergeOpenClawMessagingPlatformConfig(rootDefault, {
|
|
platform: 'slack',
|
|
accountId: 'team-a',
|
|
form: { mode: 'socket', botToken: 'team-bot', appToken: 'team-app' },
|
|
})
|
|
|
|
assert.equal(explicitDefault.channels.discord.defaultAccount, 'ops')
|
|
assert.equal(explicitDefault.channels.discord.accounts.alerts.token, 'alerts-token')
|
|
assert.equal(rootDefault.channels.slack.defaultAccount, undefined)
|
|
assert.equal(rootDefault.channels.slack.accounts['team-a'].botToken, 'team-bot')
|
|
})
|