backend-webkit.mjs (3367B)
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}=await startSiteServer(process.argv[2]||'unused',true); 9 const profile=await mkdtemp(join(tmpdir(),'tricu-webkit-')); 10 let browser,timer; 11 try { 12 // Match the other browser harnesses: a fresh disk-backed profile per run. 13 browser=await webkit.launchPersistentContext(profile,{headless:true,viewport:{width:1280,height:900}}); 14 const page=await browser.newPage(),errors=[]; 15 page.on('pageerror',e=>errors.push(String(e))); 16 await page.goto(url); 17 const report=await Promise.race([completion,new Promise((_,reject)=>{timer=setTimeout(()=>reject(Error('WebKit probe timeout')),240000);})]); 18 assert.deepEqual(errors,[]); 19 if(process.env.TEST_IMPORT_PICKER){ 20 await page.click('#add-import'); 21 await page.waitForFunction(()=>document.querySelector('#import-results button')); 22 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');} 23 await page.keyboard.press('Escape'); 24 assert(await page.evaluate(()=>!document.querySelector('#import-dialog').open&&document.activeElement.id==='add-import'),'Escape restores focus'); 25 await page.click('#add-import'); 26 await page.getByRole('button',{name:/^native-math ยท/}).click(); 27 } 28 for(const width of [320,390,1280]){ 29 await page.setViewportSize({width,height:844}); 30 // Let ResizeObserver update the textarea's decorative mirror geometry. 31 await page.evaluate(()=>new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)))); 32 if(process.env.TEST_IMPORT_PICKER)assert(await page.evaluate(()=>{ 33 const content=document.querySelector('#import-content').getBoundingClientRect(); 34 return ['import-cancel','insert-import','import-alias','import-preview'].every(id=>{ 35 const r=document.getElementById(id).getBoundingClientRect(); 36 return r.top>=0&&r.bottom<=innerHeight&&(id==='import-cancel'||id==='insert-import'||r.top>=content.top&&r.bottom<=content.bottom); 37 }); 38 }),'Import controls and preview visible at '+width); 39 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)})) : []); 40 assert.deepEqual(overflow,[],'Viewport overflow at '+width); 41 if(process.env.SCREENSHOT){await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:process.env.SCREENSHOT.replace(/\.png$/, '-'+width+'.png')});} 42 } 43 report.engine='Linux WebKit'; 44 if(process.env.BENCHMARK_REPORT)await writeFile(process.env.BENCHMARK_REPORT,JSON.stringify(report,null,2)+'\n'); 45 46 console.log('PASS '+report.engine+': '+report.checks.join(' / ')); 47 } finally { 48 clearTimeout(timer);await browser?.close();server.closeAllConnections();await new Promise(r=>server.close(r)); 49 await rm(profile,{recursive:true,force:true}); 50 }