dsh-im-ops/test/channels/wecom/client-ui.test.mjs

138 lines
5.4 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import TestRenderer from 'react-test-renderer';
import {
AccountCard,
WecomSettingsTab,
} from '../../../plugin-src/client/channels/wecom/index.js';
const { act, create } = TestRenderer;
const CLIENT_URL = new URL('../../../plugin-src/client/channels/wecom/index.js', import.meta.url);
async function flushMicrotasks() {
for (let index = 0; index < 6; index += 1) await Promise.resolve();
}
function textOf(node) {
if (typeof node === 'string' || typeof node === 'number') return String(node);
return node?.children?.map(textOf).join('') ?? '';
}
function buttonNamed(root, name) {
return root.findAllByType('button').find((button) => textOf(button) === name);
}
function account(botId, name) {
return {
botId,
connected: true,
state: 'connected',
workspace: '/workspace/current',
bot: { name, appIdMasked: `${botId}•••` },
health: { summary: '企业微信 WebSocket 长连接运行正常', lastCheckedAt: Date.now() },
error: null,
};
}
test('Enterprise WeChat settings uses the shared compact channel toolbar', () => {
const markup = renderToStaticMarkup(React.createElement(WecomSettingsTab, {
rpcCall: async () => ({ ok: true, value: {} }),
}));
assert.match(markup, /class="ddt-page dwecom-page dim-channelPage"/);
assert.match(markup, /class="ddt-button dim-scanButton"/);
assert.match(markup, /aria-label="扫码接入企业微信机器人"/);
assert.match(markup, /class="dim-actionIcon"[^]*扫码接入机器人/);
assert.doesNotMatch(markup, /凭据仅保存在本机|role="switch"|type="checkbox"/);
});
test('Enterprise WeChat bot cards match the shared two-metric card treatment', () => {
const markup = renderToStaticMarkup(React.createElement(AccountCard, {
account: {
botId: 'wecom_bot',
connected: true,
state: 'connected',
bot: { name: '企业微信机器人', appIdMasked: 'bot••••001' },
health: { summary: '企业微信 WebSocket 长连接运行正常', lastCheckedAt: Date.now() },
error: null,
},
onReconnect() {},
onRequestRemove() {},
onConfirmRemove() {},
onCancelRemove() {},
}));
assert.match(markup, /class="ddt-card dim-botCard"/);
assert.match(markup, /data-im-channel-logo="wecom"/);
assert.equal((markup.match(/class="ddt-metric dim-botMetric"/g) ?? []).length, 2);
assert.match(markup, />消息通道<[^]*>最近检查</);
assert.match(markup, />检查连接<[^]*>移除接入</);
assert.doesNotMatch(markup, /收到\s*\/\s*回复|dim-cardSummary|企业微信 WebSocket 长连接运行正常/);
});
test('Enterprise WeChat card feedback stays visible without hiding connection errors', () => {
const markup = renderToStaticMarkup(React.createElement(AccountCard, {
account: {
...account('wecom_bot', '企业微信机器人'),
connected: false,
state: 'error',
error: { code: 'offline', message: '连接凭据已失效' },
},
feedback: '企业微信连接检查完成,测试消息已发送。',
onReconnect() {}, onRequestRemove() {}, onConfirmRemove() {}, onCancelRemove() {},
}));
assert.match(markup, />连接凭据已失效</);
assert.match(markup, /role="status"[^>]*>企业微信连接检查完成,测试消息已发送。</);
});
test('Enterprise WeChat connection feedback is scoped to the checked bot', async (t) => {
const previousWindow = globalThis.window;
globalThis.window = {
setInterval() { return 1; }, clearInterval() {},
setTimeout() { return 1; }, clearTimeout() {},
requestAnimationFrame(callback) { callback(); return 1; }, cancelAnimationFrame() {},
};
t.after(() => {
if (previousWindow === undefined) delete globalThis.window;
else globalThis.window = previousWindow;
});
const bots = [account('wecom_first', 'First Bot'), account('wecom_second', 'Second Bot')];
const calls = [];
const rpcCall = async (endpoint, payload) => {
if (endpoint === 'connection.status') return { ok: true, value: { bots } };
if (endpoint === 'bot.reconnect') {
calls.push(payload);
return { ok: true, value: { bots, testMessage: { sent: true } } };
}
throw new Error(`Unexpected endpoint: ${endpoint}`);
};
let renderer;
await act(async () => {
renderer = create(React.createElement(WecomSettingsTab, { rpcCall }));
await flushMicrotasks();
});
const first = renderer.root.findByProps({ 'data-bot-id': 'wecom_first' });
await act(async () => {
buttonNamed(first, '检查连接').props.onClick();
await flushMicrotasks();
});
const firstAfter = renderer.root.findByProps({ 'data-bot-id': 'wecom_first' });
const secondAfter = renderer.root.findByProps({ 'data-bot-id': 'wecom_second' });
assert.match(textOf(firstAfter), /测试消息已发送/);
assert.doesNotMatch(textOf(secondAfter), /测试消息已发送/);
assert.deepEqual(calls, [{ botId: 'wecom_first', sendTest: true }]);
await act(async () => { renderer.unmount(); });
});
test('Enterprise WeChat reconnect failure uses fixed translatable copy', async () => {
const source = await readFile(CLIENT_URL, 'utf8');
assert.match(source, /'连接检查失败,请稍后重试。'/);
assert.doesNotMatch(source, /连接检查失败:\$\{presentError\(error\)\.message\}/);
});