backend-webkit.mjs (3869B)
1 // Exercise the built site with Linux WebKit. 2 import assert from 'node:assert/strict'; 3 import {writeFile,mkdtemp,rm} from 'node:fs/promises'; 4 import {tmpdir} from 'node:os'; 5 import {join} from 'node:path'; 6 import {startSiteServer} from './backend-server.mjs'; 7 const {webkit}=await import(process.env.PLAYWRIGHT_MODULE); 8 const {server,url,completion,marks}=await startSiteServer(process.argv[2]||'unused',true); 9 const profile=await mkdtemp(join(tmpdir(),'tricu-webkit-')); 10 const timeoutMs=Number(process.env.TEST_WEBKIT_TIMEOUT_MS??240000); 11 assert(Number.isSafeInteger(timeoutMs)&&timeoutMs>=1000&&timeoutMs<=600000); 12 let browser,timer,diagnostics; 13 try { 14 // Match the other browser harnesses: a fresh disk-backed profile per run. 15 browser=await webkit.launchPersistentContext(profile,{headless:true,viewport:{width:1280,height:900}}); 16 const page=await browser.newPage(),errors=[]; 17 page.on('pageerror',e=>errors.push(String(e))); 18 await page.goto(url); 19 if(process.env.TEST_DIAGNOSTICS)diagnostics=setInterval(()=>{void page.evaluate(()=>({status:document.getElementById('status')?.textContent,activity:document.getElementById('compile-activity')?.textContent})).then(state=>console.log('Page:',JSON.stringify(state))).catch(()=>{});},30000); 20 const report=await Promise.race([completion,new Promise((_,reject)=>{timer=setTimeout(()=>reject(Error('WebKit probe timeout; phases: '+JSON.stringify(marks.slice(-4)))),timeoutMs);})]); 21 assert.deepEqual(errors,[]); 22 if(process.env.TEST_IMPORT_PICKER){ 23 await page.click('#add-import'); 24 await page.waitForFunction(()=>document.querySelector('#import-results button')); 25 for(let i=0;i<8;i++){await page.keyboard.press('Tab');assert(await page.evaluate(()=>document.querySelector('#import-dialog').contains(document.activeElement)),'Dialog contains keyboard focus');} 26 await page.keyboard.press('Escape'); 27 assert(await page.evaluate(()=>!document.querySelector('#import-dialog').open&&document.activeElement.id==='add-import'),'Escape restores focus'); 28 await page.click('#add-import'); 29 await page.getByRole('button',{name:/^native-math ยท/}).click(); 30 } 31 for(const width of [320,390,1280]){ 32 await page.setViewportSize({width,height:844}); 33 // Let CodeMirror measure its editable viewport. 34 await page.evaluate(()=>new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)))); 35 if(process.env.TEST_IMPORT_PICKER)assert(await page.evaluate(()=>{ 36 const content=document.querySelector('#import-content').getBoundingClientRect(); 37 return ['import-cancel','insert-import','import-alias','import-preview'].every(id=>{ 38 const r=document.getElementById(id).getBoundingClientRect(); 39 return r.top>=0&&r.bottom<=innerHeight&&(id==='import-cancel'||id==='insert-import'||r.top>=content.top&&r.bottom<=content.bottom); 40 }); 41 }),'Import controls and preview visible at '+width); 42 const overflow=await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth ? [...document.querySelectorAll('body *')].filter(e=>{const r=e.getBoundingClientRect();return r.width&&r.right>innerWidth+1;}).map(e=>({tag:e.tagName,id:e.id,class:e.className,width:e.getBoundingClientRect().width,text:e.textContent.slice(0,100)})) : []); 43 assert.deepEqual(overflow,[],'Viewport overflow at '+width); 44 if(process.env.SCREENSHOT){await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:process.env.SCREENSHOT.replace(/\.png$/, '-'+width+'.png')});} 45 } 46 report.engine='Linux WebKit'; 47 if(process.env.BENCHMARK_REPORT)await writeFile(process.env.BENCHMARK_REPORT,JSON.stringify(report,null,2)+'\n'); 48 49 console.log('PASS '+report.engine+': '+report.checks.join(' / ')); 50 } finally { 51 clearTimeout(timer);clearInterval(diagnostics);await browser?.close();server.closeAllConnections();await new Promise(r=>server.close(r)); 52 await rm(profile,{recursive:true,force:true}); 53 }