gui tests: a press is made only on a target wholly in sight, so Playwright's click doesn't scroll it the last fraction of a pixel itself (request-archive-usage.test.cjs: "a click moved the page: 860 to 861" in Chromium once the Usage page's archive switch shows, which #1017 makes it do) — reader.inView took a target cut off by up to a pixel at the view's foot as in sight; Fetch from archive spanned 539.80–562.59 in a 562px view (the switch makes .led-head 4px taller, so the 20px wheel steps land the rows elsewhere), and Playwright's click scrollIntoViewIfNeeded'd it 1px before dispatching, before the app's capture-phase click listener took the positions hold() keeps, so the app saw nothing to put back. A raw page.mouse.click at the same point moves nothing; no page code scrolls or focuses there, and overflow-anchor: none changes nothing. inView now wants the target wholly in the view (or, taller than it, its top in sight), and the press test's web ±1 allowance ("settles a row's first opening up to a pixel off") is gone: a click moves the page by nothing. With #1017's diff applied, request-archive-usage.test.cjs failed in Chromium (both app modes) and passed in WebKit; with this it passes 5/5 in both, and 3/3 with the allowance removed. The 32 suites using reader.cjs, request-archive*, usage-*, click-scroll and ledger-* pass in Chromium and WebKit (275/275). No app change.

This commit is contained in:
yetone committed 2026-10-06 21:08:57 +08:00
1 parent aad799eae6
commit 70e7e36675
2 files changed
+9 -5

No files matched your search

+8 -2
View File
@@ -1,5 +1,10 @@
// The app deliberately undoes unsolicited scrollIntoView (including Playwright's
// automatic scroll). Bring a control into sight with real wheel input first.
// Wholly in sight: one cut off by a fraction of a pixel at the view's foot
// was scrolled the rest of the way by Playwright's click itself, before the
// app saw the click, and the page moved 1px under it (860 to 861 on the
// Usage page's Fetch from archive, once the archive switch in its header
// had moved the rows 4px down).
async function inView(page, locator) {
await locator.waitFor({state:"visible"});
if (await locator.evaluate(e => !e.closest("#view-usage"))) return;
@@ -9,11 +14,12 @@ async function inView(page, locator) {
for (let i = 0; i < 80; i++) {
const b = await locator.boundingBox();
if (!b) { await page.waitForTimeout(40); continue; }
if (b.y >= v.y - 1 && b.y + b.height <= v.y + v.height + 1) {
// one taller than the view: its top in sight
if (b.y >= v.y && (b.y + b.height <= v.y + v.height || (b.height > v.height && b.y < v.y + v.height))) {
await page.waitForTimeout(300);
return;
}
const delta = b.y < v.y - 1 ? -20 : 20;
const delta = b.y < v.y ? -20 : 20;
await page.mouse.wheel(0, delta);
await page.waitForTimeout(40);
}
@@ -117,9 +117,7 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
const at = await top();
await loc.click();
await p.waitForTimeout(200);
// magpie web's page settles a row's first opening up to a pixel
// off, on main before #447 as well
assert(Math.abs((await top()) - at) <= (web ? 1 : 0), `a click moved the page: ${at} to ${await top()}`);
assert.equal(await top(), at, "a click moved the page");
};
const wait = async (n) => { for (let i = 0; i < 60 && seen.length < n; i++) await p.waitForTimeout(50); };