diff --git a/e2e/chart-overlay-controls.spec.ts b/e2e/chart-overlay-controls.spec.ts index f475bbd3c..dec64dd30 100644 --- a/e2e/chart-overlay-controls.spec.ts +++ b/e2e/chart-overlay-controls.spec.ts @@ -120,11 +120,18 @@ test.describe("chart overlay controls", () => { await expect(targetRangeToggle).toBeVisible({ timeout: 5_000 }); // Toggle target-range on. Radix Switch is a button[role=switch]. - // Force the click — `scrollIntoViewIfNeeded()` on the portalled - // dropdown content is a no-op (the Radix portal sits at the body - // root, outside the page scroll container) so we bypass Playwright's - // viewport check directly. - await targetRangeToggle.click({ force: true }); + // The Radix dropdown content portals to the body root and can land + // below the viewport on a 393×851 Pixel 5 (or near the bottom edge + // on the 1280×720 desktop profile). Playwright's `click({force:true})` + // still computes the element's bbox against the viewport and refuses + // to dispatch the click when it falls outside, so neither + // `scrollIntoViewIfNeeded()` on the portalled content nor `force` + // can rescue the action. `dispatchEvent('click')` synthesises a DOM + // click on the element without any viewport / actionability check, + // which is exactly the semantic we want for an off-screen portalled + // Radix Switch — and it still fires the onCheckedChange handler that + // the surface listens for. + await targetRangeToggle.dispatchEvent("click"); // The PUT fires once for the toggle change. await expect.poll(() => putRequestCount).toBeGreaterThan(0); diff --git a/e2e/charts-mobile.spec.ts b/e2e/charts-mobile.spec.ts index 111cd8502..5d1797828 100644 --- a/e2e/charts-mobile.spec.ts +++ b/e2e/charts-mobile.spec.ts @@ -211,11 +211,18 @@ test.describe("charts — mobile-viewport regression", () => { await firstChartCard.waitFor({ state: "visible", timeout: 10_000 }); await firstChartCard.scrollIntoViewIfNeeded(); // After scroll, give the chart a beat to lay out under the new - // measured size before counting ticks. + // measured size before counting ticks. The chart card on Pixel-5 + // is taller than the 851-px viewport, so `scrollIntoViewIfNeeded` + // brings the card's TOP into view but the bottom-anchored x-axis + // labels can remain below the fold — and `waitFor({state:"visible"})` + // would then time out even though Recharts has already painted the + // ticks into the DOM. The subsequent `evaluate` only needs + // them attached, not visually on-screen, so `state: "attached"` is + // both sufficient and stable against viewport overflow. await page .locator(".recharts-xAxis .recharts-cartesian-axis-tick text") .first() - .waitFor({ state: "visible", timeout: 10_000 }); + .waitFor({ state: "attached", timeout: 10_000 }); // Recharts lays its visible tick labels under // `.recharts-xAxis .recharts-cartesian-axis-tick`. Count the ones