const {chromium}=require(process.env.PLAYWRIGHT_MODULE || 'playwright-core'); const fs=require('fs'); const assert=require('assert/strict'); (async()=>{ const browser=await chromium.launch({headless:true,executablePath:process.env.CHROMIUM_BIN}); try { const page=await browser.newPage({viewport:{width:1440,height:1000}}); const errors=[];page.on('pageerror',e=>errors.push(String(e))); const {execFileSync}=require('child_process'); const data=JSON.parse(execFileSync(process.env.PYTHON_BIN || 'python3',['-c',` import json,sys sys.path.insert(0,${JSON.stringify(__dirname)}) import workflow,trigger data={'cards':[ {'id':'ready','title':'Implement the acceptance criteria','source':'intent','phase':'geplant'}, {'id':'blocked','title':'Repair publication before continuing','source':'intent','phase':'in_umsetzung','last_run_status':'publish_failed','failure_stage':'publication','failure_detail':'Push rejected; worktree retained.'}, {'id':'legacy','title':'Check the historical deployment','source':'intent','phase':'deployed','review_report':'docs/review/legacy.md'}, {'id':'parent','title':'Complete the family','source':'intent','phase':'wartet_auf_kinder'}, {'id':'child','title':'Answer the child question','source':'intent','phase':'inspector_rueckfrage','parent_id':'parent','clarification_question':'Which acceptance criterion?'}, {'id':'archive','title':'Archived goal','source':'intent','phase':'archiviert'}, {'id':'done','title':'Deployed goal','source':'intent','phase':'deployed','deployment_status':'deployed','deployed_commit_hash':'a'*40,'activated_system':'/nix/store/verified-system'} ]} for card in data['cards']: children=[c for c in data['cards'] if c.get('parent_id')==card['id']] card['display']=workflow.presentation(card,children) card['available_actions']=trigger.available_actions(card['id'],card['source'],card) print(json.dumps(data)) `],{encoding:'utf8'})); let offline=false; await page.route('**/*',route=>{ const url=new URL(route.request().url()); assert.equal(route.request().method(),'GET','Browser test must not mutate live state'); if(url.pathname==='/')return route.fulfill({contentType:'text/html',body:fs.readFileSync(require('path').join(__dirname,'board.html'),'utf8')}); if(url.pathname==='/api/board')return offline?route.abort():route.fulfill({json:data}); return route.fulfill({json:{content:'Fixture report: verified local browser test.',runs:[]}}); }); await page.goto('http://board.test/');await page.waitForSelector('.card'); assert.equal(await page.locator('#settings-dialog').isVisible(),false); assert.equal(await page.locator('.column[data-lifecycle=archived]').count(),0); await page.screenshot({path:'/tmp/intent-board-candidate-desktop.png'}); await page.locator('[data-action=details]').first().click(); await page.getByRole('button',{name:'Evidence',exact:true}).click(); await page.screenshot({path:'/tmp/intent-board-candidate-evidence.png'}); await page.keyboard.press('Escape'); await page.locator('#view').selectOption('archived'); assert.ok(await page.locator('.card').count()>0); await page.locator('#search').fill('no-match-xyz');assert.equal(await page.locator('.card').count(),0); await page.locator('#search').fill('');await page.locator('#view').selectOption('all'); const first=page.locator('[data-action=details]').first();await first.focus(); await page.evaluate(()=>render(true)); assert.equal(await page.evaluate(()=>document.activeElement.dataset.action),'details'); await page.setViewportSize({width:390,height:844});await page.emulateMedia({colorScheme:'dark'}); const dimensions=await page.evaluate(()=>({viewport:innerWidth,width:document.documentElement.scrollWidth})); assert.ok(dimensions.width<=dimensions.viewport,JSON.stringify(dimensions)); await page.screenshot({path:'/tmp/intent-board-candidate-mobile.png'}); offline=true;await page.evaluate(()=>render(true)); assert.match(await page.locator('#connection').innerText(),/unavailable/); assert.ok(await page.locator('.card').count()>0);assert.deepEqual(errors,[]); console.log(JSON.stringify({passed:true,dimensions,errors,screenshots:'/tmp/intent-board-candidate-*.png'})); } finally {await browser.close();} })().catch(error=>{console.error(error);process.exitCode=1;});