blob: 6d0f7d433b983f5d20e4ab378737009cefc674fe [file] [log] [blame]
Andrew Top61a84952019-04-30 15:07:33 -07001<!DOCTYPE HTML>
2<html>
3<!--
4 Test cases for Touch Events v1 Recommendation
5 http://www.w3.org/TR/touch-events/
6
7 These tests are based on Mozilla-Nokia-Google's single-touch
8 tests and to some extent Olli Pettay's multi-touch tests.
9
10 The primary purpose of the tests in this document is checking that the
11 various interfaces of the Touch Events APIs are correctly implemented.
12 Other interactions are covered in other test files.
13
14 This document references Test Assertions (abbrev TA below) written by Cathy Chan
15 http://www.w3.org/2010/webevents/wiki/TestAssertions
16-->
17
18<head>
19<title>Touch Events Multi-Touch Interface Tests</title>
20<meta name="viewport" content="width=device-width">
21<script src="/resources/testharness.js"></script>
22<script>
23 setup({explicit_done: true});
24
25 // Check a Touch object's atttributes for existence and correct type
26 // TA: 1.1.2, 1.1.3
27 function check_Touch_object (t) {
28 test(function() {
29 assert_equals(Object.prototype.toString.call(t), "[object Touch]", "touch is of type Touch");
30 }, "touch point is a Touch object");
31 [
32 ["long", "identifier"],
33 ["EventTarget", "target"],
34 ["long", "screenX"],
35 ["long", "screenY"],
36 ["long", "clientX"],
37 ["long", "clientY"],
38 ["long", "pageX"],
39 ["long", "pageY"],
40 ].forEach(function(attr) {
41 var type = attr[0];
42 var name = attr[1];
43
44 // existence check
45 test(function() {
46 assert_true(name in t, name + " attribute in Touch object");
47 }, "Touch." + name + " attribute exists");
48
49 // type check
50 switch(type) {
51 case "long":
52 test(function() {
53 assert_equals(typeof t[name], "number", name + " attribute of type long");
54 }, "Touch." + name + " attribute is of type number (long)");
55 break;
56 case "EventTarget":
57 // An event target is some type of Element
58 test(function() {
59 assert_true(t[name] instanceof Element, "EventTarget must be an Element.");
60 }, "Touch." + name + " attribute is of type Element");
61 break;
62 default:
63 break;
64 }
65 });
66 }
67
68 // Check a TouchList object's attributes and methods for existence and proper type
69 // Also make sure all of the members of the list are Touch objects
70 // TA: 1.2.1, 1.2.2, 1.2.5, 1.2.6
71 function check_TouchList_object (tl) {
72 test(function() {
73 assert_equals(Object.prototype.toString.call(tl), "[object TouchList]", "touch list is of type TouchList");
74 }, "touch list is a TouchList object");
75 [
76 ["unsigned long", "length"],
77 ["function", "item"],
78 ].forEach(function(attr) {
79 var type = attr[0];
80 var name = attr[1];
81
82 // existence check
83 test(function() {
84 assert_true(name in tl, name + " attribute in TouchList");
85 }, "TouchList." + name + " attribute exists");
86
87 // type check
88 switch(type) {
89 case "unsigned long":
90 test(function() {
91 assert_equals(typeof tl[name], "number", name + " attribute of type long");
92 }, "TouchList." + name + " attribute is of type number (unsigned long)");
93 break;
94 case "function":
95 test(function() {
96 assert_equals(typeof tl[name], "function", name + " attribute of type function");
97 }, "TouchList." + name + " attribute is of type function");
98 break;
99 default:
100 break;
101 }
102 });
103 // Each member of tl should be a proper Touch object
104 for (var i=0; i < tl.length; i++) {
105 check_Touch_object(tl.item(i));
106 }
107 }
108
109 // Check a TouchEvent event's attributes for existence and proper type
110 // Also check that each of the event's TouchList objects are valid
111 // TA: 1.{3,4,5}.1.1, 1.{3,4,5}.1.2
112 function check_TouchEvent(ev) {
113 test(function() {
114 assert_true(ev instanceof TouchEvent, "event is a TouchEvent event");
115 }, ev.type + " event is a TouchEvent event");
116 [
117 ["TouchList", "touches"],
118 ["TouchList", "targetTouches"],
119 ["TouchList", "changedTouches"],
120 ["boolean", "altKey"],
121 ["boolean", "metaKey"],
122 ["boolean", "ctrlKey"],
123 ["boolean", "shiftKey"],
124 ].forEach(function(attr) {
125 var type = attr[0];
126 var name = attr[1];
127
128 // existence check
129 test(function() {
130 assert_true(name in ev, name + " attribute in " + ev.type + " event");
131 }, ev.type + "." + name + " attribute exists");
132
133 // type check
134 switch(type) {
135 case "boolean":
136 test(function() {
137 assert_equals(typeof ev[name], "boolean", name + " attribute of type boolean");
138 }, ev.type + "." + name + " attribute is of type boolean");
139 break;
140 case "TouchList":
141 test(function() {
142 assert_equals(Object.prototype.toString.call(ev[name]), "[object TouchList]", name + " attribute of type TouchList");
143 }, ev.type + "." + name + " attribute is of type TouchList");
144 // Now check the validity of the TouchList
145 check_TouchList_object(ev[name]);
146 break;
147 default:
148 break;
149 }
150 });
151 }
152
153 function is_touch_over_element(touch, element) {
154 var bounds = element.getBoundingClientRect();
155 return touch.pageX >= bounds.left && touch.pageX <= bounds.right &&
156 touch.pageY >= bounds.top && touch.pageY <= bounds.bottom;
157 }
158
159 function check_touch_clientXY(touch) {
160 assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
161 assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
162 }
163
164 function run() {
165 var target0 = document.getElementById("target0");
166 var target1 = document.getElementById("target1");
167
168 var test_touchstart = async_test("touchstart event received");
169 var test_touchmove = async_test("touchmove event received");
170 var test_touchend = async_test("touchend event received");
171 var test_mousedown = async_test("Interaction with mouse events");
172
173 var touchstart_received = 0;
174 var touchmove_received = false;
175 var touchend_received = false;
176 var invalid_touchmove_received = false;
177
178 on_event(target0, "touchstart", function onTouchStart(ev) {
179 ev.preventDefault();
180
181 if(!touchstart_received) {
182 // Check event ordering TA: 1.6.2
183 test_touchstart.step(function() {
184 assert_false(touchmove_received, "touchstart precedes touchmove");
185 assert_false(touchend_received, "touchstart precedes touchend");
186 });
187 test_touchstart.done();
188 test_mousedown.done(); // If we got here, then the mouse event test is not needed.
189 }
190
191 if(++touchstart_received <= 2)
192 check_TouchEvent(ev);
193 });
194
195 on_event(target0, "touchmove", function onTouchMove(ev) {
196 ev.preventDefault();
197
198 if (touchmove_received)
199 return;
200 touchmove_received = true;
201
202 test_touchmove.step(function() {
203 assert_true(touchstart_received>0, "touchmove follows touchstart");
204 assert_false(touchend_received, "touchmove precedes touchend");
205 });
206 test_touchmove.done();
207
208 check_TouchEvent(ev);
209 });
210
211 on_event(target1, "touchmove", function onTouchMove(ev) {
212 invalid_touchmove_received = true;
213 });
214
215 on_event(window, "touchend", function onTouchEnd(ev) {
216 touchend_received = true;
217
218 test_touchend.step(function() {
219 assert_true(touchstart_received>0, "touchend follows touchstart");
220 assert_true(touchmove_received, "touchend follows touchmove");
221 assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
222 });
223 test_touchend.done();
224
225 check_TouchEvent(ev);
226 done();
227 });
228
229 on_event(target0, "mousedown", function onMouseDown(ev) {
230 test_mousedown.step(function() {
231 assert_true(touchstart_received,
232 "The touchstart event must be dispatched before any mouse " +
233 "events. (If this fails, it might mean that the user agent does " +
234 "not implement W3C touch events at all.)"
235 );
236 });
237 test_mousedown.done();
238
239 if (!touchstart_received) {
240 // Abort the tests. If touch events are not supported, then most of
241 // the other event handlers will never be called, and the test will
242 // time out with misleading results.
243 done();
244 }
245 });
246 }
247</script>
248<style>
249 div {
250 margin: 0em;
251 padding: 2em;
252 }
253 #target0 {
254 background: yellow;
255 border: 1px solid orange;
256 }
257 #target1 {
258 background: lightblue;
259 border: 1px solid blue;
260 }
261</style>
262</head>
263<body onload="run()">
264 <h1>Touch Events: multi-touch interface tests</h1>
265 <div id="target0">
266 Touch this box with one finger, then another one...
267 </div>
268 <div id="target1">
269 ...then drag to this box and lift your fingers.
270 </div>
271 <div id="log"></div>
272</body>
273</html>