commit b8b0fd53c362907a06139731f372677c9b8a5959
parent fe29a92f0c60e32256e08dc506d52a218ecbeb97
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Thu, 17 Sep 2026 20:36:49 -0400
e2e: two adjacent paused rows, and the pixel has to belong to the menu
One paused row alone does not reproduce the operator report: an opacity group still
paints above the plain rows below it. Two paused rows in a row is the smallest shape
that does, and selectOption never hit-tests, so the assertion asks the page who owns
the pixel. Verified: passes with 29aeeba, fails without it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 41 insertions(+), 14 deletions(-)
diff --git a/editor/e2e/channel-priority.spec.ts b/editor/e2e/channel-priority.spec.ts
@@ -149,33 +149,60 @@ test("the Sync only preset is paused everywhere with sync pinned back", async ({
//
// A row is dimmed when it is excluded from the build or its base tier is
// Paused, and the dim used to sit on the `<tr>` as `opacity-60`. Opacity below
-// 1 creates a stacking context, which confines the popover's `absolute z-30` to
-// the row: every row below it painted over the menu and ate its clicks
-// (operator report 2026-09-17). The dim is per cell now, with the Tier cell
-// left alone. The click is what proves it — Playwright hit-tests the point, so
-// a row painted on top fails the action with "intercepts pointer events".
-test("a paused row's Advanced menu draws above the rows below it", async ({
+// 1 makes the row a stacking context painted as one group, so the panel's
+// `absolute z-30` no longer lifts it out of the row: the NEXT dimmed row is a
+// later group at the same level and paints straight over the menu (operator
+// report 2026-09-17, on a corpus where paused rows sit next to each other).
+// Two paused rows in a row is the smallest shape that reproduces it; one alone
+// does not, because an opacity group still paints above the plain rows below.
+test("a paused row's Advanced menu draws above the paused row below it", async ({
page,
}) => {
await resetData("two-slow-channels");
await page.goto(ALL);
+ // slow-a is the FIRST row and slow-b the one its panel hangs over. The
+ // assertion is meaningless on the last row of the table, which has nothing
+ // after it to be covered by.
+ const slugs = await page
+ .locator('[aria-label^="select slow-"]')
+ .evaluateAll((els) =>
+ els.map((el) => el.getAttribute("aria-label")!.replace("select ", "")),
+ );
+ expect(slugs).toEqual(["slow-a", "slow-b"]);
+
+ await page.getByLabel("select all channels").check();
+ await page.getByLabel("bulk tier").selectOption("paused");
await page
- .getByLabel("tier for slow-a", { exact: true })
- .selectOption("paused");
+ .getByLabel("channel priority bulk")
+ .getByRole("button", { name: "Apply tier" })
+ .click();
await expect
- .poll(async () => (await settings()).channelPriority?.channels["slow-a"])
- .toEqual({ tier: "paused" });
- // Reloaded, so the row renders dimmed from the server's own tier rather than
- // from the control's optimistic state.
+ .poll(async () => (await settings()).channelPriority?.channels)
+ .toEqual({ "slow-a": { tier: "paused" }, "slow-b": { tier: "paused" } });
+ // Reloaded, so both rows render dimmed from the server's own tiers rather
+ // than from the controls' optimistic state.
await page.reload();
await page.getByLabel("advanced priority for slow-a").click();
- // `sync` is the first row of the popover, the part that hangs over slow-b.
+ // `sync` is the first control in the panel, the part that hangs over slow-b.
const override = page.getByLabel("sync override for slow-a");
await expect(override).toBeInViewport();
- await override.selectOption("normal");
+ // THE ASSERTION. `selectOption` never hit-tests, so it passes straight
+ // through a row painted on top of the panel; this asks the page directly who
+ // owns the pixel. With `opacity-60` back on the `<tr>` the answer is a cell
+ // of the paused slow-b row below.
+ const owner = await override.evaluate((el) => {
+ const r = el.getBoundingClientRect();
+ const top = document.elementFromPoint(r.x + r.width / 2, r.y + r.height / 2);
+ return top === el || el.contains(top)
+ ? "the override"
+ : `${top?.tagName ?? "nothing"} ${top?.getAttribute("aria-label") ?? top?.textContent?.trim().slice(0, 40) ?? ""}`;
+ });
+ expect(owner).toBe("the override");
+
+ await override.selectOption("normal");
await expect
.poll(async () => (await settings()).channelPriority?.channels["slow-a"])
.toEqual({ tier: "paused", overrides: { sync: "normal" } });