← back to Commercialrealestate

5x/sales-assert.js

38 lines

// Strong sales.html gate: table rows render with data (no NaN), both charts drew, a filter narrows rows,
// depth note present; empty-data degrades with no NaN/error.
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/closed-sales**',r=>r.fulfill({status:200,contentType:'application/json',body:'{"sales":[],"rows":[]}'}));
  await pg.goto('http://127.0.0.1:9911/sales.html',{waitUntil:'networkidle'}); await pg.waitForTimeout(1800);
  const base=await pg.evaluate(()=>{
    const rows=[...document.querySelectorAll('#tbl tbody tr')];
    const cellTxt=rows.slice(0,40).map(r=>r.textContent).join(' ');
    return { rows:rows.length, anyNaN:/NaN|undefined/.test(cellTxt),
      cityChart:!!(window.Chart&&Chart.getChart('cityChart')), yearChart:!!(window.Chart&&Chart.getChart('yearChart')),
      depthNote:(document.querySelector('#depthNote')?.textContent||'').length>0 };
  });
  let filterOk=null;
  if(!mockEmpty){
    filterOk=await pg.evaluate(async()=>{ const sel=document.querySelector('#city'); if(!sel||sel.tagName!=='SELECT'||(sel.options||[]).length<2) return null;
      const before=document.querySelectorAll('#tbl tbody tr').length;
      sel.selectedIndex=1; sel.dispatchEvent(new Event('change'));
      await new Promise(r=>setTimeout(r,400));
      const after=document.querySelectorAll('#tbl tbody tr').length;
      return { before, after, narrowed: after<=before && after>0 }; });
  }
  await b.close();
  return { mockEmpty, ...base, filterOk, jsErrors:errors };
}
(async()=>{
  const normal=await run(false); const empty=await run(true);
  const passNormal = normal.rows>0 && !normal.anyNaN && normal.cityChart && normal.yearChart && (!normal.filterOk||normal.filterOk.narrowed) && 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);});