Files

106 lines
3.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 端到端验证:通过 UI 发送一条消息,等待回复,报告结果。
*
* 用法:node scripts/e2e-send.mjs <port> <消息> [超时秒]
*/
const port = Number(process.argv[2] ?? 9335)
const message = process.argv[3] ?? '列出工作目录里有哪些文件'
const timeoutMs = Number(process.argv[4] ?? 180) * 1000
async function main() {
const list = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()
const page = list.filter((t) => t.type === 'page')[0]
if (!page) throw new Error('未找到页面')
const ws = new WebSocket(page.webSocketDebuggerUrl)
await new Promise((r, j) => {
const t = setTimeout(() => j(new Error('连接超时')), 8000)
ws.addEventListener('open', () => {
clearTimeout(t)
r()
})
ws.addEventListener('error', () => {
clearTimeout(t)
j(new Error('连接失败'))
})
})
const send = (method, params = {}) =>
new Promise((res, rej) => {
const id = Math.floor(Math.random() * 1e9)
const timer = setTimeout(() => rej(new Error(`超时 ${method}`)), 25000)
const h = (ev) => {
const m = JSON.parse(ev.data)
if (m.id === id) {
clearTimeout(timer)
ws.removeEventListener('message', h)
res(m.result)
}
}
ws.addEventListener('message', h)
ws.send(JSON.stringify({ id, method, params }))
})
const evaluate = (expression) => send('Runtime.evaluate', { expression, returnByValue: true })
// 1) 填入消息(React 受控组件需用原生 setter)
const fill = `(() => {
const el = document.querySelector('.composer__input');
if (!el) return 'NO_INPUT';
const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
setter.call(el, ${JSON.stringify(message)});
el.dispatchEvent(new Event('input', { bubbles: true }));
return 'OK';
})()`
const filled = await evaluate(fill)
console.log('填入:', filled.result.value)
// 2) 点击发送
const click = `(() => {
const btn = document.querySelector('.btn-send');
if (!btn) return 'NO_BUTTON';
if (btn.disabled) return 'DISABLED';
btn.click();
return 'SENT';
})()`
const clicked = await evaluate(click)
console.log('发送:', clicked.result.value)
if (clicked.result.value !== 'SENT') {
ws.close()
process.exit(1)
}
// 3) 轮询等待回复完成
const started = Date.now()
let last = ''
while (Date.now() - started < timeoutMs) {
await new Promise((r) => setTimeout(r, 1200))
const probe = await evaluate(`(() => {
const msgs = [...document.querySelectorAll('.msg--assistant')];
const lastMsg = msgs[msgs.length - 1];
const status = lastMsg ? lastMsg.querySelector('.msg__status')?.textContent ?? '' : '';
return JSON.stringify({
count: msgs.length,
content: lastMsg ? lastMsg.querySelector('.msg__content')?.textContent.slice(0, 400) : '',
status
});
})()`)
const state = JSON.parse(probe.result.value)
last = state.content
if (state.status && /已完成|失败|已取消|error|done/i.test(state.status)) {
console.log('状态:', state.status)
console.log('回复:', state.content)
ws.close()
return
}
}
console.log('超时,最后内容:', last)
ws.close()
}
main().catch((e) => {
console.error('失败:', e.message)
process.exit(1)
})