tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

multi-touch-interfaces.html (11774B)


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