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
Add test for wheel event groups #37445
base: master
Are you sure you want to change the base?
Add test for wheel event groups #37445
Conversation
As stated in w3c/uievents#338 the WebKit failure in my local tests is due to a webdriver exception, but follows the expected behavior with manual tests. |
.scroll(40, 2, 0, 20, {origin: firstSpacer}) | ||
.scroll(40, 2, 0, 100, {origin: firstSpacer}) | ||
.pause(1) | ||
.scroll(40, 2, 0, 50, {origin: firstSpacer}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my understanding, firstSpacer
is now scrolled out after the previous .scroll
call. Does this call emulate user input in any browsers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this emulates what happens for several small wheel scrolls that start on firstSpacer
that happen in quick succession. I'll add a test that doesn't add an origin for additional coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test that does what this test did without an element as an origin. It intermittently fails on WebKit, but the behavior is always the same for a manual test.
assert_equals(second_spacer_wheel_event, false, "Wheel event should not be fired to the second spacer"); | ||
assert_equals(inner_wheel_event, false, "Wheel event should not be fired to inner div"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least under current UI Events spec, one of these should be true
if the last .scroll
call emulates a wheel operation on secondSpacer
or innerDiv
because both of them are in same scrollable element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also my understanding of the current spec. This is what I was trying to describe in w3c/uievents#338, but I'm not sure if I described it well. For both manual and emulated tests, the current spec behavior does not seem to happen on WebKit or Blink.
Note that a event sent to secondSpacer
when the scroll moves beyond the bounds of firstSpacer
would cause user scrolls to be interrupted in the case that secondSpacer
has a event listener that uses preventDefault. We get a steady stream of bug reports for this in the Gecko APZ component. So maybe it makes the most sense to fire the wheel event at the parent that contains both elements instead of firing it at the initial target and relying on the event bubbling up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay to reply, but I've still not reached the conclusion yet.
Could you rewrite these tests to collect Event.target
of wheel
events with window.addEventListener
into an array and compare each array item with what you expect? Then, what's expected here becomes easier to understand. I.e.,
let wheelEventTargets = [];
window.addEventListener("wheel", event => {
wheelEventTargets.push(event.target);
}, {passive: true});
...
function runTest() {
wheelEventTargets = [];
...
assert_equal(
document.getElementById("..."),
wheelEventTargets[0],
"..."
);
assert_equal(
document.getElementById("..."),
wheelEventTargets[1],
"..."
);
}
(I guess and assume that the number of wheel
events is not different between browsers in what this test does.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay to reply, but I've still not reached the conclusion yet.
No problem! This is a bit of a complex topic that (I think) doesn't currently follow the spec.
Could you rewrite these tests to collect Event.target of wheel events with window.addEventListener into an array and compare each array item with what you expect?
Thanks for the feedback! Yeah, that makes sense... I think I can rework the test to work like this. Some of the way the tests are architected is an artifact of me trying to figure out how non-firefox browsers handle wheel event group targetting.
2625a56
to
7876bd1
Compare
7876bd1
to
dbf4b63
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review! Hopefully this version makes it easier to reason about... if it doesn't, let me know and I can think about altering things to make it more readable.
I can also create a example for manual testing if it would help.
testInfo.scrollingElement.scrollTo({top: 0, left: 0, behavior: "instant"}); | ||
|
||
wheelEventTargetsEqual(testInfo.targetElement, | ||
"All wheel events in the group have the same element"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you rewrite these tests to collect Event.target of wheel events with window.addEventListener into an array and compare each array item with what you expect?
Went about doing this in a slightly different manner. All the wheel event targets for a given test should be in the same wheel event group, so they all should be the same. As a result, we don't need to check wheelEventTargets[0] == expectedTarget
, we can just iterate through all the wheel event targets we collected in the testcase and ensure they're the expected target.
targetElement: secondInnerSpacer, | ||
title: 'Wheel event groups beyond the origin bound have the same target', | ||
}, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used a array of test info instead of separate test definitions to make it easier to reason about the test cases.
9bca6f9
to
ce7b93f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wanted to add a test for a moved element, but that turns out to be a bit more complicated and the tests get super flaky, so I'm not really sure what the correct behavior is.
"All wheel events in the group have the same target"); | ||
|
||
document.removeEventListener("wheel", onEventRemoveInitialTarget, {passive: true}); | ||
}, "Remove the initial wheel event target."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a simple test that removes the initial target on the first wheel event. Note that I assumed chromes behavior for this test because it was easier to test. I'm unsure if this is the right behavior.
ce7b93f
to
2dd2f45
Compare
Reorganized the tests and rewrote the removal/move initial target tests to greatly improve their reliability. All tests pass very reliably for chrome and firefox (with the bug 1168182 patch) for me on the main box I'm using to work on this. I'll try to run the tests on WebKit and maybe other OSes over the next few days. |
2dd2f45
to
9884b2b
Compare
9884b2b
to
9e28eb2
Compare
Added |
aad9b4d
to
18e23c3
Compare
CC: @smaug---- |
|
||
// The first wheel event should be targetted at the moved element. | ||
assert_equals(wheelEventTargets.shift(), initialTarget, | ||
"Initial wheel event is has the moved element as the target"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"is has"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
3271944
to
2effcbd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review! Added new test that exercises the display: none
case.
|
||
// The first wheel event should be targetted at the moved element. | ||
assert_equals(wheelEventTargets.shift(), initialTarget, | ||
"Initial wheel event is has the moved element as the target"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
wheelEventTargets.forEach((wheelEventTarget) => { | ||
assert_not_equals(wheelEventTarget, initialTarget, | ||
"All following wheel events are not targetting the removed element"); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that browser engines do different things in the event target mutation test cases. E.g. Gecko and WebKit will essentially fallback to the non wheel event groups event target after the original event target is mutated in some way, while Blink will only retarget once. I greatly weakened this assertion, so that all engines should pass. We might want to circle back at some point once there is some sort of consensus.
2effcbd
to
69a7b66
Compare
e.target.style.height = '10px'; | ||
} | ||
} | ||
window.addEventListener("wheel", resizeInitialElement, {passive: true}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, passive
value could change the behavior due to optimization in some browsers. Did you check the false
case?
Could be nicer to check both passive: true
and passive: false
cases in variants.
scrollY: 2, | ||
scrollingElement: document.scrollingElement, | ||
targetElement: firstRootSpacer, | ||
title: 'Wheel events are grouped and are not targetted at following elements.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: using "should" or "shouldn't" make the expectation clearer for everybody.
// Wait some extra time to ensure nothing from the prior test impacts this one. | ||
// At a minimum this should be greater than 500ms to ensure that the wheel events | ||
// in this test are in a new wheel event group | ||
await new Promise(resolve => step_timeout(resolve, 1000)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really required in some browsers? It's odd to work a wheel transaction across browsing contexts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was also confused by this. Spent some time investigating this and the issue was partially solved by using variants. It turns out these tests also need to wait for the compositor to be ready waitForCompositorReady()
.
wheelEventTargets.forEach((wheelEventTarget) => { | ||
assert_equals(wheelEventTarget, testInfo.targetElement, | ||
"All wheel events in the group have the same target"); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unclear which index's result is wrong. Please update the assertion comment to let developers know the failure point.
|
||
await waitForCompositorCommit(); | ||
|
||
wheelEventTargets = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't you define the variable at this line?
function runTest() { | ||
promise_test(async (t) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, if you do:
promise_test(async t => {
await new Promise(resolve => addEventListener("load", resolve, {once:true});
...
Then, you can reduce one indent level of the test body.
wheelEventTargets.forEach((wheelEventTarget) => { | ||
assert_equals(wheelEventTarget, firstRootSpacer, | ||
"All following wheel events in the group have the same target"); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto, please update the assertion message to let developers know which index failed.
wheelEventTargets.forEach((wheelEventTarget) => { | ||
assert_not_equals(wheelEventTarget, initialTarget, | ||
"All following wheel events are not targetting the moved element"); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto please change the assertion message for each.
assert_not_equals(wheelEventTarget, initialTarget, | ||
"All following wheel events are not targetting the removed element"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
assert_equals(wheelEventTarget, initialTarget, | ||
"All wheel events should target the initial element"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto update the assertion message for each.
await waitForAnimationEnd(() => { return document.scrollingElement.scrollTop; }); | ||
await waitForCompositorCommit(); | ||
|
||
wheelEventTargets.forEach((wheelEventTarget) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, scroll top should be checked whether it's still 0
or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably worthwhile
Thanks for re-triggering the tests! Just re-ran these tests locally on chrome beta and m-c (with and without the bug 1821733 patchset). Tests pass reliably for me, but I'd be interested if others see the same results.
I think the tests accurately describe browsers current behavior and are stable in my local testing. @masayuki-nakano is there anything else you think this PR needs? |
8e67e3a
to
b8e8af9
Compare
Added |
@dlrobertson thanks for adding the test! It would be good if you could retrigger the CI checks (at least those for Firefox) once the fix from bug 1821733 made it into the next Nightly build. |
b8e8af9
to
b5d49fa
Compare
@whimboo good point. Re-triggered the CI checks and the check wpt-firefox-nightly-results seems to pass now. |
Great. So I think that @masayuki-nakano could have another look now. |
@smaug---- or @masayuki-nakano PTAL, I'd like to get more testing coverage for this, since this behavior is now the default in firefox (riding the trains with bug 1823700)). If this doesn't look like it is ready to be merged soon-ish, I can pull this into the mozilla specific wpts for now. |
I think I'd still prefer to call this thing something else than "event group". It is more like a wheel transaction or some such. And sorry being late here. Getting the review through bugzilla would be faster in my case, even for public wpts But I'll take a look here. |
No problem, thanks for the feedback! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests are a bit hard to review since there is really no comment what is the overall thing they are trying to test. Could you add some comments?
scrollY: 2, | ||
scrollingElement: document.scrollingElement, | ||
targetElement: firstRootSpacer, | ||
title: 'Wheel events should be grouped and should not targetted following elements.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This talk about grouping is a bit unusual. In pointer events spec events may be captured to a one particular target. Could this all use similar terminology, something like wheel event capturing?
And then elsewhere there is also the concept of transaction used for this thing.
And there is also pointer lock. Is this whole thing some sort of implicit wheel event lock?
|
||
let variants = [ | ||
{ | ||
key: 'target-basic', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does key refer to here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahaa, it is for some helper function.
|
||
<script> | ||
|
||
let variants = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish there was some generic comment on top of the script explaining what is being tested. This is not very easy test to read when one needs to find all the relevant helper methods in other script files etc.
b5d49fa
to
598c501
Compare
@smaug---- as it looks like this PR is waiting for another round of review. Could you please have a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to put all the filed under tentative/ just because there is no spec for this. But other than that looks good
598c501
to
eb993ee
Compare
Renamed all tests to |
dom/events/scrolling/wheel-event-transactions-multiple-action-chains.tentative.html
Show resolved
Hide resolved
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please always add <meta charset="utf-8">
to skip maybe expensive auto-detection of the browsers.
And shouldn't this test have <meta name="timeout" content="long">
for avoiding unexpected timeout during the test?
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
dom/events/scrolling/wheel-event-transactions-target-display-change.tentative.html
Show resolved
Hide resolved
dom/events/scrolling/wheel-event-transactions-target-removal.tentative.html
Show resolved
Hide resolved
dom/events/scrolling/wheel-event-transactions-target-removal.tentative.html
Outdated
Show resolved
Hide resolved
Hi @dlrobertson. Do you plan to update this PR? It might be nice to have those tests for the upcoming work for widget level events in Marionette. Thanks. |
8388187
to
2691a25
Compare
Add tests for groups of wheel events.
2691a25
to
b4d5721
Compare
@whimboo Updated and resolved all comments. Thanks for the ping! |
Re tentative, now there is a spec since w3c/uievents#338 was merged. |
👍 Thanks for the note about this. Forgot that I'd need to update this. Also it looks like chrome no longer passes the tests reliably. I'll have to dig into the tests to figure out what changed. |
@zcorpan Actually to what extent should I rename things? For example, AFAIK it isn't explicitly specified what should happen when the initial target of the wheel transaction is removed, but I have a test for that in this PR. |
Keep |
Hi @dlrobertson. Do you have an update for this PR? |
Add tests for groups of wheel events.