mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1849229 - [remote] Convert delta values for wheel scroll actions from CSS to device pixels. r=webdriver-reviewers,jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D186534
This commit is contained in:
parent
68a7302612
commit
08de5855e6
@ -157,6 +157,20 @@ event.synthesizeTouchAtPoint = function (left, top, opts, win) {
|
||||
* Window object.
|
||||
*/
|
||||
event.synthesizeWheelAtPoint = function (left, top, opts, win) {
|
||||
const dpr = win.devicePixelRatio;
|
||||
|
||||
// All delta properties expect the value in device pixels while the
|
||||
// WebDriver specification uses CSS pixels.
|
||||
if (typeof opts.deltaX !== "undefined") {
|
||||
opts.deltaX *= dpr;
|
||||
}
|
||||
if (typeof opts.deltaY !== "undefined") {
|
||||
opts.deltaY *= dpr;
|
||||
}
|
||||
if (typeof opts.deltaZ !== "undefined") {
|
||||
opts.deltaZ *= dpr;
|
||||
}
|
||||
|
||||
return _getEventUtils(win).synthesizeWheelAtPoint(left, top, opts, win);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
from copy import deepcopy
|
||||
|
||||
import pytest
|
||||
from tests.classic.perform_actions.support.refine import get_events
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_pixel_ratio", ["1.0", "2.0", "0.5"])
|
||||
def test_scroll_delta_device_pixel(configuration, url, geckodriver, device_pixel_ratio):
|
||||
config = deepcopy(configuration)
|
||||
|
||||
prefs = config["capabilities"]["moz:firefoxOptions"].get("prefs", {})
|
||||
prefs.update({"layout.css.devPixelsPerPx": device_pixel_ratio})
|
||||
config["capabilities"]["moz:firefoxOptions"]["prefs"] = prefs
|
||||
|
||||
try:
|
||||
driver = geckodriver(config=config)
|
||||
driver.new_session()
|
||||
|
||||
driver.session.url = url(
|
||||
"/webdriver/tests/support/html/test_actions_scroll.html"
|
||||
)
|
||||
|
||||
target = driver.session.find.css("#scrollable", all=False)
|
||||
|
||||
chain = driver.session.actions.sequence("wheel", "wheel_id")
|
||||
chain.scroll(0, 0, 5, 10, origin=target).perform()
|
||||
|
||||
events = get_events(driver.session)
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] == 5
|
||||
assert events[0]["deltaY"] == 10
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "scrollable-content"
|
||||
|
||||
finally:
|
||||
driver.stop()
|
@ -10,14 +10,14 @@ pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
@pytest.mark.parametrize("delta_x, delta_y", [(0, 10), (5, 0), (5, 10)])
|
||||
async def test_wheel_scroll(
|
||||
async def test_scroll_not_scrollable(
|
||||
bidi_session, setup_wheel_test, top_context, get_element, delta_x, delta_y
|
||||
):
|
||||
actions = Actions()
|
||||
|
||||
outer = await get_element("#outer")
|
||||
target = await get_element("#not-scrollable")
|
||||
actions.add_wheel().scroll(
|
||||
x=0, y=0, delta_x=delta_x, delta_y=delta_y, origin=get_element_origin(outer)
|
||||
x=0, y=0, delta_x=delta_x, delta_y=delta_y, origin=get_element_origin(target)
|
||||
)
|
||||
|
||||
await bidi_session.input.perform_actions(
|
||||
@ -27,37 +27,14 @@ async def test_wheel_scroll(
|
||||
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= delta_x
|
||||
assert events[0]["deltaY"] >= delta_y
|
||||
assert events[0]["deltaX"] == delta_x
|
||||
assert events[0]["deltaY"] == delta_y
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "outer"
|
||||
assert events[0]["target"] == "not-scrollable-content"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("delta_x, delta_y", [(0, 10), (5, 0), (5, 10)])
|
||||
async def test_wheel_scroll_iframe(
|
||||
bidi_session, setup_wheel_test, top_context, get_element, delta_x, delta_y
|
||||
):
|
||||
actions = Actions()
|
||||
|
||||
subframe = await get_element("#subframe")
|
||||
actions.add_wheel().scroll(
|
||||
x=0, y=0, delta_x=delta_x, delta_y=delta_y, origin=get_element_origin(subframe)
|
||||
)
|
||||
|
||||
await bidi_session.input.perform_actions(
|
||||
actions=actions, context=top_context["context"]
|
||||
)
|
||||
events = await get_events(bidi_session, top_context["context"])
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= delta_x
|
||||
assert events[0]["deltaY"] >= delta_y
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "iframeContent"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("delta_x, delta_y", [(0, 10), (5, 0), (5, 10)])
|
||||
async def test_wheel_scroll_overflow(
|
||||
async def test_scroll_scrollable_overflow(
|
||||
bidi_session, setup_wheel_test, top_context, get_element, delta_x, delta_y
|
||||
):
|
||||
actions = Actions()
|
||||
@ -78,15 +55,38 @@ async def test_wheel_scroll_overflow(
|
||||
events = await get_events(bidi_session, top_context["context"])
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= delta_x
|
||||
assert events[0]["deltaY"] >= delta_y
|
||||
assert events[0]["deltaX"] == delta_x
|
||||
assert events[0]["deltaY"] == delta_y
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "scrollContent"
|
||||
assert events[0]["target"] == "scrollable-content"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("delta_x, delta_y", [(0, 10), (5, 0), (5, 10)])
|
||||
async def test_scroll_iframe(
|
||||
bidi_session, setup_wheel_test, top_context, get_element, delta_x, delta_y
|
||||
):
|
||||
actions = Actions()
|
||||
|
||||
target = await get_element("#iframe")
|
||||
actions.add_wheel().scroll(
|
||||
x=0, y=0, delta_x=delta_x, delta_y=delta_y, origin=get_element_origin(target)
|
||||
)
|
||||
|
||||
await bidi_session.input.perform_actions(
|
||||
actions=actions, context=top_context["context"]
|
||||
)
|
||||
events = await get_events(bidi_session, top_context["context"])
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] == delta_x
|
||||
assert events[0]["deltaY"] == delta_y
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "iframeContent"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ["open", "closed"])
|
||||
@pytest.mark.parametrize("nested", [False, True], ids=["outer", "inner"])
|
||||
async def test_wheel_scroll_shadow_tree(
|
||||
async def test_scroll_shadow_tree(
|
||||
bidi_session, top_context, get_test_page, mode, nested
|
||||
):
|
||||
await bidi_session.browsing_context.navigate(
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from webdriver.error import InvalidArgumentException
|
||||
|
||||
from tests.support.asserts import assert_error
|
||||
from . import perform_actions
|
||||
|
||||
@ -821,3 +823,16 @@ def test_wheel_action_scroll_origin_element_invalid_value(session):
|
||||
]
|
||||
response = perform_actions(session, actions)
|
||||
assert_error(response, "no such element")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("missing", ["x", "y", "deltaX", "deltaY"])
|
||||
def test_wheel_action_scroll_missing_property(
|
||||
session, test_actions_scroll_page, wheel_chain, missing
|
||||
):
|
||||
target = session.find.css("#scrollable", all=False)
|
||||
|
||||
actions = wheel_chain.scroll(0, 0, 5, 10, origin=target)
|
||||
del actions._actions[-1][missing]
|
||||
|
||||
with pytest.raises(InvalidArgumentException):
|
||||
actions.perform()
|
||||
|
@ -1,10 +1,9 @@
|
||||
import pytest
|
||||
|
||||
from webdriver.error import InvalidArgumentException, NoSuchWindowException
|
||||
from webdriver.error import NoSuchWindowException
|
||||
|
||||
|
||||
from tests.classic.perform_actions.support.refine import get_events
|
||||
from tests.support.asserts import assert_move_to_coordinates
|
||||
from tests.support.helpers import filter_dict
|
||||
|
||||
|
||||
def test_null_response_value(session, wheel_chain):
|
||||
@ -22,51 +21,51 @@ def test_no_browsing_context(session, closed_window, wheel_chain):
|
||||
wheel_chain.scroll(0, 0, 0, 10).perform()
|
||||
|
||||
|
||||
def test_wheel_scroll(session, test_actions_scroll_page, wheel_chain):
|
||||
session.execute_script("document.scrollingElement.scrollTop = 0")
|
||||
def test_scroll_not_scrollable(session, test_actions_scroll_page, wheel_chain):
|
||||
target = session.find.css("#not-scrollable", all=False)
|
||||
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=target).perform()
|
||||
|
||||
outer = session.find.css("#outer", all=False)
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=outer).perform()
|
||||
events = get_events(session)
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= 5
|
||||
assert events[0]["deltaY"] >= 10
|
||||
assert events[0]["deltaX"] == 5
|
||||
assert events[0]["deltaY"] == 10
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "outer"
|
||||
assert events[0]["target"] == "not-scrollable-content"
|
||||
|
||||
|
||||
def test_wheel_scroll_overflow(session, test_actions_scroll_page, wheel_chain):
|
||||
session.execute_script("document.scrollingElement.scrollTop = 0")
|
||||
def test_scroll_scrollable_overflow(session, test_actions_scroll_page, wheel_chain):
|
||||
target = session.find.css("#scrollable", all=False)
|
||||
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=target).perform()
|
||||
|
||||
scrollable = session.find.css("#scrollable", all=False)
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=scrollable).perform()
|
||||
events = get_events(session)
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= 5
|
||||
assert events[0]["deltaY"] >= 10
|
||||
assert events[0]["deltaX"] == 5
|
||||
assert events[0]["deltaY"] == 10
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "scrollContent"
|
||||
assert events[0]["target"] == "scrollable-content"
|
||||
|
||||
|
||||
def test_wheel_scroll_iframe(session, test_actions_scroll_page, wheel_chain):
|
||||
session.execute_script("document.scrollingElement.scrollTop = 0")
|
||||
def test_scroll_iframe(session, test_actions_scroll_page, wheel_chain):
|
||||
target = session.find.css("#iframe", all=False)
|
||||
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=target).perform()
|
||||
|
||||
subframe = session.find.css("#subframe", all=False)
|
||||
wheel_chain.scroll(0, 0, 5, 10, origin=subframe).perform()
|
||||
events = get_events(session)
|
||||
assert len(events) == 1
|
||||
assert events[0]["type"] == "wheel"
|
||||
assert events[0]["deltaX"] >= 5
|
||||
assert events[0]["deltaY"] >= 10
|
||||
assert events[0]["deltaX"] == 5
|
||||
assert events[0]["deltaY"] == 10
|
||||
assert events[0]["deltaZ"] == 0
|
||||
assert events[0]["target"] == "iframeContent"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ["open", "closed"])
|
||||
@pytest.mark.parametrize("nested", [False, True], ids=["outer", "inner"])
|
||||
def test_wheel_scroll_shadow_tree(session, get_test_page, wheel_chain, mode, nested):
|
||||
def test_scroll_shadow_tree(session, get_test_page, wheel_chain, mode, nested):
|
||||
session.url = get_test_page(
|
||||
shadow_doc="""
|
||||
<div id="scrollableShadowTree"
|
||||
@ -109,17 +108,6 @@ def test_wheel_scroll_shadow_tree(session, get_test_page, wheel_chain, mode, nes
|
||||
|
||||
events = session.execute_script("return window.wheelEvents;") or []
|
||||
assert len(events) == 1
|
||||
assert events[0]["deltaX"] >= 5
|
||||
assert events[0]["deltaY"] >= 10
|
||||
assert events[0]["deltaX"] == 5
|
||||
assert events[0]["deltaY"] == 10
|
||||
assert events[0]["target"] == "scrollableShadowTreeContent"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("missing", ["x", "y", "deltaX", "deltaY"])
|
||||
def test_wheel_missing_prop(session, test_actions_scroll_page, wheel_chain, missing):
|
||||
session.execute_script("document.scrollingElement.scrollTop = 0")
|
||||
|
||||
outer = session.find.css("#outer", all=False)
|
||||
actions = wheel_chain.scroll(0, 0, 5, 10, origin=outer)
|
||||
del actions._actions[-1][missing]
|
||||
with pytest.raises(InvalidArgumentException):
|
||||
actions.perform()
|
||||
|
@ -1,103 +1,139 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<html>
|
||||
<head>
|
||||
<head>
|
||||
<title>Test Actions</title>
|
||||
<style>
|
||||
div { padding: 0; margin: 0; }
|
||||
.area { width: 100px; height: 50px; background-color: #ccc; }
|
||||
#scrollable { width: 100px; height: 100px; overflow: scroll; }
|
||||
#scrollContent { width: 600px; height: 1000px; background-color: blue; }
|
||||
#subframe { width: 100px; height: 100px; }
|
||||
div {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#not-scrollable {
|
||||
margin-bottom: 100px;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#not-scrollable-content {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
#scrollable {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#scrollable-content {
|
||||
width: 600px;
|
||||
height: 1000px;
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
#iframe {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#event-reporter {
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
var els = {};
|
||||
var allEvents = { events: [] };
|
||||
function displayMessage(message) {
|
||||
document.getElementById("events").innerHTML = "<p>" + message + "</p>";
|
||||
}
|
||||
var eventReporter;
|
||||
var allEvents = { events: [] };
|
||||
|
||||
function appendMessage(message) {
|
||||
document.getElementById("events").innerHTML += "<p>" + message + "</p>";
|
||||
}
|
||||
function addMessage(message) {
|
||||
eventReporter.textContent = `${message}\n${eventReporter.textContent}`;
|
||||
}
|
||||
|
||||
function recordWheelEvent(event) {
|
||||
allEvents.events.push({
|
||||
"type": event.type,
|
||||
"button": event.button,
|
||||
"buttons": event.buttons,
|
||||
"deltaX": event.deltaX,
|
||||
"deltaY": event.deltaY,
|
||||
"deltaZ": event.deltaZ,
|
||||
"deltaMode": event.deltaMode,
|
||||
"target": event.target.id
|
||||
});
|
||||
appendMessage(event.type + " " +
|
||||
"button: " + event.button + ", " +
|
||||
"pageX: " + event.pageX + ", " +
|
||||
"pageY: " + event.pageY + ", " +
|
||||
"button: " + event.button + ", " +
|
||||
"buttons: " + event.buttons + ", " +
|
||||
"deltaX: " + event.deltaX + ", " +
|
||||
"deltaY: " + event.deltaY + ", " +
|
||||
"deltaZ: " + event.deltaZ + ", " +
|
||||
"deltaMode: " + event.deltaMode + ", " +
|
||||
"target id: " + event.target.id);
|
||||
}
|
||||
|
||||
function resetEvents() {
|
||||
allEvents.events.length = 0;
|
||||
displayMessage("");
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var outer = document.getElementById("outer");
|
||||
outer.addEventListener("wheel", recordWheelEvent);
|
||||
|
||||
var scrollable = document.getElementById("scrollable");
|
||||
scrollable.addEventListener("wheel", recordWheelEvent);
|
||||
function recordWheelEvent(event) {
|
||||
allEvents.events.push({
|
||||
"type": event.type,
|
||||
"button": event.button,
|
||||
"buttons": event.buttons,
|
||||
"pageX": event.pageX,
|
||||
"pageY": event.pageY,
|
||||
"deltaX": event.deltaX,
|
||||
"deltaY": event.deltaY,
|
||||
"deltaZ": event.deltaZ,
|
||||
"deltaMode": event.deltaMode,
|
||||
"target": event.target.id,
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h2>ScrollReporter</h2>
|
||||
<div id="outer" class="area">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>OverflowScrollReporter</h2>
|
||||
<div id="scrollable">
|
||||
<div id="scrollContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>IframeScrollReporter</h2>
|
||||
<iframe id='subframe' srcdoc='
|
||||
<script>
|
||||
document.scrollingElement.addEventListener("wheel",
|
||||
function(event) {
|
||||
window.parent.allEvents.events.push({
|
||||
"type": event.type,
|
||||
"button": event.button,
|
||||
"buttons": event.buttons,
|
||||
"deltaX": event.deltaX,
|
||||
"deltaY": event.deltaY,
|
||||
"deltaZ": event.deltaZ,
|
||||
"deltaMode": event.deltaMode,
|
||||
"target": event.target.id
|
||||
});
|
||||
}
|
||||
|
||||
addMessage(
|
||||
"type: " + event.type + " " +
|
||||
"button: " + event.button + ", " +
|
||||
"buttons: " + event.buttons + ", " +
|
||||
"pageX: " + event.pageX + ", " +
|
||||
"pageY: " + event.pageY + ", " +
|
||||
"deltaX: " + event.deltaX + ", " +
|
||||
"deltaY: " + event.deltaY + ", " +
|
||||
"deltaZ: " + event.deltaZ + ", " +
|
||||
"deltaMode: " + event.deltaMode + ", " +
|
||||
"target id: " + event.target.id
|
||||
);
|
||||
</script>
|
||||
<div id="iframeContent"
|
||||
style="width: 7500px; height: 7500px; background-color:blue" ></div>'>
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="resultContainer">
|
||||
<h2>Events</h2>
|
||||
<div id="events"></div>
|
||||
</div>
|
||||
</body>
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
eventReporter = document.getElementById("event-reporter");
|
||||
|
||||
var noScroll = document.getElementById("not-scrollable");
|
||||
noScroll.addEventListener("wheel", recordWheelEvent);
|
||||
|
||||
var scrollable = document.getElementById("scrollable");
|
||||
scrollable.addEventListener("wheel", recordWheelEvent);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h2>Scroll Reporter</h2>
|
||||
<div id="not-scrollable">
|
||||
<div id="not-scrollable-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Overflow Scroll Reporter</h2>
|
||||
<div id="scrollable">
|
||||
<div id="scrollable-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>iframe Scroll Reporter</h2>
|
||||
<iframe id="iframe" srcdoc='
|
||||
<script>
|
||||
document.scrollingElement.addEventListener("wheel", event => {
|
||||
window.parent.recordWheelEvent({
|
||||
"type": event.type,
|
||||
"button": event.button,
|
||||
"buttons": event.buttons,
|
||||
"pageX": event.pageX,
|
||||
"pageY": event.pageY,
|
||||
"deltaX": event.deltaX,
|
||||
"deltaY": event.deltaY,
|
||||
"deltaZ": event.deltaZ,
|
||||
"deltaMode": event.deltaMode,
|
||||
"target": event.target
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div id="iframeContent" style="width: 7500px; height: 7500px; background-color:blue">
|
||||
</div>'>
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
<div id="resultContainer">
|
||||
<hr />
|
||||
<h2>Events</h2>
|
||||
<div id="event-reporter"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user