← 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);});