Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(input): a mode that performs hit target check during input #9546

Merged
merged 1 commit into from
Nov 6, 2021

Conversation

dgozman
Copy link
Contributor

@dgozman dgozman commented Oct 15, 2021

Reincarnation of #6352.

This change replaces previous checkHitTarget heuristic that took place before the action with a new setupHitTargetInterceptor that works during the action:

  • Before the action we set up capturing listeners on the window.
  • During the action we ensure that event target is the element we expect to interact with.
  • After the action we clear the listeners.

This should catch the "layout shift" issues where things move between action point calculation and the actual action.

Possible issues:

  • Risk: { trial: true } might dispatch move events like mousemove or pointerout,
    because we do actually move the mouse but prevent all other events.
  • Timing: The timing of "hit target check" has moved, so this may affect different web pages
    in different ways, for example expose more races. In this case, we should retry the click as before.
  • No risk: There is still a possibility of mis-targeting with iframes shifting around,
    because we only intercept in the target frame. This behavior does not change.

There is an opt-out environment variable PLAYWRIGHT_NO_LAYOUT_SHIFT_CHECK that reverts to previous behavior.

Fixes #6238.

tests/tap.spec.ts Outdated Show resolved Hide resolved
tests/page/page-click.spec.ts Outdated Show resolved Hide resolved
@dgozman dgozman force-pushed the input-intercept branch 2 times, most recently from 57f6082 to f725f9b Compare November 4, 2021 02:46
@dgozman dgozman changed the title feat(input): perform hit target check during input feat(input): a mode that performs hit target check during input Nov 4, 2021
@dgozman dgozman added CQ1 and removed CQ1 labels Nov 4, 2021
@dgozman dgozman force-pushed the input-intercept branch 2 times, most recently from 6241292 to d44daa4 Compare November 4, 2021 20:08
@dgozman dgozman force-pushed the input-intercept branch 2 times, most recently from 14dc823 to 3ea19f0 Compare November 5, 2021 20:45
@dgozman dgozman added CQ1 and removed CQ1 labels Nov 5, 2021
This replaces previous `checkHitTarget` heuristic that took place before the action
with a new `setupHitTargetInterceptor` that works during the action:
- Before the action we set up capturing listeners on the window.
- During the action we ensure that event target is the element we expect to interact with.
- After the action we clear the listeners.

This should catch the "layout shift" issues where things move
between action point calculation and the actual action.

Possible issues:
- **Risk:** `{ trial: true }` might dispatch move events like `mousemove` or `pointerout`,
because we do actually move the mouse but prevent all other events.
- **Timing**: The timing of "hit target check" has moved, so this may affect different web pages
in different ways, for example expose more races. In this case, we should retry the click as before.
- **No risk**: There is still a possibility of mis-targeting with iframes shifting around,
because we only intercept in the target frame. This behavior does not change.
Copy link
Member

@pavelfeldman pavelfeldman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship it!

@dgozman dgozman added CQ1 and removed CQ1 labels Nov 5, 2021
@dgozman dgozman merged commit 61ff527 into microsoft:master Nov 6, 2021
dgozman added a commit to dgozman/playwright that referenced this pull request Dec 20, 2021
This changes previous layout shift attempt (see microsoft#9546)
to account for more valid usecases:
- On the first event that is intercepted we enforce the hit target. This
  is similar to the current mode that checks hit target before the action,
  but is better timed.
- On subsequent events, we only check that target element still covers the
  action point. If it does not, we run previous logic to determinte the
  actual hit target.

This check is enabled by default, with `process.env.PLAYWRIGHT_NO_LAYOUT_SHIFT_CHECK`
to opt out.
dgozman added a commit to dgozman/playwright that referenced this pull request Jan 3, 2022
This changes previous layout shift attempt (see microsoft#9546)
to account for more valid usecases:
- On the first event that is intercepted we enforce the hit target. This
  is similar to the current mode that checks hit target before the action,
  but is better timed.
- On subsequent events we assume that everything is fine. This covers more
  scenarios like react rerender, glass pane on mousedown, detach on mouseup.

This check is enabled by default, with `process.env.PLAYWRIGHT_NO_LAYOUT_SHIFT_CHECK`
to opt out.
dgozman added a commit that referenced this pull request Jan 4, 2022
This changes previous layout shift attempt (see #9546)
to account for more valid usecases:
- On the first event that is intercepted we enforce the hit target. This
  is similar to the current mode that checks hit target before the action,
  but is better timed.
- On subsequent events we assume that everything is fine. This covers more
  scenarios like react rerender, glass pane on mousedown, detach on mouseup.

This check is enabled by default, with `process.env.PLAYWRIGHT_NO_LAYOUT_SHIFT_CHECK`
to opt out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Wrong element is clicked due to lazy loading/UI shift
3 participants