Files
console-dev/tests/review-content-geometry.e2e.test.mjs
T
cieanyau 1c0c0f16bc
前端验证 / verify (push) Failing after 3m34s
修复布局:同步生成表格标签并移除跨帧补写
通过表格原生渲染统一生成手机布局标签,删除全页监听与后补扫描。动态等级列使用单一标题并保留颜色。

补齐首次插入、深链刷新、动态表头与首页延迟响应几何回归。全量214项通过,最终专项16项通过;不声明全站所有场景零位移。
2026-11-07 06:21:31 +08:00

87 lines
3.2 KiB
JavaScript

/** 回归缺口:异步列表替换骨架时,已显示的相邻卡片不应因同样五行内容而上下跳动。 */
import assert from "node:assert/strict";
import { test } from "node:test";
import { backendOrigin, login, scenario } from "./helpers/console-browser.mjs";
for (const width of [1440, 390]) {
test(
`home list reserves its rendered row geometry at ${width}px`,
{ timeout: 30000 },
(t) =>
scenario(t, {}, async (page) => {
await page.setViewportSize({ width, height: 900 });
await page.emulateMedia({ reducedMotion: "reduce" });
let release;
const held = new Promise((resolve) => {
release = resolve;
});
await page.route(`${backendOrigin}/console/v1/**`, async (route) => {
const path = new URL(route.request().url()).pathname;
if (![/\/ticket$/, /\/announcement$/].some((end) => end.test(path)))
return route.fallback();
await held;
return route.fulfill({
json: {
status: 200,
msg: "",
data: {
count: 5,
list: Array.from({ length: 5 }, (_, index) => ({
id: index + 1,
title: `本地布局验收 ${index + 1}`,
create_time: 1730000000,
post_time: 1730000000,
status: "待回复",
color: "#0284c7",
})),
},
},
});
});
const geometry = () =>
page.locator(".home-tickets, .home-notices").evaluateAll((cards) =>
cards.map((card) => {
const box = card.getBoundingClientRect();
return {
card: card.classList.contains("home-tickets")
? "tickets"
: "notices",
top: box.top + scrollY,
height: box.height,
};
}),
);
let before;
try {
await login(page, "/");
await page
.locator(".home-tickets .home-row-skeleton")
.first()
.waitFor();
await page.evaluate(() => document.fonts.ready);
// 只比较本次控制的两个响应,避免混入其他独立面板的正常数据替换。
await page.waitForFunction(
() =>
!document.querySelector(
".home-servers .home-row-skeleton, .home-expiring .home-row-skeleton, .home-referral .p-skeleton",
),
);
before = await geometry();
} finally {
release();
}
await page.locator(".home-notices .notice-row").last().waitFor();
await page.locator(".home-tickets .home-row").last().waitFor();
const after = await geometry();
for (let index = 0; index < before.length; index++) {
for (const dimension of ["height", "top"])
assert.ok(
Math.abs(before[index][dimension] - after[index][dimension]) <= 1,
`${before[index].card} ${dimension} changed: ${before[index][dimension]} -> ${after[index][dimension]}`,
);
}
return { width, sameRowGeometryAfterData: true };
}),
);
}