Skip to content

a wheel asked twice scrolls past the member it was aiming at #1310

Description

@ExtraToast

member manager virtualization >> scrolling reaches a member far down the list failed on mobile-chrome in run 35334254409, on a branch that changes no frontend source. Same spec as #1186, different symptom: there the wheel scrolled nothing, here it scrolls roughly twice as far as asked.

What the trace says

The retain-on-failure trace records two wheel dispatches, both asking for the whole distance:

call@712  mouseWheel  {deltaX: 0, deltaY: 10956}
call@722  mouseWheel  {deltaX: 0, deltaY: 10956}

The poll added by #1203 reads scrollTop, and dispatches a wheel for whatever distance is left:

const target = 249 * ROW_HEIGHT        // 10956
await expect
  .poll(async () => {
    const reached = await scroller.evaluate(el => el.scrollTop)
    if (reached < target) {
      await page.mouse.wheel(0, target - reached)
    }
    return scroller.evaluate(el => el.scrollTop)
  })
  .toBeGreaterThanOrEqual(target)

A second delta of exactly 10956 means reached was still 0 on the second iteration — the first wheel had not moved the scroller yet, which is the settling behaviour #1186 documented. So 21912px is dispatched in total against a maximum scrollTop of 13266 - clientHeight, roughly 12800. The scroller clamps at the bottom of the list.

The poll then passes, because the assertion is toBeGreaterThanOrEqual(target) and the bottom of the list is well past row 250. The next line is what fails:

Error: expect(locator).toBeVisible() failed
Locator: getByText('Member 250', { exact: true })
Expected: visible
Error: element(s) not found

Row 250 is off-window above; the window holds rows near 300.

Why it is surfacing now

#1203 turned "the wheel does nothing" into "the wheel fires twice", and the retry in playwright.config.ts absorbed the result. #1309 sets retries: 0, so the first failure is now the reported one. The bug predates that change — it is the #1203 fix racing the same settling window #1186 described, not anything about sharding.

Where a fix probably goes

The poll asks for an absolute destination using a relative gesture, and re-asks before the previous gesture has landed. Two shapes worth considering:

  • Ask once and wait for the scroller to settle, rather than re-asking on a delta that may already be in flight — for instance poll only on scrollTop changing, and dispatch again only after it has gone quiet for a frame.
  • Assert the destination rather than a floor: toBeGreaterThanOrEqual(target) accepts the bottom of the list as success. The spec wants row 250 in the window, so a bounded range, or scrolling the row into view directly, says what it means.

The second is the one that would have caught this rather than passing through it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ci-cdbugSomething isn't workingcipriority/2-nextUnblocks a chain of other work once the now list is clear.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions