[object Object]

← back to Commercialrealestate

5x night item 2: crcp.html strong gate (crcp-assert.js — tiles/segments/expand/modal/sort/empty all PASS); six-way 6/6 with correct visible selector. No crcp defect — M3 FAIL was collapse-default vs visibility-selector mismatch, not a bug

928c43fab2b328d05f36832225919fffbf697021 · 2026-06-28 23:33:32 -0700 · Steve

Files touched

Diff

commit 928c43fab2b328d05f36832225919fffbf697021
Author: Steve <steve@designerwallcoverings.com>
Date:   Sun Jun 28 23:33:32 2026 -0700

    5x night item 2: crcp.html strong gate (crcp-assert.js — tiles/segments/expand/modal/sort/empty all PASS); six-way 6/6 with correct visible selector. No crcp defect — M3 FAIL was collapse-default vs visibility-selector mismatch, not a bug
---
 5x/crcp-assert.js   | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5x/crcp-sweep-1.raw | 19 ++++++++++++++++++
 5x/crcp-sweep-2.raw | 15 ++++++++++++++
 3 files changed, 91 insertions(+)

diff --git a/5x/crcp-assert.js b/5x/crcp-assert.js
new file mode 100644
index 0000000..596f2df
--- /dev/null
+++ b/5x/crcp-assert.js
@@ -0,0 +1,57 @@
+// Strong crcp.html gate: tiles render with data (no NaN), 8 segment rows ATTACHED+correct, collapsed panel
+// expands to visible, segment modal opens with a call-list, broker sort reorders, empty-data degrades clean.
+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('**/api/segments',r=>r.fulfill({status:200,contentType:'application/json',body:'{"segments":[]}'}));
+    await pg.route('**/api/crcp/stats',r=>r.fulfill({status:200,contentType:'application/json',body:'{}'}));
+  }
+  await pg.goto('http://127.0.0.1:9911/crcp.html',{waitUntil:'networkidle'}); await pg.waitForTimeout(1500);
+  const base=await pg.evaluate(()=>{
+    const tiles=[...document.querySelectorAll('#tiles .tile .v')].map(v=>v.textContent);
+    const srows=[...document.querySelectorAll('.srow')];
+    const cellText=srows.map(r=>r.textContent).join(' ');
+    return { tiles, segRowsAttached:srows.length, anyNaN:/NaN|undefined/.test(cellText+' '+tiles.join(' ')),
+      segVisibleBefore: srows.length?srows[0].offsetParent!==null:false };
+  });
+  let expanded=false, modal={}, sortOk=null;
+  if(!mockEmpty){
+    // expand the Call Segments panel (the .panel that holds #segTbl)
+    expanded=await pg.evaluate(()=>{ const t=document.querySelector('#segTbl'); const p=t&&t.closest('.panel');
+      if(!p) return false; const h=p.querySelector('h3'); if(p.classList.contains('collapsed')) h.click();
+      return !p.classList.contains('collapsed'); });
+    await pg.waitForTimeout(250);
+    const visAfter=await pg.evaluate(()=>{ const r=document.querySelector('.srow'); return r? r.offsetParent!==null:false; });
+    // click first clickable segment row → modal with call list
+    await pg.evaluate(()=>{ const r=[...document.querySelectorAll('.srow')].find(x=>x.style.cursor==='pointer'); if(r)r.click(); });
+    await pg.waitForTimeout(900);
+    modal=await pg.evaluate(()=>({ open:document.querySelector('#ov')?.classList.contains('on'),
+      items:document.querySelectorAll('#mbody .brow3').length, hasHeading:!!document.querySelector('#mbody h2') }));
+    await pg.evaluate(()=>{ const ov=document.querySelector('#ov'); if(ov)ov.classList.remove('on'); });
+    modal.visAfterExpand=visAfter;
+    // broker table sort: expand its panel, capture order, click a header, compare
+    sortOk=await pg.evaluate(async()=>{ const t=document.querySelector('#brTbl'); const p=t&&t.closest('.panel');
+      if(p&&p.classList.contains('collapsed')) p.querySelector('h3').click();
+      await new Promise(r=>setTimeout(r,150));
+      const before=[...document.querySelectorAll('#brTbl tbody tr')].map(r=>r.textContent).slice(0,5).join('|');
+      const th=document.querySelector('#brTbl th.srt[data-col=name]'); if(!th) return null; th.click();
+      await new Promise(r=>setTimeout(r,200));
+      const after=[...document.querySelectorAll('#brTbl tbody tr')].map(r=>r.textContent).slice(0,5).join('|');
+      return { changed: before!==after, rows: document.querySelectorAll('#brTbl tbody tr').length }; });
+  }
+  await b.close();
+  return { mockEmpty, ...base, expanded, modal, sortOk, jsErrors:errors };
+}
+(async()=>{
+  const normal=await run(false); const empty=await run(true);
+  const passNormal = normal.segRowsAttached>=7 && !normal.anyNaN && normal.expanded && normal.modal.visAfterExpand
+    && normal.modal.open && normal.modal.hasHeading && (normal.modal.items>0) && normal.sortOk && normal.sortOk.changed && 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);});
diff --git a/5x/crcp-sweep-1.raw b/5x/crcp-sweep-1.raw
new file mode 100644
index 0000000..1c0b6d2
--- /dev/null
+++ b/5x/crcp-sweep-1.raw
@@ -0,0 +1,19 @@
+
+/3x — verifying http://127.0.0.1:9911/crcp.html
+
+Phase A — 3 unique methods:
+  [PASS] M1 HTTP contract  request layer — HTTP 200 text/html
+  [PASS] M2 headless render  render layer — screenshot 84KB → /var/folders/2n/jmw9_4v56_x4m3539tr4v0lr0000gn/T/3x-TKmVpN/render.png
+  [FAIL] M3 automation E2E  interaction layer — page.waitForSelector: Timeout 8000ms exceeded.
+Call log:
+  - waiting for locator('#segTbl tbody tr') to be visible
+    21 × locator resolved to 8 elements. Proceeding with the first one: <tr class="srow" data-key="mixed-use">…</tr>
+
+
+Phase B — 3 browsers (cross-browser):
+  [SKIP] B4 Google Chrome  cross-browser — engine not installed, --no-open set
+  [SKIP] B5 Safari  cross-browser — engine not installed, --no-open set
+  [SKIP] B6 Firefox  cross-browser — engine not installed, --no-open set
+
+  RESULT → 2/3 passed, 1 FAILED, 3 skipped
+  artifacts: /var/folders/2n/jmw9_4v56_x4m3539tr4v0lr0000gn/T/3x-TKmVpN
diff --git a/5x/crcp-sweep-2.raw b/5x/crcp-sweep-2.raw
new file mode 100644
index 0000000..cccf2b8
--- /dev/null
+++ b/5x/crcp-sweep-2.raw
@@ -0,0 +1,15 @@
+
+/3x — verifying http://127.0.0.1:9911/crcp.html
+
+Phase A — 3 unique methods:
+  [PASS] M1 HTTP contract  request layer — HTTP 200 text/html
+  [PASS] M2 headless render  render layer — screenshot 84KB → /var/folders/2n/jmw9_4v56_x4m3539tr4v0lr0000gn/T/3x-cCYJrI/render.png
+  [PASS] M3 automation E2E  interaction layer — 7×"#tiles .tile", 0 JS errors
+
+Phase B — 3 browsers (cross-browser):
+  [PASS] B4 Google Chrome  cross-browser — automated render OK
+  [PASS] B5 Safari  cross-browser — automated render OK
+  [PASS] B6 Firefox  cross-browser — automated render OK
+
+  RESULT → 6/6 passed
+  artifacts: /var/folders/2n/jmw9_4v56_x4m3539tr4v0lr0000gn/T/3x-cCYJrI

← cdaa2b4 5x night-log: items 1+3 done; queue + method note for next w  ·  back to Commercialrealestate  ·  5x night item 5: harden geocoder — strip unit designators (# ad89b92 →