tor-browser

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

test_legacy_event.html (10208B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=1236979
      5 -->
      6 <head>
      7  <meta charset="utf-8">
      8  <title>Test for Bug 1236979 (events that have legacy alternative versions)</title>
      9  <script src="/tests/SimpleTest/SimpleTest.js"></script>
     10  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     11  <style>
     12    @keyframes anim1 {
     13      0%   { margin-left: 0px }
     14      100% { margin-left: 100px }
     15    }
     16  </style>
     17 </head>
     18 <body>
     19 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1236979">Mozilla Bug 1236979</a>
     20 <p id="display"></p>
     21 <div id="content" style="display: none">
     22 
     23 </div>
     24 <pre id="test">
     25 <script type="application/javascript">
     26 
     27 /** Test for Bug 1236979 */
     28 
     29 'use strict';
     30 SimpleTest.waitForExplicitFinish();
     31 
     32 // Array of info-bundles about each legacy event to be tested:
     33 var gLegacyEventInfo = [
     34  {
     35    legacy_name: "webkitTransitionEnd",
     36    modern_name: "transitionend",
     37    trigger_event: triggerShortTransition,
     38  },
     39  {
     40    legacy_name: "webkitAnimationStart",
     41    modern_name: "animationstart",
     42    trigger_event: triggerShortAnimation,
     43  },
     44  {
     45    legacy_name: "webkitAnimationEnd",
     46    modern_name: "animationend",
     47    trigger_event: triggerShortAnimation,
     48  },
     49  {
     50    legacy_name: "webkitAnimationIteration",
     51    modern_name: "animationiteration",
     52    trigger_event: triggerAnimationIteration,
     53  }
     54 ];
     55 
     56 // EVENT-TRIGGERING FUNCTIONS
     57 // --------------------------
     58 // This function triggers a very short (1ms long) transition, which will cause
     59 // events to fire for the transition ending.
     60 function triggerShortTransition(node) {
     61  node.style.transition = "1ms color linear" ;
     62  node.style.color = "purple";
     63  // Flush style, so that the above assignment value actually takes effect
     64  // in the computed style, so that a transition will get triggered when it
     65  // changes.
     66  window.getComputedStyle(node).color;
     67  node.style.color = "teal";
     68 }
     69 
     70 // This function triggers a very short (1ms long) animation, which will cause
     71 // events to fire for the animation beginning & ending.
     72 function triggerShortAnimation(node) {
     73  node.style.animation = "anim1 1ms linear";
     74 }
     75 
     76 // This function triggers a very short (10ms long) animation with many
     77 // iterations, which will cause a start event followed by an iteration event
     78 // on each subsequent tick, to fire.
     79 //
     80 // NOTE: We need the many iterations since if an animation frame coincides
     81 // with the animation starting or ending we dispatch only the start or end
     82 // event and not the iteration event.
     83 function triggerAnimationIteration(node) {
     84  node.style.animation = "anim1 10ms linear 20000";
     85 }
     86 
     87 // GENERAL UTILITY FUNCTIONS
     88 // -------------------------
     89 // Creates a new div and appends it as a child of the specified parentNode, or
     90 // (if no parent is specified) as a child of the element with ID 'display'.
     91 function createChildDiv(parentNode) {
     92  if (!parentNode) {
     93    parentNode = document.getElementById("display");
     94    if (!parentNode) {
     95      ok(false, "no 'display' element to append to");
     96    }
     97  }
     98  var div = document.createElement("div");
     99  parentNode.appendChild(div);
    100  return div;
    101 }
    102 
    103 // Returns an event-handler function, which (when invoked) simply checks that
    104 // the event's type matches what's expected. If a callback is passed in, then
    105 // the event-handler will invoke that callback as well.
    106 function createHandlerWithTypeCheck(expectedEventType, extraHandlerLogic) {
    107  var handler = function(e) {
    108    is(e.type, expectedEventType,
    109       "When an event handler for '" + expectedEventType + "' is invoked, " +
    110       "the event's type field should be '" + expectedEventType + "'.");
    111    if (extraHandlerLogic) {
    112      extraHandlerLogic(e);
    113    }
    114  }
    115  return handler;
    116 }
    117 
    118 // TEST FUNCTIONS
    119 // --------------
    120 // These functions expect to be passed an entry from gEventInfo, and they
    121 // return a Promise which performs the test & resolves when it's complete.
    122 // The function names all begin with "mp", which stands for "make promise".
    123 // So e.g. "mpTestLegacyEventSent" means "make a promise to test that the
    124 // legacy event is sent".
    125 
    126 // Tests that the legacy event type is sent, when only a legacy handler is
    127 // registered.
    128 function mpTestLegacyEventSent(eventInfo) {
    129  return new Promise(
    130    function(resolve, reject) {
    131      // Create a node & register an event-handler for the legacy event:
    132      var div = createChildDiv();
    133 
    134      var handler = createHandlerWithTypeCheck(eventInfo.legacy_name,
    135                                               function() {
    136        // When event-handler is done, clean up & resolve:
    137        div.remove();
    138        resolve();
    139      });
    140      div.addEventListener(eventInfo.legacy_name, handler);
    141 
    142      // Trigger the event:
    143      eventInfo.trigger_event(div);
    144    }
    145  );
    146 }
    147 
    148 // Test that the modern event type (and only the modern event type) is fired,
    149 // when listeners of both modern & legacy types are registered. The legacy
    150 // listener should not be invoked.
    151 function mpTestModernBeatsLegacy(eventInfo) {
    152  return new Promise(
    153    function(resolve, reject) {
    154      var div = createChildDiv();
    155 
    156      var legacyHandler = function(e) {
    157        reject("Handler for legacy event '" + eventInfo.legacy_name +
    158               "' should not be invoked when there's a handler registered " +
    159               "for both modern & legacy event type on the same node");
    160      };
    161 
    162      var modernHandler = createHandlerWithTypeCheck(eventInfo.modern_name,
    163                                                     function() {
    164        // Indicate that the test has passed (we invoked the modern handler):
    165        ok(true, "Handler for modern event '" + eventInfo.modern_name +
    166           "' should be invoked when there's a handler registered for " +
    167           "both modern & legacy event type on the same node");
    168        // When event-handler is done, clean up & resolve:
    169        div.remove();
    170        resolve();
    171      });
    172 
    173      div.addEventListener(eventInfo.legacy_name, legacyHandler);
    174      div.addEventListener(eventInfo.modern_name, modernHandler);
    175      eventInfo.trigger_event(div);
    176    }
    177  );
    178 }
    179 
    180 // Test that an event which bubbles may fire listeners of different flavors
    181 // (modern vs. legacy) at each bubbling level, depending on what's registered
    182 // at that level.
    183 function mpTestDiffListenersEventBubbling(eventInfo) {
    184  return new Promise(
    185    function(resolve, reject) {
    186      var grandparent = createChildDiv();
    187      var parent = createChildDiv(grandparent);
    188      var target = createChildDiv(parent);
    189      var didEventFireOnTarget = false;
    190      var didEventFireOnParent = false;
    191      var eventSentToTarget;
    192 
    193      target.addEventListener(eventInfo.modern_name,
    194        createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
    195          ok(e.bubbles, "Expecting event to bubble");
    196          eventSentToTarget = e;
    197          didEventFireOnTarget = true;
    198        }));
    199 
    200      parent.addEventListener(eventInfo.legacy_name,
    201        createHandlerWithTypeCheck(eventInfo.legacy_name, function(e) {
    202          is(e, eventSentToTarget,
    203             "Same event object should bubble, despite difference in type");
    204          didEventFireOnParent = true;
    205        }));
    206 
    207      grandparent.addEventListener(eventInfo.modern_name,
    208        createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
    209        ok(didEventFireOnTarget,
    210           "Event should have fired on child");
    211        ok(didEventFireOnParent,
    212           "Event should have fired on parent");
    213        is(e, eventSentToTarget,
    214           "Same event object should bubble, despite difference in type");
    215        // Clean up.
    216        grandparent.remove();
    217        resolve();
    218      }));
    219 
    220      eventInfo.trigger_event(target);
    221    }
    222  );
    223 }
    224 
    225 // Test that an event in the capture phase may fire listeners of different
    226 // flavors (modern vs. legacy) at each level, depending on what's registered
    227 // at that level.
    228 function mpTestDiffListenersEventCapturing(eventInfo) {
    229  return new Promise(
    230    function(resolve, reject) {
    231      var grandparent = createChildDiv();
    232      var parent = createChildDiv(grandparent);
    233      var target = createChildDiv(parent);
    234      var didEventFireOnTarget = false;
    235      var didEventFireOnParent = false;
    236      var didEventFireOnGrandparent = false;
    237      var eventSentToGrandparent;
    238 
    239      grandparent.addEventListener(eventInfo.modern_name,
    240        createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
    241          eventSentToGrandparent = e;
    242          didEventFireOnGrandparent = true;
    243        }), true);
    244 
    245      parent.addEventListener(eventInfo.legacy_name,
    246        createHandlerWithTypeCheck(eventInfo.legacy_name, function(e) {
    247          is(e.eventPhase, Event.CAPTURING_PHASE,
    248             "event should be in capturing phase");
    249          is(e, eventSentToGrandparent,
    250             "Same event object should capture, despite difference in type");
    251          ok(didEventFireOnGrandparent,
    252             "Event should have fired on grandparent");
    253          didEventFireOnParent = true;
    254      }), true);
    255 
    256      target.addEventListener(eventInfo.modern_name,
    257        createHandlerWithTypeCheck(eventInfo.modern_name, function(e) {
    258          is(e.eventPhase, Event.AT_TARGET,
    259             "event should be at target phase");
    260          is(e, eventSentToGrandparent,
    261             "Same event object should capture, despite difference in type");
    262          ok(didEventFireOnParent,
    263             "Event should have fired on parent");
    264          // Clean up.
    265          grandparent.remove();
    266          resolve();
    267      }), true);
    268 
    269      eventInfo.trigger_event(target);
    270    }
    271  );
    272 }
    273 
    274 // MAIN FUNCTION: Kick off the tests.
    275 function main() {
    276  Promise.resolve().then(function() {
    277    return Promise.all(gLegacyEventInfo.map(mpTestLegacyEventSent))
    278  }).then(function() {
    279    return Promise.all(gLegacyEventInfo.map(mpTestModernBeatsLegacy));
    280  }).then(function() {
    281    return Promise.all(gLegacyEventInfo.map(mpTestDiffListenersEventCapturing));
    282  }).then(function() {
    283    return Promise.all(gLegacyEventInfo.map(mpTestDiffListenersEventBubbling));
    284  }).then(function() {
    285    SimpleTest.finish();
    286  }).catch(function(reason) {
    287    ok(false, "Test failed: " + reason);
    288    SimpleTest.finish();
    289  });
    290 }
    291 
    292 main();
    293 
    294 </script>
    295 </pre>
    296 </body>
    297 </html>