"""Read-only production asset rendering; synthetic state and blocked networking.""" import os os.environ['QT_QPA_PLATFORM'] = 'offscreen' import json, sys from pathlib import Path from PySide6.QtCore import QEventLoop, QTimer, QUrl from PySide6.QtWidgets import QApplication, QMainWindow from unittest.mock import Mock from PySide6.QtWebEngineWidgets import QWebEngineView from PySide6.QtWebEngineCore import QWebEnginePage, QWebEngineUrlRequestInterceptor DEST = Path(__file__).parent class DenyNetwork(QWebEngineUrlRequestInterceptor): def interceptRequest(self, info): if info.requestUrl().scheme() in ('http','https','ws','wss'): info.block(True) class Page(QWebEnginePage): def javaScriptConsoleMessage(self, level, message, line, source): print('JS:', str(message), flush=True) app=QApplication([]) sys.path.insert(0, r'C:\kefu\wechat_rpa') import wechat_gui_qt as qt qt.CONSOLE_HTML=Path(r'C:\wechat_rpa\assets\ui\zhenyang-ai-console.html') owner=QMainWindow();owner._push_console_state=Mock() view=qt.ConsoleShell(owner);owner.setCentralWidget(view);owner.resize(1440,1000);owner.show() page=view.page() blocker=DenyNetwork(page); page.profile().setUrlRequestInterceptor(blocker) view.resize(1440,1000);view.show() def wait(ms): loop=QEventLoop();QTimer.singleShot(ms,loop.quit);loop.exec() def js(code): values=[];loop=QEventLoop() def done(value): values.append(value);loop.quit() page.runJavaScript(code,done);QTimer.singleShot(10000,loop.quit);loop.exec() if not values: raise RuntimeError('JS callback timeout') return values[0] loop=QEventLoop();loaded=[] view.loadFinished.connect(lambda ok:(loaded.append(ok),loop.quit())) view.load(QUrl.fromLocalFile(r'C:\wechat_rpa\assets\ui\zhenyang-ai-console.html')) QTimer.singleShot(15000,loop.quit);loop.exec() assert loaded==[True],loaded state={'view':'automation','ready':True,'demo':False,'automation':{'transport':'protocol','reviewAssistant':{ 'supported':True,'ready':True,'enabled':False,'busy':False,'accountId':'168800000000001','accountName':'合成账号', 'recipient':{'id':'S:168800000000001_10001','name':'合成医疗助理','label':'企业微信客户 · 联系编号10001','kind':'企业微信客户','peerId':'10001'}, 'notification':{'message':'等待人工直接回复客户'},'preview':'【合成审核提醒内容】仅渲染测试,不发送消息'}}} unsupported={'view':'automation','ready':True,'demo':False,'automation':{'transport':'visual','reviewAssistant':{'supported':False,'ready':False,'enabled':False,'reason':'当前版本不支持协议审核提醒'}}} js('window.applyState('+json.dumps(unsupported)+');render("automation");') assert js('document.querySelector("[data-action=review-assistant-toggle]").disabled') assert js('document.querySelector("[data-action=review-assistant-choose]").disabled') assert '当前版本不支持' in js('document.body.textContent') js('window.applyState('+json.dumps(state)+');render("automation");') assert not js('document.querySelector("[data-action=review-assistant-toggle]").disabled') js('window.qtBridge={setReviewAssistantEnabled:(payload,cb)=>cb(JSON.stringify({ok:true,message:"synthetic"}))};document.querySelector("[data-action=review-assistant-toggle]").click();') js('window.fit(); document.querySelector("details").open=true;') metrics=[] for ms in (700,700,2000): wait(ms) dom=json.loads(js('JSON.stringify({visibility:document.visibilityState,view:STATE.view,mainText:document.querySelector("#main").textContent.length,mainRect:document.querySelector("#main").getBoundingClientRect().toJSON(),screenRect:document.querySelector(".screen").getBoundingClientRect().toJSON(),opacity:getComputedStyle(document.querySelector(".screen")).opacity,transform:getComputedStyle(document.querySelector("#stage")).transform,window:[innerWidth,innerHeight],toggleRect:document.querySelector("[data-action=review-assistant-toggle]").getBoundingClientRect().toJSON()})')) shot=view.grab();path=DEST/f'assistant-settings-shell-{len(metrics)}-{ms}.png';assert shot.save(str(path)) image=shot.toImage();pixels=set(image.pixelColor(x,y).name() for x in range(240,1350,9) for y in range(30,970,9)) dom.update(wait_ms=ms,pixel_colors_main=len(pixels),path=str(path));metrics.append(dom) (DEST/'assistant-shell-render-metrics.json').write_text(json.dumps(metrics,ensure_ascii=False,indent=2),encoding='utf-8') print(json.dumps(metrics,ensure_ascii=False,indent=2),flush=True) view.close();app.processEvents() os._exit(0)