Files
kefu/deploy/loading-performance-20260917/frontend-test.mjs
T
2026-09-21 10:34:06 +08:00

64 lines
7.0 KiB
JavaScript

import {createRequire} from 'node:module';
import {readFileSync,writeFileSync} from 'node:fs';
import assert from 'node:assert/strict';
const require=createRequire('C:/kefu/admin-web/package.json');const{chromium}=require('playwright');
const folder='C:/kefu/deploy/loading-performance-20260917';
const browser=await chromium.launch({executablePath:'C:/Program Files/Google/Chrome/Application/chrome.exe',headless:true});
const results=[],errors=[];
for(const [label,root] of [['protocol','C:/wechat_rpa'],['original','C:/kefu/wechat_rpa']]){
const context=await browser.newContext({viewport:{width:1440,height:900}});
await context.route('**/*',route=>route.request().url().startsWith('file:')?route.continue():route.abort());
async function page(view='wechatdb',extra={}){
const p=await context.newPage();p.on('pageerror',e=>errors.push({label,error:e.message}));
await p.goto(`file:///${root}/assets/ui/zhenyang-ai-console.html`);await p.waitForTimeout(150);
await p.evaluate(({view,extra})=>{
window.calls=[];window.qtBridge=new Proxy({}, {get:(_,method)=>(...args)=>calls.push({method,args})});
window.db={loading:false,query:'',selectedAccount:'account-a',selectedConversation:'conv-a',accounts:[{id:'account-a',name:'测试账号A'},{id:'account-b',name:'测试账号B'}],conversations:[{id:'conv-a',name:'测试会话A'},{id:'conv-b',name:'测试会话B'}],messages:[{id:'msg',content:'合成聊天消息',direction:'inbound'}],...extra};
applyState({view,ready:true,demo:false,wechatDb:db,system:{scale:'自动'},automation:{transport:'protocol',protocol:{status:'idle'}}});
},{view,extra});return p;
}
async function check(name,fn){try{const detail=await fn();results.push({label,name,passed:true,...(detail||{})});}catch(e){results.push({label,name,passed:false,error:String(e)});}}
await check('刷新五次只发一次并立即禁用',async()=>{
const p=await page();const count=await p.evaluate(()=>{const b=document.querySelector('[data-action="wechat-db-refresh"]');for(let i=0;i<5;i++)b.click();return calls.filter(c=>c.method==='refreshWeChatDatabase').length});
assert.equal(count,1);assert.equal(await p.locator('[data-action="wechat-db-refresh"]').isDisabled(),true);await p.close();return {bridgeCalls:count};
});
await check('加载完成恢复刷新按钮,加载中继续禁用',async()=>{
const p=await page();await p.locator('[data-action="wechat-db-refresh"]').click();
await p.evaluate(()=>applyState({view:'wechatdb',wechatDb:{...db,loading:true}}));await p.waitForTimeout(900);
assert.equal(await p.locator('[data-action="wechat-db-refresh"]').isDisabled(),true);
await p.evaluate(()=>applyState({view:'wechatdb',wechatDb:{...db,loading:false}}));assert.equal(await p.locator('[data-action="wechat-db-refresh"]').isDisabled(),false);await p.close();
});
await check('同账号会话不重复请求,切换中可改选其他目标',async()=>{
const p=await page();const got=await p.evaluate(()=>{
const click=(action,key,n=1)=>{const b=document.querySelector(`[data-action="${action}"][data-key="${key}"]`);for(let i=0;i<n;i++)b.click()};
click('wechat-db-account','account-a',5);click('wechat-db-account','account-b',5);click('wechat-db-account','account-a');
click('wechat-db-conversation','conv-a',5);click('wechat-db-conversation','conv-b',5);click('wechat-db-conversation','conv-a');return calls;
});assert.deepEqual(got,[{method:'selectWeChatAccount',args:['account-b']},{method:'selectWeChatAccount',args:['account-a']},{method:'selectWeChatConversation',args:['conv-b']},{method:'selectWeChatConversation',args:['conv-a']}]);await p.close();
});
await check('加载过程中仍可传递新会话与最终搜索',async()=>{
const p=await page('wechatdb',{loading:true});await p.locator('[data-action="wechat-db-conversation"][data-key="conv-b"]').click();await p.locator('#wechat-db-search').fill('最终查询');await p.waitForTimeout(350);
assert.deepEqual(await p.evaluate(()=>calls),[{method:'selectWeChatConversation',args:['conv-b']},{method:'setWeChatDatabaseQuery',args:['最终查询']}]);await p.close();
});
await check('患者关联加载不阻塞聊天或搜索',async()=>{
const p=await page('wechatdb',{patientContext:{loading:true,permissions:{can_search:true,can_bind:true,can_unbind:true},patient_bindings:[{is_primary:true,patient_name:'合成人名'}]}});
assert.match(await p.locator('[data-patient-loading]').innerText(),/患者关联加载中/);assert.equal(await p.locator('[data-action="wechat-patient-bind"],[data-action="wechat-patient-unbind"]').count(),0);
assert.match(await p.locator('.db-chat').innerText(),/合成聊天消息/);assert.equal(await p.locator('#wechat-db-search').isEnabled(),true);assert.equal(await p.locator('[data-action="wechat-db-conversation"][data-key="conv-b"]').isEnabled(),true);
await p.screenshot({path:`${folder}/${label}-patient-loading.png`,scale:'css'});await p.close();
});
await check('中文组字不提交半成品,只查询最终中文',async()=>{
const p=await page();await p.locator('#wechat-db-search').evaluate(input=>input.dispatchEvent(new CompositionEvent('compositionstart',{bubbles:true})));
for(const text of ['ni','nihao','你好']){await p.locator('#wechat-db-search').evaluate((input,text)=>{input.value=text;input.dispatchEvent(new InputEvent('input',{bubbles:true,isComposing:true}));},text);await p.waitForTimeout(330);}
assert.equal(await p.evaluate(()=>calls.length),0);await p.locator('#wechat-db-search').evaluate(input=>input.dispatchEvent(new CompositionEvent('compositionend',{bubbles:true})));await p.waitForTimeout(350);
assert.deepEqual(await p.evaluate(()=>calls),[{method:'setWeChatDatabaseQuery',args:['你好']}]);await p.close();
});
await check('加载快照保留搜索节点、输入与光标',async()=>{
const p=await page();await p.locator('#wechat-db-search').fill('正在输入');const kept=await p.evaluate(()=>{const input=document.getElementById('wechat-db-search');input.setSelectionRange(2,2);applyState({view:'wechatdb',wechatDb:{...db,loading:true}});return {same:input===document.getElementById('wechat-db-search'),active:document.activeElement===input,value:input.value,position:input.selectionStart}});
assert.deepEqual(kept,{same:true,active:true,value:'正在输入',position:2});await p.close();
});
if(label==='protocol')await check('协议检测五次只发一次并立即禁用',async()=>{
const p=await page('automation');const n=await p.evaluate(()=>{const b=document.querySelector('[data-action="probe-protocol"]');for(let i=0;i<5;i++)b.click();return calls.filter(c=>c.method==='probeProtocol').length});assert.equal(n,1);assert.equal(await p.locator('[data-action="probe-protocol"]').isDisabled(),true);await p.close();return {bridgeCalls:n};
});
await context.close();
}
await browser.close();const report={results,errors,total:results.length,passed:results.filter(r=>r.passed).length};writeFileSync(`${folder}/frontend-results.json`,JSON.stringify(report,null,2));console.log(JSON.stringify(report));if(results.some(r=>!r.passed)||errors.length)process.exitCode=1;