Files
documentation/scripts/browser/presentation.cjs
jarvis-at-skic 946b6f1cbb
Build and publish Eldorado documentation / build (pull_request) Successful in 46s
docs: give slide 14 concrete workflow and skill metrics
2026-10-09 07:08:51 +00:00

56 lines
6.5 KiB
JavaScript

const {chromium}=require('playwright');
const staircaseFits=require('./presentation-staircase.cjs');
const fs=require('node:fs'); const assert=require('node:assert/strict');
(async()=>{
const base=process.argv[2]||'http://127.0.0.1:4179'; const root='/eldorado-v1/documentation/';const url=base+root+'presentations/less-prompting-more-shipping/';
const out='.cache/presentation';fs.mkdirSync(out,{recursive:true});
const browser=await chromium.launch({headless:true,args:['--no-sandbox'],executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE});
const results=[];
try{
for(const viewport of [{width:1440,height:900},{width:390,height:844},{width:844,height:390}]){
const context=await browser.newContext({viewport,hasTouch:viewport.width<1000,reducedMotion:'reduce'});
const page=await context.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message));page.on('response',r=>{if(r.status()>=400)errors.push(`${r.status()} ${r.url()}`)});page.on('console',m=>{if(m.type()==='error')errors.push(m.text())});
assert.equal((await page.goto(url,{waitUntil:'networkidle'})).status(),200);
await page.waitForFunction(()=>window.Reveal?.isReady());await page.evaluate(()=>document.fonts.ready);
assert.equal(await page.evaluate(()=>Reveal.getTotalSlides()),23);
assert.equal(await page.evaluate(()=>Reveal.getConfig().transition),'none');
const bounds=[];
for(let i=0;i<23;i++){
await page.evaluate(i=>Reveal.slide(i),i);await page.waitForTimeout(60);
const bad=await page.evaluate(()=>{
const slide=Reveal.getCurrentSlide(),r=slide.getBoundingClientRect();
return [...slide.querySelectorAll('.measurement-panels,.metric,.metric b,.metric span,.qualification-note,h3,svg,text,.journey,.learning-loop,.contribution-grid,h1,h2,p,li,td,th,.rail,.gate,.facts,.flow,.roles,.timeline,.capacity,.measure-list,.contrast,.comparison,.choices,.ledger')].filter(e=>!e.closest('.notes')&&e.getBoundingClientRect().width>0).filter(e=>{const b=e.getBoundingClientRect();return b.bottom>r.bottom+1||b.right>r.right+1||b.left<r.left-1||b.top<r.top-1}).map(e=>e.textContent.slice(0,60));
});
if(i===6)assert(await page.evaluate(staircaseFits),'staircase aligns each arrow with its intended steps');
if(i===4)assert(await page.evaluate(()=>[...document.querySelectorAll('#contributors .contribution-grid>div')].every(e=>{const a=e.querySelector('span').getBoundingClientRect(), arrow=e.querySelector('i').getBoundingClientRect(), b=e.querySelector('b').getBoundingClientRect();return a.bottom<=arrow.top+2&&arrow.bottom<=b.top+2&&Math.abs((a.left+a.right-b.left-b.right)/2)<2&&getComputedStyle(e.querySelector('i')).transform==='matrix(0, 1, -1, 0, 0, 0)'})),'contribution arrows must point down to their own phase');
bounds.push({slide:i+1,overflow:bad});
await page.screenshot({path:`${out}/${viewport.width}-slide-${String(i+1).padStart(2,'0')}.png`});
}
fs.writeFileSync(`${out}/${viewport.width}-bounds.json`,JSON.stringify(bounds,null,2));
assert.deepEqual(bounds.filter(b=>b.overflow.length),[],'slide overflow');
await page.goto(url+'#/qualification');await page.reload();await page.waitForFunction(()=>Reveal.isReady());assert.equal(await page.evaluate(()=>Reveal.getCurrentSlide().id),'qualification');
await page.keyboard.press('ArrowRight');assert.equal(await page.evaluate(()=>Reveal.getCurrentSlide().id),'experiment');await page.keyboard.press('ArrowLeft');
await page.getByRole('button',{name:'Overview',exact:true}).click();assert(await page.evaluate(()=>Reveal.isOverview()));await page.keyboard.press('Escape');assert(!await page.evaluate(()=>Reveal.isOverview()));
if(viewport.width===1440){
await page.getByRole('button',{name:'Fullscreen',exact:true}).click();await page.waitForFunction(()=>!!document.fullscreenElement);await page.getByRole('button',{name:'Fullscreen',exact:true}).click();await page.waitForFunction(()=>!document.fullscreenElement);
const popupPromise=context.waitForEvent('page');await page.getByRole('button',{name:'Notes',exact:true}).click();const popup=await popupPromise;await popup.waitForLoadState();await popup.waitForFunction(()=>document.body.innerText.includes('The author cannot approve'),{timeout:10000});await popup.screenshot({path:`${out}/speaker-view.png`});await popup.close();
} else {
const client=await context.newCDPSession(page);
const before=await page.evaluate(()=>Reveal.getIndices().h);
await client.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[{x:viewport.width*.8,y:viewport.height*.5}]});
await client.send('Input.dispatchTouchEvent',{type:'touchMove',touchPoints:[{x:viewport.width*.2,y:viewport.height*.5}]});
await client.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});
assert.equal(await page.evaluate(()=>Reveal.getIndices().h),before+1);
}
const links=await page.locator('a').evaluateAll(els=>els.map(e=>e.href).filter(h=>!h.includes('?')));
for(const link of new Set(links))assert.equal((await page.request.get(link)).status(),200,link);
await page.getByRole('link',{name:'Portal',exact:true}).click();await page.waitForURL(base+root);await page.getByRole('link',{name:/Open presentation/}).scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${viewport.width}-homepage.png`});await page.getByRole('link',{name:/Open presentation/}).click();await page.waitForFunction(()=>window.Reveal?.isReady());
assert.deepEqual(errors,[]);results.push({viewport,slides:23,overflow:false,errors,deepLinkRefresh:true,keyboard:true,overview:true,links:true,touch:viewport.width!==1440});await context.close();
}
const narrow=await browser.newPage({viewport:{width:320,height:720}});await narrow.goto(url,{waitUntil:'networkidle'});await narrow.evaluate(()=>document.fonts.ready);assert(await narrow.evaluate(()=>document.querySelector('.toolbar').scrollWidth<=innerWidth),'320px toolbar must not clip Print');await narrow.screenshot({path:out+'/320-toolbar.png'});await narrow.close();
const page=await browser.newPage({viewport:{width:1440,height:900}});await page.goto(url+'?print-pdf',{waitUntil:'networkidle'});await page.waitForFunction(()=>document.querySelectorAll('.pdf-page').length===23);await page.pdf({path:out+'/print.pdf',preferCSSPageSize:true,printBackground:true});
assert.equal(await page.locator('.pdf-page').count(),23);
fs.writeFileSync(`${out}/results.json`,JSON.stringify({results,printPages:23},null,2));console.log('PASS: 69 slide views, bounds, refresh/hash, keyboard, overview, touch, fullscreen, notes, all links, homepage, print');
}finally{await browser.close()}
})().catch(e=>{console.error(e);process.exitCode=1});