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