import { chromium } from '../tools/playwright/node_modules/playwright/index.mjs'; import assert from 'node:assert/strict'; const transcript = Array.from({length:5000}, (_, i) => ({role:i%2?'assistant':'user', content:`Message ${i}\n\n${'Variable height **Markdown** content. '.repeat(i%8+1)}`,at:new Date(1700000000000+i*60000).toISOString()})); const activity={state:'idle',running:false,queued:false,active_task_ids:[]}; const browser=await chromium.launch({headless:true}); try { const page=await browser.newPage({viewport:{width:1280,height:800}}); const errors=[];page.on('pageerror',e=>errors.push(e.message)); await page.addInitScript(()=>{window.sources=[];window.EventSource=class { constructor(){window.sources.push(this)} close(){} };}); await page.route('**/api/**',route=>{ const path=new URL(route.request().url()).pathname; if(path==='/api/agents') return route.fulfill({json:{agents:[{id:'owner',name:'Memory test'}]}}); if(path==='/api/agents/owner') return route.fulfill({json:{id:'owner',name:'Memory test',transcript,activity}}); if(path.endsWith('/activity'))return route.fulfill({json:activity}); if(path.endsWith('/computer'))return route.fulfill({json:{ready:false,state:'stopped'}}); return route.fulfill({json:{}}); }); await page.goto(process.env.LAZYBOY_TEST_UI_URL || 'http://127.0.0.1:5173'); await page.locator('[data-message-index="4999"]').waitFor(); const cdp=await page.context().newCDPSession(page); const heap=async()=>{await cdp.send('HeapProfiler.collectGarbage');return (await cdp.send('Runtime.getHeapUsage')).usedSize;}; const baseline=await heap(); let maxRows=0; for(let round=0;round<3;round++)for(let step=0;step<30;step++){ await page.locator('.messages').evaluate((el,ratio)=>{el.scrollTop=(el.scrollHeight-el.clientHeight)*ratio;},step/29); await page.waitForTimeout(40); maxRows=Math.max(maxRows,await page.locator('.message-block').count()); } await page.locator('.messages').evaluate(el=>{el.scrollTop=0}); await page.locator('[data-message-index="0"]').waitFor(); const top=await page.locator('.messages').evaluate(el=>el.scrollTop); transcript.push({role:'assistant',content:'NEW REPLY',at:new Date().toISOString()}); await page.evaluate(()=>window.sources.at(-1).onopen()); await page.waitForTimeout(500); assert.ok(Math.abs(await page.locator('.messages').evaluate(el=>el.scrollTop)-top)<5,'new reply must not pull reader down'); await page.locator('.messages').evaluate(el=>{el.scrollTop=el.scrollHeight}); await page.getByText('NEW REPLY',{exact:true}).waitFor(); const end=await heap(); assert.ok(maxRows<80,`rendered ${maxRows} rows`); assert.ok(end-baseline<32*1024*1024,`heap grew ${(end-baseline)/1024/1024} MiB`); assert.deepEqual(errors,[]); console.log(JSON.stringify({result:'PASS',messages:transcript.length,maxRows,baselineMiB:baseline/1024/1024,finalMiB:end/1024/1024})); } finally {await browser.close();}