← back to Commercialrealestate
5x: index.html strong gate (index-assert.js — 1407 cards/no-NaN/loopnet+rent links/sort-reorders/filter-narrows/empty-degrades, PASS). No defect; all 6 pages now gated. Added index to health-check.sh
9c2a5fc2872d3ef9ab580cb9f9efd6205ef079e7 · 2026-06-29 01:49:55 -0700 · Steve
Files touched
M 5x/health-check.shA 5x/index-assert.js
Diff
commit 9c2a5fc2872d3ef9ab580cb9f9efd6205ef079e7
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Jun 29 01:49:55 2026 -0700
5x: index.html strong gate (index-assert.js — 1407 cards/no-NaN/loopnet+rent links/sort-reorders/filter-narrows/empty-degrades, PASS). No defect; all 6 pages now gated. Added index to health-check.sh
---
5x/health-check.sh | 2 +-
5x/index-assert.js | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/5x/health-check.sh b/5x/health-check.sh
index c5ab95f..1ccf214 100755
--- a/5x/health-check.sh
+++ b/5x/health-check.sh
@@ -5,7 +5,7 @@ cd "$(dirname "$0")/.."
code=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9911/crcp.html 2>/dev/null)
[ "$code" = "200" ] || { echo "SERVER DOWN ($code) — restart: node scripts/serve.js &"; exit 1; }
fail=0
-for g in deals map crcp sales brokers; do
+for g in deals map crcp sales brokers index; do
if node "5x/$g-assert.js" >/dev/null 2>&1; then echo " $g-assert: PASS"; else echo " $g-assert: FAIL"; fail=1; fi
done
[ $fail = 0 ] && echo "ALL GATES PASS — healthy" || echo "REGRESSION DETECTED"
diff --git a/5x/index-assert.js b/5x/index-assert.js
new file mode 100644
index 0000000..8bad0a9
--- /dev/null
+++ b/5x/index-assert.js
@@ -0,0 +1,45 @@
+// Strong index.html gate (primary property viewer). Tests the REAL DOM (verified by probe):
+// • 1407 ranked cards under .grid render, NO NaN/$NaN, count text present, LoopNet + rent lines present
+// • changing #sort reorders the cards (first card changes)
+// • clicking a filter .chip narrows the result set
+// • empty data (mocked ranked.json/listings.json) degrades: 0 cards, no NaN, 0 swallowed JS errors
+const pw=require('/Users/stevestudio2/.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:1320,height:1000}});
+ 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('**/ranked.json',r=>r.fulfill({status:200,contentType:'application/json',body:'{"ranked":[]}'}));
+ await pg.route('**/listings.json',r=>r.fulfill({status:200,contentType:'application/json',body:'{"listings":[]}'}));
+ }
+ await pg.goto('http://127.0.0.1:9911/index.html',{waitUntil:'networkidle'}); await pg.waitForTimeout(2000);
+ const base=await pg.evaluate(()=>({
+ cards:document.querySelectorAll('.grid .card').length,
+ anyNaN:/NaN|\$NaN|undefined/.test([...document.querySelectorAll('.grid .card')].slice(0,40).map(c=>c.textContent).join(' ')),
+ loopnet:document.querySelectorAll('.src a[href*="loopnet"], .src a[href*="site:loopnet"]').length,
+ rentLines:[...document.querySelectorAll('.card')].filter(c=>/Est\. rent/.test(c.textContent)).length,
+ countTxt:(document.querySelector('.bar .count')?.textContent||'').replace(/\s+/g,' ').trim() }));
+ let sortOk=null, filterOk=null;
+ if(!mockEmpty){
+ sortOk=await pg.evaluate(async()=>{ const sel=document.querySelector('#sort'); if(!sel||sel.options.length<2) return null;
+ const first=()=>document.querySelector('.grid .card .addr')?.textContent||document.querySelector('.grid .card')?.textContent.slice(0,40);
+ const before=first(); sel.selectedIndex=(sel.selectedIndex+1)%sel.options.length; sel.dispatchEvent(new Event('change'));
+ await new Promise(r=>setTimeout(r,500)); return { before, after:first(), changed:before!==first() }; });
+ filterOk=await pg.evaluate(async()=>{ const chip=document.querySelector('.chip'); if(!chip) return null;
+ const n=()=>document.querySelectorAll('.grid .card').length; const before=n();
+ chip.click(); await new Promise(r=>setTimeout(r,500)); const after=n();
+ return { before, after, narrowed: after<before && after>=0 }; });
+ }
+ await b.close();
+ return { mockEmpty, ...base, sortOk, filterOk, jsErrors:errors };
+}
+(async()=>{
+ const normal=await run(false); const empty=await run(true);
+ const passNormal = normal.cards>0 && !normal.anyNaN && normal.loopnet>0 && normal.rentLines>0
+ && (!normal.sortOk||normal.sortOk.changed) && (!normal.filterOk||normal.filterOk.narrowed) && normal.jsErrors.length===0;
+ const passEmpty = empty.cards===0 && !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);});
← 9455571 5x: health-check.sh (server + all 5 strong gates) + night-lo
·
back to Commercialrealestate
·
5x: OVERNIGHT-REPORT.md (final) — all 6 pages gated + PASS; 119516b →