const {chromium}=require('playwright'); const fs=require('node:fs'); const path=require('node:path'); const assert=require('node:assert/strict'); (async()=>{ const dir=process.argv[2]||'.cache/skills-candidate'; const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']}); const results=[]; try { for(const topic of ['measurement','baseline','governance','quality','adoption','maintenance']) for(const width of [1440,1024,390,320]){ const spec=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}${width<=1100?'-mobile':''}.architecture.json`)); const page=await browser.newPage({viewport:{width:1200,height:1000}}); await page.goto('file://'+path.resolve(`${dir}/${topic}-${width}.svg`)); const measured=await page.locator('svg').evaluate(svg=>{ const v=svg.viewBox.baseVal;const issues=[]; for(const el of svg.querySelectorAll('[data-node-id],path[data-edge-id],g[data-edge-id]')){ const b=el.getBBox();if(b.xv.x+v.width+1||b.y+b.height>v.y+v.height+1)issues.push(el.getAttribute('data-node-id')||el.getAttribute('data-edge-id')); } // Measure the whole rendered label group, including its opaque mask: // text presence alone cannot detect one label hiding another. const labels=[...svg.querySelectorAll('g[data-edge-id]')].filter(el=>el.querySelector('text')).map(el=>({id:el.dataset.edgeId,box:el.getBoundingClientRect()})); const labelOverlaps=[]; for(let i=0;iMath.max(a.box.left,b.box.left)&&Math.min(a.box.bottom,b.box.bottom)>Math.max(a.box.top,b.box.top))labelOverlaps.push([a.id,b.id]); } return {labelOverlaps,viewBox:[v.width,v.height],nodes:[...svg.querySelectorAll('[data-node-id]')].map(n=>n.dataset.nodeId),edges:[...svg.querySelectorAll('path[data-edge-id]')].map(n=>n.dataset.edgeId),text:svg.textContent,issues}; }); assert.deepEqual(measured.viewBox,spec.meta.viewBox); assert.deepEqual(measured.nodes.sort(),spec.components.map(n=>n.id).sort()); assert.deepEqual(measured.edges.sort(),spec.connections.map(e=>e.id).sort()); assert.deepEqual(measured.issues,[]); assert.deepEqual(measured.labelOverlaps,[],`${topic}-${width}: rendered edge labels overlap`); for(const n of spec.components){assert(measured.text.includes(n.label));assert(measured.text.includes(n.tag));for(const line of n.sublabel.split('\n'))assert(measured.text.includes(line));} for(const e of spec.connections)if(e.label)assert(measured.text.includes(e.label)); if(width===1440){ await page.setViewportSize({width:spec.meta.viewBox[0],height:spec.meta.viewBox[1]}); await page.screenshot({path:`${dir}/${topic}-standalone-export.png`}); } results.push({topic,width,nodes:measured.nodes.length,edges:measured.edges.length,complete:true});await page.close(); } fs.writeFileSync(`${dir}/export-results.json`,JSON.stringify(results,null,2)); console.log(`PASS ${results.length} standalone SVGs: exact graph, text, full-canvas containment and non-overlapping edge labels`); }finally{await browser.close();} })().catch(e=>{console.error(e);process.exitCode=1});