← back to CelebritySignatures
scripts/screenrecord-tk10191.mjs
65 lines
import pkg from '/Users/macstudio3/Projects/homesonspec/node_modules/.pnpm/playwright-core@1.61.1/node_modules/playwright-core/index.js'; const { chromium } = pkg;
import fs from 'fs';
const URL='http://localhost:9956/';
const BASE='/Users/macstudio3/Projects/CelebritySignatures/screenrecord';
const LOG=BASE+'/debug-log.jsonl';
const prior = fs.existsSync(LOG)? fs.readFileSync(LOG,'utf8').trim().split('\n').filter(Boolean).map(l=>{try{return JSON.parse(l)}catch{ return {}}}):[];
const priorБad=new Set(prior.filter(r=>r.errors&&r.errors.length).map(r=>r.selector));
const append=o=>fs.appendFileSync(LOG, JSON.stringify(o)+'\n');
const orderFor=(run,els)=>{
if(run===0)return els;
if(run===1)return [...els].reverse();
if(run===2)return [...els].sort((a,b)=>(b.type==='range')-(a.type==='range'));
if(run===3){const s=[...els];for(let i=s.length-1;i>0;i--){const j=(i*7+run*13)%(i+1);[s[i],s[j]]=[s[j],s[i]];}return s;}
return [...els].sort((a,b)=>(priorБad.has(b.sel))-(priorБad.has(a.sel)));
};
const allRunErrors=[];
for(let run=0;run<5;run++){
const browser=await chromium.launch({channel:'chrome',headless:true});
const ctx=await browser.newContext({viewport:{width:1440,height:900},recordVideo:{dir:`${BASE}/rec/run${run}`}});
const page=await ctx.newPage();
let errs=[]; page.on('console',m=>m.type()==='error'&&errs.push(m.text().slice(0,300))); page.on('pageerror',e=>errs.push('PAGEERROR: '+(''+e).slice(0,300)));
await page.goto(URL,{waitUntil:'domcontentloaded',timeout:20000});
await page.waitForTimeout(1500);
const loadErrs=errs.splice(0); if(loadErrs.length) append({run,ts:Date.now(),selector:'(pageload)',label:'initial load',action:'goto',ok:false,errors:loadErrs});
// discover
const els=await page.evaluate(()=>{
const out=[]; const seen=new Set();
const sel=el=>{ if(el.id)return '#'+CSS.escape(el.id); const t=el.tagName.toLowerCase(); const c=(el.className&&el.className.toString().trim().split(/\s+/)[0])||''; const txt=(el.textContent||'').trim().slice(0,20); return t+(c?'.'+CSS.escape(c):'')+(txt?`:has("${txt}")`:''); };
document.querySelectorAll('button, a[href], [role=button], [onclick], input[type=range], input[type=checkbox], [data-action], nav a, .tab, .chip, select').forEach(el=>{
const s=sel(el); const label=(el.getAttribute('aria-label')||el.textContent||el.value||el.getAttribute('href')||'').trim().slice(0,40);
const key=s+'|'+label; if(seen.has(key))return; seen.add(key);
out.push({sel:s, label, type:(el.type||el.tagName.toLowerCase()), href:el.getAttribute&&el.getAttribute('href')||null});
});
return out;
});
append({run,ts:Date.now(),selector:'(discover)',label:`${els.length} interactive els`,action:'enumerate',ok:true,errors:[]});
const ordered=orderFor(run,els);
let acted=0;
for(const e of ordered){
if(acted>=60){ append({run,ts:Date.now(),selector:'(cap)',label:'capped at 60 actions',action:'skip',ok:true,errors:[]}); break; }
try{
// for links that leave the page, record + skip actual nav to keep front-page focus (log href)
const isNav = e.type==='a' && e.href && !e.href.startsWith('#') && !/javascript:/i.test(e.href);
const loc=page.locator(e.sel).first();
if(await loc.count()===0){ continue; }
await loc.scrollIntoViewIfNeeded({timeout:2000}).catch(()=>{});
if(isNav){ append({run,ts:Date.now(),selector:e.sel,label:e.label,action:'nav-link(logged, not followed)',ok:true,effect:'href='+e.href,errors:errs.splice(0)}); acted++; continue; }
const before=await page.evaluate(()=>document.body.innerText.length).catch(()=>0);
if(e.type==='range'){ await loc.fill(String(Math.floor(Math.random()*100))).catch(async()=>{await loc.click({timeout:2000}).catch(()=>{});}); }
else { await loc.click({timeout:2500,force:false}).catch(async()=>{await loc.click({timeout:1500,force:true}).catch(()=>{});}); }
await page.waitForTimeout(350);
const after=await page.evaluate(()=>document.body.innerText.length).catch(()=>0);
append({run,ts:Date.now(),selector:e.sel,label:e.label,action:'click',ok:errs.length===0,effect:`text ${before}->${after}`,errors:errs.splice(0)});
acted++;
// dismiss any modal/overlay + ensure still on base
await page.keyboard.press('Escape').catch(()=>{});
if(!page.url().startsWith(URL)){ await page.goto(URL,{waitUntil:'domcontentloaded'}).catch(()=>{}); }
}catch(err){ append({run,ts:Date.now(),selector:e.sel,label:e.label,action:'click',ok:false,errors:[...errs.splice(0),'THROW: '+(''+err).slice(0,150)]}); }
}
const runErrCount=prior.length; // n/a
await ctx.close(); await browser.close();
console.log(`run ${run}: ${ordered.length} els, ${acted} acted`);
}
console.log('DONE 5 runs');