mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-10 10:30:47 +08:00
Add unified IM channel plugin
This commit is contained in:
commit
b8bd681a79
26 changed files with 7901 additions and 0 deletions
55
test/weixin-client-api.test.mjs
Normal file
55
test/weixin-client-api.test.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import {
|
||||
normalizeProvisioning,
|
||||
normalizeSnapshot,
|
||||
safeQrSource,
|
||||
safeVerificationUrl,
|
||||
unwrapRpcResult,
|
||||
} from '../plugin-src/client/channels/weixin/api.js';
|
||||
|
||||
test('client normalizes the exact redacted Host account view', () => {
|
||||
const snapshot = normalizeSnapshot({
|
||||
schemaVersion: 1,
|
||||
revision: 5,
|
||||
bots: [{
|
||||
botId: 'wx_safe',
|
||||
state: 'connected',
|
||||
connected: true,
|
||||
configured: true,
|
||||
bot: { name: '微信机器人', accountIdMasked: 'abc••••bot' },
|
||||
health: { status: 'healthy', summary: '正常', lastCheckedAt: 123 },
|
||||
stats: { messagesReceived: 3, messagesReplied: 2 },
|
||||
token: 'host-secret-that-must-be-dropped',
|
||||
}],
|
||||
});
|
||||
assert.equal(snapshot.totals.connected, 1);
|
||||
assert.doesNotMatch(JSON.stringify(snapshot), /host-secret|token/);
|
||||
});
|
||||
|
||||
test('client accepts only image data URLs and Tencent Weixin HTTPS links', () => {
|
||||
assert.match(safeQrSource('data:image/png;base64,AAAA'), /^data:image/);
|
||||
assert.equal(safeQrSource('javascript:alert(1)'), undefined);
|
||||
assert.equal(safeVerificationUrl('https://liteapp.weixin.qq.com/q/test'), 'https://liteapp.weixin.qq.com/q/test');
|
||||
assert.equal(safeVerificationUrl('https://attacker.test/q/test'), undefined);
|
||||
});
|
||||
|
||||
test('client preserves verification-required provisioning without accepting unknown states', () => {
|
||||
const value = normalizeProvisioning({
|
||||
attemptId: 'attempt',
|
||||
status: 'needs_verification',
|
||||
expiresAt: Date.now() + 1000,
|
||||
verificationRequired: true,
|
||||
});
|
||||
assert.equal(value.status, 'needs_verification');
|
||||
assert.equal(value.verificationRequired, true);
|
||||
assert.equal(normalizeProvisioning({ attemptId: 'attempt', status: 'mystery' }).status, 'failed');
|
||||
});
|
||||
|
||||
test('RPC errors are surfaced with their safe code', () => {
|
||||
assert.throws(
|
||||
() => unwrapRpcResult({ ok: false, error: { code: 'safe-code', message: '安全消息' } }),
|
||||
(error) => error.code === 'safe-code' && error.message === '安全消息',
|
||||
);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue