tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

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 }