| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- """Local report layout/link check, separate from production board acceptance."""
- from pathlib import Path
- import base64
- import json
- import subprocess
- import tempfile
- import time
- import websocket
- from urllib.request import urlopen
- from urllib.parse import urlparse,unquote
- ROOT=Path(__file__).resolve().parents[1]
- WORK=ROOT/'work/voc-structure-20261105'
- REPORT=ROOT/'artifacts/康师傅VOC结构化入库-20261105/结构化入库与Agent规则报告.html'
- profile=Path(tempfile.mkdtemp(prefix='r2-report-browser-',dir=WORK))
- process=subprocess.Popen(['C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe','--headless=new','--disable-gpu',
- '--remote-debugging-port=0','--disable-background-networking','--disable-component-update','--disable-sync','--disable-extensions',
- '--no-first-run','--no-default-browser-check','--user-data-dir='+str(profile),'about:blank'],
- stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,creationflags=subprocess.CREATE_NO_WINDOW)
- ws=None;serial=0
- try:
- end=time.monotonic()+20
- while not (profile/'DevToolsActivePort').exists():
- assert time.monotonic()<end and process.poll() is None
- time.sleep(.1)
- port=(profile/'DevToolsActivePort').read_text().splitlines()[0]
- page=next(x for x in json.load(urlopen('http://127.0.0.1:'+port+'/json/list',timeout=5)) if x['type']=='page')
- ws=websocket.create_connection(page['webSocketDebuggerUrl'],timeout=20,suppress_origin=True,http_no_proxy=['127.0.0.1','localhost'])
- def call(method,params=None):
- global serial
- serial+=1;rid=serial;ws.send(json.dumps(dict(id=rid,method=method,params=params or {})))
- while True:
- response=json.loads(ws.recv())
- if response.get('id')==rid:
- assert 'error' not in response,response
- return response.get('result',{})
- def evaluate(expression):
- response=call('Runtime.evaluate',dict(expression=expression,returnByValue=True))
- assert 'exceptionDetails' not in response,response
- return response['result'].get('value')
- call('Page.enable');call('Page.navigate',dict(url=REPORT.as_uri()))
- end=time.monotonic()+10
- while evaluate('document.readyState')!='complete':
- assert time.monotonic()<end
- time.sleep(.05)
- results=[]
- for width,height in [(1440,1000),(390,844),(320,740)]:
- call('Emulation.setDeviceMetricsOverride',dict(width=width,height=height,deviceScaleFactor=1,mobile=width<700))
- metrics=evaluate("""(()=>({width:innerWidth,documentWidth:document.documentElement.scrollWidth,title:document.title,h1:document.querySelector('h1').textContent,sections:document.querySelectorAll('section').length,scenarioRows:document.querySelectorAll('section')[3].querySelectorAll('tr').length-1,links:[...document.querySelectorAll('a')].map(a=>a.href)}))()""")
- assert metrics['documentWidth']<=width,metrics
- assert metrics['scenarioRows']==13,metrics
- for link in metrics['links']:
- path=unquote(urlparse(link).path)
- if path.startswith('/') and path[2:3]==':':path=path[1:]
- assert Path(path).is_file(),link
- image=call('Page.captureScreenshot',dict(format='png',captureBeyondViewport=False))
- (WORK/f'report-r2-{width}.png').write_bytes(base64.b64decode(image['data']))
- results.append(metrics)
- result=dict(ok=True,report=str(REPORT),localReportBrowserVerified=True,productionBoardBrowserVerified=False,widths=results)
- (WORK/'report-r2-browser-validation.json').write_text(json.dumps(result,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
- print(json.dumps(dict(ok=True,widths=[x['width'] for x in results],noDocumentOverflow=True,localLinksVerified=True,scenarios=13,productionBoardBrowserVerified=False),ensure_ascii=False,indent=2))
- finally:
- if ws:ws.close()
- process.terminate()
- try:process.wait(timeout=8)
- except subprocess.TimeoutExpired:process.kill()
|