diff --git a/tests/review-style-motion.e2e.test.mjs b/tests/review-style-motion.e2e.test.mjs index 85bcb28..317fa65 100644 --- a/tests/review-style-motion.e2e.test.mjs +++ b/tests/review-style-motion.e2e.test.mjs @@ -98,6 +98,11 @@ async function enterMonitor(page) { (count) => count === 4, "The real monitor must render all four charts", ); + await eventually( + () => page.getByRole("button", { name: "刷新", exact: true }).isEnabled(), + Boolean, + "Initial chart responses must finish before observing available data", + ); // 先给无动画图表一个绘制帧,不把 Canvas 的创建本身误认为动画。 await page.clock.runFor(50); await page.mouse.move(0, 0); @@ -107,15 +112,19 @@ async function enterMonitor(page) { async function observeFrames(page, state) { const sample = () => page.locator(".chart-viewport canvas").evaluateAll((canvases) => - canvases.map((canvas) => ({ - width: canvas.width, - height: canvas.height, - painted: canvas - .getContext("2d") - .getImageData(0, 0, canvas.width, canvas.height) - .data.some((channel) => channel !== 0), - image: canvas.toDataURL(), - })), + canvases.map((canvas) => { + const image = canvas.toDataURL(); + const blank = document.createElement("canvas"); + blank.width = canvas.width; + blank.height = canvas.height; + // 不对产品画布反复 getImageData:浏览器可能因此从 GPU 切到 CPU,制造一次性光栅差异。 + return { + width: canvas.width, + height: canvas.height, + painted: image !== blank.toDataURL(), + image, + }; + }), ); const first = await sample(); assert.equal( @@ -279,7 +288,11 @@ test( .first() .click(); await eventually( - () => page.locator(".chart-viewport canvas").count(), + async () => { + // 导航也依赖浏览器任务/rAF;暂停时钟下只轮询 DOM 会阻止真实路由完成卸载。 + await page.clock.runFor(50); + return page.locator(".chart-viewport canvas").count(); + }, (count) => count === 0, "Leaving the instance must unmount the monitor charts", );