Bug 1357590 - Test drag and drop with mouse actions; r?ato
MozReview-Commit-ID: 6vRHj7pRGdh
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -181336,17 +181336,17 @@
"ace7008a593a32ca016685aaa85bda9b4c4bd8c8",
"testharness"
],
"html/webappapis/idle-callbacks/callback-invoked.html": [
"e7cf5a399d92f1fcb98f6ebb1ed3283d60d2bfe2",
"testharness"
],
"html/webappapis/idle-callbacks/callback-multiple-calls.html": [
- "6375309c43a1e7c9fafdc95f01fcccb4c92f8afc",
+ "af6e6a65fda2486ac8669340988b1d57a178e77a",
"testharness"
],
"html/webappapis/idle-callbacks/callback-removed-frame.html": [
"ff034276659407d2dea91d2b0ed0e5919b875904",
"testharness"
],
"html/webappapis/idle-callbacks/callback-suspended.html": [
"f3f9eeda9e2d47825c77eaf278be6e976a8e1715",
@@ -208156,17 +208156,17 @@
"78b6434a88021b7f56e5a7bf3e858fc9558a7c19",
"wdspec"
],
"webdriver/actions/key.py": [
"918bcadf034657dfcb679fd92c8a11efe34bfedf",
"wdspec"
],
"webdriver/actions/mouse.py": [
- "86b27e994042b37b4889175a10a02c30a24d3c7e",
+ "823e2b1e5ba200487d0598eecbb051f73b5ea69f",
"wdspec"
],
"webdriver/actions/sequence.py": [
"d80f382863e52ff223db735a2a551197e570774f",
"wdspec"
],
"webdriver/actions/special_keys.py": [
"b2d6c2fa8852c6299b6bd214f67007efebe3029a",
@@ -208180,17 +208180,17 @@
"636991372c21e52b623ed4ada9dfb675dd7f7e14",
"support"
],
"webdriver/actions/support/refine.py": [
"0d244bffe67ef57be68aad99f1cbc7440ff80e27",
"support"
],
"webdriver/actions/support/test_actions_wdspec.html": [
- "ccd55308840f1b7ab6e9c56b7123b9ac370f0d25",
+ "c56cc117512bf9a5b6378dcead8e2640493d23a4",
"support"
],
"webdriver/conftest.py": [
"39ba7649c437b50bb97d766561e4bd5a110f6459",
"wdspec"
],
"webdriver/contexts.py": [
"302a1a0cb246aef74f2c1d961a210d9de7e366c5",
--- a/testing/web-platform/tests/webdriver/actions/mouse.py
+++ b/testing/web-platform/tests/webdriver/actions/mouse.py
@@ -1,23 +1,36 @@
+import pytest
import urllib
from support.refine import get_events, filter_dict
# TODO use support.inline module once available from upstream
def inline(doc):
return "data:text/html;charset=utf-8,%s" % urllib.quote(doc)
def link_doc(dest):
content = "<a href=\"{}\" id=\"link\">destination</a>".format(dest)
return inline(content)
+def get_center(rect):
+ return {
+ "x": rect["width"] / 2 + rect["x"],
+ "y": rect["height"] / 2 + rect["y"],
+ }
+
+
+# TODO use pytest.approx once we upgrade to pytest > 3.0
+def approx(n, m, tolerance=1):
+ return abs(n - m) < tolerance
+
+
def test_click_at_coordinates(session, test_actions_page, mouse_chain):
div_point = {
"x": 82,
"y": 187,
}
mouse_chain \
.pointer_move(div_point["x"], div_point["y"], duration=1000) \
.click() \
@@ -38,29 +51,26 @@ def test_click_at_coordinates(session, t
{"type": "click", "buttons": 0},
]
filtered_events = [filter_dict(e, expected[0]) for e in events]
assert expected == filtered_events[1:]
def test_click_element_center(session, test_actions_page, mouse_chain):
outer = session.find.css("#outer", all=False)
- outer_rect = outer.rect
- center_x = outer_rect["width"] / 2 + outer_rect["x"]
- center_y = outer_rect["height"] / 2 + outer_rect["y"]
+ center = get_center(outer.rect)
mouse_chain.click(element=outer).perform()
events = get_events(session)
assert len(events) == 4
event_types = [e["type"] for e in events]
assert ["mousemove", "mousedown", "mouseup", "click"] == event_types
for e in events:
if e["type"] != "mousemove":
- # TODO use pytest.approx once we upgrade to pytest > 3.0
- assert abs(e["pageX"] - center_x) < 1
- assert abs(e["pageY"] - center_y) < 1
+ assert approx(e["pageX"], center["x"])
+ assert approx(e["pageY"], center["y"])
assert e["target"] == "outer"
def test_click_navigation(session, url):
destination = url("/webdriver/actions/support/test_actions_wdspec.html")
start = link_doc(destination)
def click(link):
@@ -70,8 +80,34 @@ def test_click_navigation(session, url):
session.url = start
click(session.find.css("#link", all=False))
assert session.url == destination
# repeat steps to check behaviour after document unload
session.url = start
click(session.find.css("#link", all=False))
assert session.url == destination
+
+
+@pytest.mark.parametrize("drag_duration", [0, 300, 800])
+@pytest.mark.parametrize("dx, dy", [(20, 0), (0, 15), (10, 15)])
+def test_drag_and_drop(session, test_actions_page, mouse_chain, dx, dy, drag_duration):
+ drag_target = session.find.css("#dragTarget", all=False)
+ initial_rect = drag_target.rect
+ initial_center = get_center(initial_rect)
+ # Conclude chain with extra move to allow time for last queued
+ # coordinate-update of drag_target and to test that drag_target is "dropped".
+ mouse_chain \
+ .pointer_move(0, 0, origin=drag_target) \
+ .pointer_down() \
+ .pointer_move(dx, dy, duration=drag_duration, origin="pointer") \
+ .pointer_up() \
+ .pointer_move(80, 50, duration=100, origin="pointer") \
+ .perform()
+ # mouseup that ends the drag is at the expected destination
+ e = get_events(session)[1]
+ assert e["type"] == "mouseup"
+ assert approx(e["pageX"], initial_center["x"] + dx)
+ assert approx(e["pageY"], initial_center["y"] + dy)
+ # check resulting location of the dragged element
+ final_rect = drag_target.rect
+ assert initial_rect["x"] + dx == final_rect["x"]
+ assert initial_rect["y"] + dy == final_rect["y"]
--- a/testing/web-platform/tests/webdriver/actions/support/test_actions_wdspec.html
+++ b/testing/web-platform/tests/webdriver/actions/support/test_actions_wdspec.html
@@ -1,23 +1,24 @@
<!doctype html>
<meta charset=utf-8>
<head>
<title>Test Actions</title>
<style>
div { padding:0px; margin: 0px; }
+ #trackPointer { position: fixed; }
#resultContainer { width: 600px; height: 60px; }
- #outer { width: 100px; height: 50px; background-color: #ccc; }
- #trackPointer {
- width: 5px;
- height: 5px;
- border: solid 1px red;
- position: fixed; }
+ .area { width: 100px; height: 50px; background-color: #ccc; }
+ .block { width: 5px; height: 5px; border: solid 1px red; }
+ #dragArea { position: relative; }
+ #dragTarget { position: absolute; top:22px; left:47px;}
</style>
<script>
+ "use strict";
+ var els = {};
var allEvents = {events: []};
function displayMessage(message) {
document.getElementById("events").innerHTML = "<p>" + message + "</p>";
}
function appendMessage(message) {
document.getElementById("events").innerHTML += "<p>" + message + "</p>";
}
@@ -85,48 +86,85 @@
window.removeEventListener("mousemove", recordFirstPointerMove);
}
function resetEvents() {
allEvents.events.length = 0;
displayMessage("");
}
+ function drop(moveHandler) {
+ return function (event) {
+ els.dragArea.removeEventListener("mousemove", moveHandler);
+ els.dragTarget.style.backgroundColor = "yellow";
+ els.dragTarget.addEventListener("mousedown", grab);
+ recordPointerEvent(event);
+ };
+ }
+
+ function move(el, offsetX, offsetY, timeout) {
+ return (event) => {
+ setTimeout(() => {
+ el.style.top = event.clientY + offsetY + "px";
+ el.style.left = event.clientX + offsetX + "px";
+ }, timeout);
+ };
+ }
+
+ function grab(event) {
+ event.target.style.backgroundColor = "red";
+ let boxRect = event.target.getBoundingClientRect();
+ let areaRect = event.target.parentElement.getBoundingClientRect();
+ let moveHandler = move(
+ event.target,
+ // coordinates of dragTarget must be relative to dragArea such that
+ // dragTarget remains under the pointer
+ -(areaRect.left + (event.clientX - boxRect.left)),
+ -(areaRect.top + (event.clientY - boxRect.top)),
+ 20);
+ els.dragArea.addEventListener("mousemove", moveHandler);
+ els.dragArea.addEventListener("mouseup", drop(moveHandler), {once: true});
+ }
+
document.addEventListener("DOMContentLoaded", () => {
var keyReporter = document.getElementById("keys");
["keyup", "keypress", "keydown"].forEach((e) => {
keyReporter.addEventListener(e, recordKeyboardEvent);
});
var outer = document.getElementById("outer");
["click", "dblclick", "mousedown",
"mouseup", "contextmenu"].forEach((e) => {
outer.addEventListener(e, recordPointerEvent);
});
- window.addEventListener("mousemove", recordFirstPointerMove);
+ window.addEventListener("mousemove", recordPointerEvent, {once: true});
//visual cue for mousemove
var pointer = document.getElementById("trackPointer");
- window.addEventListener("mousemove", (e) => {
- setTimeout(() => {
- let offset = 15;
- pointer.style.top = e.pageY + offset + "px";
- pointer.style.left = e.pageX + offset + "px";
- }, 30);
- });
+ window.addEventListener("mousemove", move(pointer, 15, 15, 30));
+ // drag and drop
+ els.dragArea = document.getElementById("dragArea");
+ els.dragTarget = document.getElementById("dragTarget");
+ els.dragTarget.addEventListener("mousedown", grab, {once: true});
});
</script>
</head>
<body>
- <div id="trackPointer"></div>
+ <div id="trackPointer" class="block"></div>
<div>
<h2>KeyReporter</h2>
<input type="text" id="keys" size="80">
</div>
<div>
<h2>ClickReporter</h2>
- <div id="outer">
+ <div id="outer" class="area">
+ </div>
+ </div>
+ <div>
+ <h2>DragReporter</h2>
+ <div id="dragArea" class="area">
+ <div id="dragTarget" class="block"></div>
</div>
</div>
<div id="resultContainer">
<h2>Events</h2>
<div id="events"></div>
</div>
</body>
</html>