← back to Commercialrealestate
5x/brokers-assert.js
48 lines
// Strong brokers.html gate (tests the REAL interaction model — verified against source):
// • vis-network canvas rendered, broker list populated (no NaN), stats present
// • #blist row click sets the firm search box (#firmq) + highlights graph [line 131]
// • showDetail(node) — the graph-node-click handler [line 76→78] — populates the detail pane
// • empty graph degrades with no crash/NaN
const pw=require('/Users/macstudio3/.claude/skills/browserbase/node_modules/playwright-core');
const EXEC='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
async function run(mockEmpty){
const errors=[]; const b=await pw.chromium.launch({executablePath:EXEC,headless:true});
const pg=await b.newPage({viewport:{width:1280,height:900}});
pg.on('pageerror',e=>errors.push('PAGEERR: '+e.message));
pg.on('console',m=>{if(m.type()==='error'&&!/Failed to load resource/.test(m.text()))errors.push('CONSOLE: '+m.text());});
if(mockEmpty){
await pg.route('**/api/graph**',r=>r.fulfill({status:200,contentType:'application/json',body:'{"nodes":[],"edges":[]}'}));
await pg.route('**/api/brokers/top**',r=>r.fulfill({status:200,contentType:'application/json',body:'{"topBrokers":[],"brokers":[]}'}));
await pg.route('**/api/brokers/enrich-stats**',r=>r.fulfill({status:200,contentType:'application/json',body:'{}'}));
}
await pg.goto('http://127.0.0.1:9911/brokers.html',{waitUntil:'networkidle'}); await pg.waitForTimeout(2600);
const base=await pg.evaluate(()=>({
netCanvas:!!document.querySelector('#net canvas'), netW:document.querySelector('#net canvas')?.width||0,
blist:document.querySelector('#blist')?.children.length||0,
anyNaN:/NaN|undefined/.test((document.querySelector('#blist')?.textContent||'')+(document.querySelector('#stats')?.textContent||'')) }));
let interOk=null;
if(!mockEmpty){
interOk=await pg.evaluate(async()=>{
const row=document.querySelector('#blist .row'); const name=row?.dataset.name;
if(row) row.click(); await new Promise(r=>setTimeout(r,200));
const firmqSet = !!name && document.querySelector('#firmq')?.value===name; // real row behavior
let detailPopulated=false;
if(typeof showDetail==='function' && typeof GRAPH==='object' && GRAPH.nodes && GRAPH.nodes.length){
showDetail(GRAPH.nodes[0].id); await new Promise(r=>setTimeout(r,350)); // real node-click behavior
detailPopulated = document.querySelector('#detailwrap').style.display!=='none' && (document.querySelector('#detail')?.textContent||'').length>10;
}
return { firmqSet, detailPopulated };
});
}
await b.close();
return { mockEmpty, ...base, interOk, jsErrors:errors };
}
(async()=>{
const normal=await run(false); const empty=await run(true);
const passNormal = normal.netCanvas && normal.netW>0 && normal.blist>0 && !normal.anyNaN
&& normal.interOk && normal.interOk.firmqSet && normal.interOk.detailPopulated && normal.jsErrors.length===0;
const passEmpty = !empty.anyNaN && empty.jsErrors.length===0;
console.log(JSON.stringify({normal,empty,passNormal,passEmpty,VERDICT:(passNormal&&passEmpty)?'PASS':'FAIL'},null,2));
process.exit((passNormal&&passEmpty)?0:1);
})().catch(e=>{console.error('FAIL',e.message);process.exit(1);});