const {chromium}=require('playwright'); 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()),19); assert.equal(await page.evaluate(()=>Reveal.getConfig().transition),'none'); const bounds=[]; for(let i=0;i<19;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('h1,h2,p,li,td,th,.rail,.gate,.facts,.flow,.roles,.timeline,.capacity,.measure-list,.contrast,.comparison,.choices,.ledger')].filter(e=>!e.closest('.notes')).filter(e=>{const b=e.getBoundingClientRect();return b.bottom>r.bottom+1||b.right>r.right+1||b.lefte.textContent.slice(0,60)); }); 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),'inconclusive');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:19,overflow:false,errors,deepLinkRefresh:true,keyboard:true,overview:true,links:true,touch:viewport.width!==1440});await context.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===19);await page.pdf({path:out+'/print.pdf',preferCSSPageSize:true,printBackground:true}); assert.equal(await page.locator('.pdf-page').count(),19); fs.writeFileSync(`${out}/results.json`,JSON.stringify({results,printPages:19},null,2));console.log('PASS: 57 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});