import asyncio,json,hashlib
from pathlib import Path
from playwright.async_api import async_playwright
async def main():
 async with async_playwright() as p:
  browser=await p.chromium.launch(headless=True,args=['--no-sandbox','--use-angle=swiftshader','--enable-unsafe-swiftshader'])
  page=await browser.new_page(viewport={'width':1280,'height':960},device_scale_factor=1)
  errors=[];page.on('pageerror',lambda e:errors.append(str(e)))
  await page.goto('http://127.0.0.1:18789/viewer/')
  await page.wait_for_function('window.__KIT_QA__?.ready',timeout=120000)
  await page.wait_for_timeout(1200);await page.screenshot(path='runtime_all.png');qa=await page.evaluate('window.__KIT_QA__');qa['all_metrics']=await page.evaluate('window.kitMetrics()');qa['captures']={};qa['glb_sha256']=hashlib.sha256(Path('kit.glb').read_bytes()).hexdigest();assert qa['all_metrics']['triangles']==json.loads(Path('kit.json').read_text())['total_triangles']+2
  for name in ['window_leaded','window_leaded_stone','window_small','door_plank','door_arched_double','window_shop','dormer','tavern_sign','bressummer_1m','ridge_tile_round']:
   await page.evaluate('(n)=>window.kitView(n)',name);await page.wait_for_timeout(350);await page.screenshot(path=f'runtime_{name}.png');qa['captures'][name]=await page.evaluate('window.kitMetrics()')
   if name in ['window_leaded','window_leaded_stone','window_small','door_plank','door_arched_double','window_shop']:
    await page.evaluate('window.kitOpen(true)');await page.wait_for_timeout(200);await page.screenshot(path=f'runtime_{name}_open.png');qa['captures'][name]['open_transforms']=await page.evaluate('window.kitTransforms()');await page.evaluate('window.kitOpen(false)');qa['captures'][name]['closed_transforms']=await page.evaluate('window.kitTransforms()');assert all(all(abs(v)<1e-6 for v in t['rotation'][:3]) for t in qa['captures'][name]['closed_transforms']);assert all(any(abs(v)>.5 for v in t['rotation'][:3]) for t in qa['captures'][name]['open_transforms'])
  await page.evaluate("window.kitView('dormer');window.kitRear(true);window.kitClay(true)");await page.wait_for_timeout(300);await page.screenshot(path='runtime_dormer_rear_clay.png')
  qa['errors']=errors;assert not errors;qa['status']='PASS';qa['performance_note']='Chromium SwiftShader software WebGL; frame timing is capture-host evidence, not a device benchmark.';Path('runtime_check.json').write_text(json.dumps(qa,indent=2));print(json.dumps(qa));await browser.close()
asyncio.run(main())
