test(e2e): measure the Coach button's clearance once the page has settled

Scrolling to the end can start a section's load, and its skeleton sat under
the button for a moment on the Insights page in landscape. The check now
scrolls to the end and measures again until the last line is in place;
content that stays under the button still fails it.
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 08:45:25 +01:00
1 parent eadf4c0f2b
commit 9ff35efb47
1 file changed
+40 -28
+40 -28
View File
@@ -577,35 +577,47 @@ for (const vp of [
if (inset) await setBottomInset(page, inset);
const fab = page.locator('[data-slot="coach-fab"]');
await expect(fab).toBeVisible();
await scrollMainToEnd(page);
const covered = await page.evaluate(() => {
const f = document
.querySelector('[data-slot="coach-fab"]')!
.getBoundingClientRect();
const main = document.getElementById("main-content")!;
const under: string[] = [];
for (const el of main.querySelectorAll<HTMLElement>("*")) {
const cs = getComputedStyle(el);
if (cs.position === "fixed" || cs.visibility === "hidden") continue;
const paints =
(el.childElementCount === 0 && !!el.textContent?.trim()) ||
cs.borderBottomWidth !== "0px" ||
cs.backgroundColor !== "rgba(0, 0, 0, 0)";
if (!paints) continue;
const b = el.getBoundingClientRect();
if (!b.width || !b.height) continue;
if (
b.right > f.left &&
b.left < f.right &&
b.bottom > f.top &&
b.top < f.bottom
) {
under.push(el.getAttribute("data-slot") ?? el.tagName);
// A section near the end can still load once the scroll reaches it
// and show its skeleton for a moment; what has to hold is the page
// as it ends up, so scroll to the end and measure again until the
// last line is in place. Content that stays under the button fails.
const coveredAtEnd = async () => {
await scrollMainToEnd(page);
return page.evaluate(() => {
const f = document
.querySelector('[data-slot="coach-fab"]')!
.getBoundingClientRect();
const main = document.getElementById("main-content")!;
const under: string[] = [];
for (const el of main.querySelectorAll<HTMLElement>("*")) {
const cs = getComputedStyle(el);
if (cs.position === "fixed" || cs.visibility === "hidden")
continue;
const paints =
(el.childElementCount === 0 && !!el.textContent?.trim()) ||
cs.borderBottomWidth !== "0px" ||
cs.backgroundColor !== "rgba(0, 0, 0, 0)";
if (!paints) continue;
const b = el.getBoundingClientRect();
if (!b.width || !b.height) continue;
if (
b.right > f.left &&
b.left < f.right &&
b.bottom > f.top &&
b.top < f.bottom
) {
under.push(el.getAttribute("data-slot") ?? el.tagName);
}
}
}
return under;
});
expect(covered, `${path}: content under the Coach button`).toEqual([]);
return under;
});
};
await expect
.poll(coveredAtEnd, {
message: `${path}: content under the Coach button`,
timeout: 15_000,
})
.toEqual([]);
}
});
}