43 lines
3.5 KiB
JavaScript
43 lines
3.5 KiB
JavaScript
|
|
import { chromium } from '../tools/playwright/node_modules/playwright/index.mjs';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
const browser=await chromium.launch({headless:true});
|
||
|
|
try {
|
||
|
|
for(const theme of ['light','dark']) {
|
||
|
|
const page=await browser.newPage({viewport:{width:1440,height:900},serviceWorkers:'block'});
|
||
|
|
await page.addInitScript(theme=>{localStorage.setItem('lazyboy.theme',theme);localStorage.setItem('lazyboy.locale','zh-Hant')},theme);
|
||
|
|
let task='old-task',state='running',stops=0;
|
||
|
|
const activity=()=>({state,running:state==='running',queued:false,observed_at_ms:Date.now(),active_task_ids:state==='running'?[task]:[]});
|
||
|
|
const agent=()=>({id:'fixture',name:'小麻糬',running:true,activity:activity(),avatar_color:'#eec78c'});
|
||
|
|
const transcript=[{role:'user',content:'幫我整理今天的工作,還有接下來的步驟。',at:'2026-09-16T08:00:00Z'},{role:'assistant',content:'可以,我會先整理重點,再列出待辦事項。\n\n### 今天的進度\n- 電腦畫面恢復完整\n- 新的透明背景圖示\n- 深淺主題都能清楚閱讀\n\n使用 `npm run build` 驗證。\n\n```js\nconst ready = true;\n```',at:'2026-09-16T08:00:01Z'}];
|
||
|
|
await page.route('**/api/**',async route=>{
|
||
|
|
const path=new URL(route.request().url()).pathname;
|
||
|
|
if(path.endsWith('/stop')) {stops++;await new Promise(r=>setTimeout(r,600));return route.fulfill({json:{ok:true}})}
|
||
|
|
if(path.endsWith('/activity'))return route.fulfill({json:activity()});
|
||
|
|
if(path.endsWith('/events'))return route.fulfill({contentType:'text/event-stream',body:'data: {"events":[]}\n\n'});
|
||
|
|
if(path.endsWith('/computer'))return route.fulfill({json:{ready:true,state:'ready',viewer_url:'/fixture-screen'}});
|
||
|
|
if(path==='/api/agents')return route.fulfill({json:{agents:[agent()]}});
|
||
|
|
if(path==='/api/agents/fixture')return route.fulfill({json:{...agent(),transcript}});
|
||
|
|
return route.fulfill({json:{}});
|
||
|
|
});
|
||
|
|
await page.route('**/fixture-screen?*',r=>r.fulfill({contentType:'text/html',body:'<body style="margin:0;background:#1b2029;color:white;font:16px system-ui;display:grid;place-items:center;height:100vh">Desktop preview</body>'}));
|
||
|
|
await page.goto('http://127.0.0.1:5173');
|
||
|
|
await page.locator('.stop-send').waitFor();
|
||
|
|
assert.ok(await page.locator('.avatar.thinking').count()>0);
|
||
|
|
await page.locator('.stop-send').click();
|
||
|
|
assert.equal(await page.locator('.avatar.thinking').count(),0,'stop must immediately remove all thinking rings');
|
||
|
|
await page.waitForTimeout(4500); // stale activity + roster poll must not revive stopped work
|
||
|
|
assert.equal(stops,1);assert.equal(await page.locator('.avatar.thinking').count(),0);
|
||
|
|
await page.screenshot({path:`.run/appearance-${theme}.png`});
|
||
|
|
const colors=await page.locator('.message.assistant .message-body').first().evaluate(el=>({bg:getComputedStyle(el).backgroundColor,fg:getComputedStyle(el).color}));
|
||
|
|
if(theme==='light'){assert.equal(colors.bg,'rgb(240, 241, 243)');assert.equal(colors.fg,'rgb(20, 20, 20)')}
|
||
|
|
task='new-task';
|
||
|
|
await page.locator('.stop-send').waitFor({timeout:6000});
|
||
|
|
assert.ok(await page.locator('.avatar.thinking').count()>0,'new work must animate normally');
|
||
|
|
state='idle';
|
||
|
|
await page.locator('.stop-send').waitFor({state:'hidden',timeout:6000});
|
||
|
|
assert.equal(await page.locator('.bot-row.selected .avatar.thinking').count(),0,'idle activity wins over stale roster');
|
||
|
|
console.log(`PASS ${theme}: immediate stop, stale activity suppression, new task and idle avatar`);
|
||
|
|
await page.close();
|
||
|
|
}
|
||
|
|
}finally{await browser.close()}
|