Files
clawpanel/tests/channel-ui-registry.test.js
2026-05-24 02:03:55 +08:00

225 lines
5.9 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
const channelsPageSource = readFileSync(new URL('../src/pages/channels.js', import.meta.url), 'utf8')
function getRegistryBlock(platformId) {
const start = channelsPageSource.indexOf(` ${platformId}: {`)
assert.notEqual(start, -1, `未找到 ${platformId} 渠道注册表`)
const braceStart = channelsPageSource.indexOf('{', start)
let depth = 0
for (let index = braceStart; index < channelsPageSource.length; index += 1) {
const char = channelsPageSource[index]
if (char === '{') depth += 1
if (char === '}') depth -= 1
if (depth === 0) return channelsPageSource.slice(start, index + 1)
}
assert.fail(`未找到 ${platformId} 渠道注册表结束位置`)
}
test('Discord 渠道 UI 会暴露服务器频道 allowlist 配置字段', () => {
const discordBlock = getRegistryBlock('discord')
assert.match(discordBlock, /key:\s*'guildId'/)
assert.match(discordBlock, /key:\s*'channelId'/)
})
test('iMessage 渠道 UI 会暴露桥接运行配置字段', () => {
const imessageBlock = getRegistryBlock('imessage')
for (const field of [
'cliPath',
'dbPath',
'remoteHost',
'service',
'allowFrom',
'groupAllowFrom',
'probeTimeoutMs',
'attachmentRoots',
'remoteAttachmentRoots',
'sendReadReceipts',
'coalesceSameSenderDms',
]) {
assert.match(imessageBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(imessageBlock, /pluginRequired:\s*'@openclaw\/imessage@latest'/)
assert.match(imessageBlock, /pluginId:\s*'imessage'/)
})
test('WhatsApp 渠道 UI 会恢复扫码登录和运行配置入口', () => {
const whatsappBlock = getRegistryBlock('whatsapp')
for (const field of [
'selfChatMode',
'allowFrom',
'groupAllowFrom',
'debounceMs',
'mediaMaxMb',
'sendReadReceipts',
'ackEmoji',
'ackGroup',
]) {
assert.match(whatsappBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(whatsappBlock, /id:\s*'login'/)
assert.match(whatsappBlock, /pluginRequired:\s*'@openclaw\/whatsapp@latest'/)
assert.match(whatsappBlock, /pluginId:\s*'whatsapp'/)
})
test('ClickClack 渠道 UI 会暴露自托管工作区配置字段', () => {
const clickclackBlock = getRegistryBlock('clickclack')
for (const field of [
'baseUrl',
'token',
'workspace',
'botUserId',
'agentId',
'replyMode',
'model',
'systemPrompt',
'timeoutSeconds',
'toolsAllow',
'senderIsOwner',
'defaultTo',
'allowFrom',
'reconnectMs',
]) {
assert.match(clickclackBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(clickclackBlock, /pluginId:\s*'clickclack'/)
})
test('Nextcloud Talk 渠道 UI 会暴露自托管 Talk 配置字段', () => {
const talkBlock = getRegistryBlock("'nextcloud-talk'")
for (const field of [
'baseUrl',
'botSecret',
'botSecretFile',
'apiUser',
'apiPassword',
'apiPasswordFile',
'webhookPort',
'webhookHost',
'webhookPath',
'webhookPublicUrl',
'dmPolicy',
'groupPolicy',
'allowFrom',
'groupAllowFrom',
'dangerouslyAllowPrivateNetwork',
'responsePrefix',
]) {
assert.match(talkBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(talkBlock, /pluginId:\s*'nextcloud-talk'/)
})
test('Twitch 渠道 UI 会暴露聊天账号和访问控制配置字段', () => {
const twitchBlock = getRegistryBlock('twitch')
for (const field of [
'username',
'accessToken',
'clientId',
'channel',
'allowFrom',
'allowedRoles',
'requireMention',
'responsePrefix',
'clientSecret',
'refreshToken',
'expiresIn',
'obtainmentTimestamp',
]) {
assert.match(twitchBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(twitchBlock, /pluginRequired:\s*'@openclaw\/twitch@latest'/)
assert.match(twitchBlock, /pluginId:\s*'twitch'/)
})
test('Nostr 渠道 UI 会暴露私钥、Relay、访问控制和 Profile 配置字段', () => {
const nostrBlock = getRegistryBlock('nostr')
for (const field of [
'privateKey',
'relays',
'dmPolicy',
'allowFrom',
'profileName',
'profileDisplayName',
'profileAbout',
'profilePicture',
'profileWebsite',
'profileNip05',
'profileLud16',
]) {
assert.match(nostrBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(nostrBlock, /pluginRequired:\s*'@openclaw\/nostr@latest'/)
assert.match(nostrBlock, /pluginId:\s*'nostr'/)
})
test('IRC 渠道 UI 会暴露服务器、NickServ 与频道访问配置字段', () => {
const ircBlock = getRegistryBlock('irc')
for (const field of [
'host',
'port',
'tls',
'nick',
'username',
'realname',
'password',
'passwordFile',
'nickservEnabled',
'nickservService',
'nickservPassword',
'nickservPasswordFile',
'nickservRegister',
'nickservRegisterEmail',
'channels',
'dmPolicy',
'allowFrom',
'defaultTo',
'groupPolicy',
'groups',
'groupAllowFrom',
'requireMention',
'mentionPatterns',
'dangerouslyAllowNameMatching',
'blockStreaming',
]) {
assert.match(ircBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(ircBlock, /pluginRequired:\s*'@openclaw\/irc@latest'/)
assert.match(ircBlock, /pluginId:\s*'irc'/)
})
test('Tlon 渠道 UI 会暴露 Urbit 登录、频道和邀请安全配置字段', () => {
const tlonBlock = getRegistryBlock('tlon')
for (const field of [
'ship',
'url',
'code',
'dangerouslyAllowPrivateNetwork',
'groupChannels',
'dmAllowlist',
'groupInviteAllowlist',
'autoDiscoverChannels',
'showModelSignature',
'responsePrefix',
'autoAcceptDmInvites',
'autoAcceptGroupInvites',
'ownerShip',
'defaultAuthorizedShips',
]) {
assert.match(tlonBlock, new RegExp(`key:\\s*'${field}'`))
}
assert.match(tlonBlock, /pluginRequired:\s*'@openclaw\/tlon@latest'/)
assert.match(tlonBlock, /pluginId:\s*'tlon'/)
})