Files
aigc-home/e2e/pagination.mjs
施工员andmultica-agent bc24370233 feat(style): 全站无彩灰阶收尾——清理 legacy 别名与硬编码色漂移 (HEL-685 S6)
- app.css 删除 8 个无引用 legacy 别名,新增 --id-1..5 身份灰阶实色阶
- 画布去紫罗兰二级 palette(tokens.css 删除,改用全站 token)
- 画布/镜头台/智能体/omni/视频组件硬编码色全部归位 token
- agentPalette 彩色身份色改为显影灰阶 --id 阶;修复 3 处相纸白底白字不可读
- WorkflowLibrary 试运行抽屉焦点还原(异步禁用触发键丢焦)修复
- e2e: fpages/import 色值断言对齐现行 token;新增 hel685 走查脚本
  (1440/1024/390 截图 + 控制台错误 + 减动效 + 键盘焦点 + 对比度探针);
  pagination 空库自举;fpages 增加逐页控制台错误检查

Co-authored-by: multica-agent <github@multica.ai>
2026-10-11 17:26:12 +08:00

97 lines
3.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Pagination + perf check (§五): intercept the jobs API and serve 220
* synthetic takes so the >80 path engages without touching the backend. */
import { chromium } from 'playwright';
let failures = 0;
const ok = (name, cond, extra = '') => {
console.log(`${cond ? 'PASS' : 'FAIL'} ${name}${extra ? ' — ' + extra : ''}`);
if (!cond) failures++;
};
const run = async () => {
const browser = await chromium.launch();
const page = await (
await browser.newContext({ viewport: { width: 1440, height: 900 } })
).newPage();
const base = 'http://127.0.0.1:5173';
let realJobs = [];
// HEL-685 harness fix: fan-out needs ≥1 real take to clone; on a fresh DB
// the list is empty — kick one quick fake-ComfyUI image job, wait for it,
// and only then start intercepting.
{
const probe = await fetch('http://127.0.0.1:8247/api/playground/jobs').then((r) => r.json());
if (!Array.isArray(probe) || probe.length === 0) {
await fetch('http://127.0.0.1:8247/api/playground/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
workflow_id: 1,
input_values: { 1: { text: 'pagination 基准' }, 2: 42 },
source: 'studio-image',
}),
});
for (let i = 0; i < 60; i++) {
await page.waitForTimeout(500);
const jobs = await fetch('http://127.0.0.1:8247/api/playground/jobs').then((r) => r.json());
if (Array.isArray(jobs) && jobs.some((j) => j.status === 'done')) break;
}
}
}
await page.route('**/api/playground/jobs**', async (route) => {
const r = await route.fetch();
realJobs = await r.json();
// Fan the real list out to 220 takes with distinct ids/timestamps.
const fan = [];
for (let i = 0; i < 220; i++) {
const src = realJobs[i % realJobs.length] ?? realJobs[0];
fan.push({
...src,
id: 9000 + i,
status: 'done',
output_paths: src.output_paths,
created_at: new Date(Date.now() - i * 47 * 60 * 1000).toISOString(),
});
}
await route.fulfill({ json: fan });
});
const t0 = Date.now();
await page.goto(`${base}/image`);
await page.waitForSelector('#desk-prompt', { timeout: 15000 });
await page.waitForSelector('.take');
await page.waitForTimeout(800);
const rendered = await page.locator('.take').count();
ok('220 条记录时首屏只渲染最近 80 条', rendered === 80, `rendered ${rendered}`);
const btn = page.locator('.earlier');
const label = await btn.textContent();
ok('出现「显示更早」按钮并带余量', /140/.test(label || ''), (label || '').trim());
await btn.click();
await page.waitForTimeout(600);
ok('点击后追加 80 条(共 160)', (await page.locator('.take').count()) === 160);
await page.locator('.earlier').click();
await page.waitForTimeout(600);
ok('再点展开全部 220 条', (await page.locator('.take').count()) === 220);
const loadMs = Date.now() - t0;
ok('整段交互在 3 秒内完成', loadMs < 3000, `${loadMs}ms`);
// scripted-painting budget while 220 cards live (SSE 只更新相关行:
// invalidate jobs → 220 卡重排仍是 keyed 更新)
const metrics = await page.evaluate(async () => {
const t = performance.now();
for (let i = 0; i < 50; i++) await fetch('/api/playground/jobs');
return { poll50: Math.round(performance.now() - t) };
});
ok('50 次 jobs 轮询(220 卡在屏)总耗时 < 8 秒', metrics.poll50 < 8000, `${metrics.poll50}ms`);
await page.screenshot({ path: 'shots/13-pagination-220.png' });
await browser.close();
console.log(failures === 0 ? '\nPAGINATION CHECKS PASSED' : `\n${failures} FAILED`);
process.exit(failures ? 1 : 0);
};
run().catch((e) => {
console.error('SCRIPT ERROR:', e);
process.exit(2);
});