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:4173'; const out=`.cache/skills-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true}); const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']}); const results=[]; try { for(const topic of ['governance','quality','adoption','measurement','maintenance']) for(const width of [1440,1024,390,320]) { const page=await browser.newPage({viewport:{width,height:900},colorScheme:'light'});const errors=[];page.on('pageerror',e=>errors.push(e.message)); const route=topic==='measurement'?topic:`skills-${topic}`; assert.equal((await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}/`,{waitUntil:'networkidle'})).status(),200); const panel=page.locator('.archify-panel--skills');assert.equal(await panel.count(),1); const iframe=panel.locator(width>1100?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded(); const frame=await(await iframe.elementHandle()).contentFrame();await frame.locator('svg[role="img"]').waitFor(); const geometry=await frame.locator('svg[role="img"]').evaluate(svg=>{ const nodes=[...svg.querySelectorAll('g[data-node-id]')];const issues=[];let min=Infinity; for(const n of nodes){const rect=n.querySelector('rect').getBBox();for(const t of n.querySelectorAll('text')){ const b=t.getBBox();min=Math.min(min,parseFloat(getComputedStyle(t).fontSize)*t.getScreenCTM().a); if(b.xrect.x+rect.width||b.y+b.height>rect.y+rect.height)issues.push(n.id+':'+t.textContent); }} return {nodes:nodes.length,min,issues,width:innerWidth,svgWidth:svg.getBoundingClientRect().width}; }); const source=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}.architecture.json`)); assert.equal(geometry.nodes,source.components.length);assert.deepEqual(geometry.issues,[]);assert(geometry.min>=10,JSON.stringify(geometry)); for(const theme of ['light','dark']){ if(await frame.locator('html').getAttribute('data-theme')!==theme)await frame.locator('#btn-theme').click(); await page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme); await panel.scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${topic}-${width}-${theme}-inline.png`}); const open=panel.getByRole('button',{name:/^Expand /});await open.click();const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'}); const expanded=await(await panel.locator('dialog iframe').elementHandle()).contentFrame();await expanded.locator('svg[role="img"]').waitFor(); assert((await expanded.url()).includes(width<=1100?`${topic}-mobile/`:`${topic}/`)); await page.screenshot({path:`${out}/${topic}-${width}-${theme}-fullscreen.png`}); if(width<=700){await page.setViewportSize({width,height:480});assert(await panel.locator('dialog').evaluate(n=>n.scrollHeight>n.clientHeight));await panel.locator('dialog').evaluate(n=>n.scrollTop=n.scrollHeight);await page.screenshot({path:`${out}/${topic}-${width}-${theme}-short-bottom.png`});await page.setViewportSize({width,height:900});} await close.focus();await page.keyboard.press('Escape');assert(await open.evaluate(n=>n===document.activeElement)); } await frame.locator('#btn-preset').click();await frame.locator('[data-preset-value="blueprint"]').click(); await frame.locator('#btn-preset').click();await frame.locator('[data-preset-value="classic"]').click(); await frame.locator('#btn-export').click();const [download]=await Promise.all([page.waitForEvent('download'),frame.locator('[data-format="svg"]').click()]);assert.equal(await download.failure(),null); await download.saveAs(`${out}/${topic}-${width}.svg`);assert(fs.readFileSync(`${out}/${topic}-${width}.svg`,'utf8').includes('eldorado-skills-typography')); assert(!await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth));assert.deepEqual(errors,[]); results.push({topic,width,geometry,controls:true,export:true,themes:true,fullscreen:true});fs.writeFileSync(`${out}/results.json`,JSON.stringify(results,null,2));await page.close(); } console.log(`PASS ${results.length} Skills story contexts: geometry, themes, controls, exports, fullscreen and short-phone scrolling`); }finally{await browser.close();} })().catch(e=>{console.error(e);process.exitCode=1});