tor-browser

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

pointerevent_after_target_removed.html (5769B)


      1 <!DOCTYPE HTML>
      2 <link rel="help" href="https://w3c.github.io/pointerevents/#firing-events-using-the-pointerevent-interface">
      3 <title>Enter/leave events fired to parent after child is removed</title>
      4 <meta name="variant" content="?mouse">
      5 <meta name="variant" content="?touch">
      6 <meta name="variant" content="?pen">
      7 <script src="/resources/testharness.js"></script>
      8 <script src="/resources/testharnessreport.js"></script>
      9 <script src="/resources/testdriver.js"></script>
     10 <script src="/resources/testdriver-actions.js"></script>
     11 <script src="/resources/testdriver-vendor.js"></script>
     12 <script src="pointerevent_support.js"></script>
     13 
     14 <style>
     15  div.target {
     16      width: 100px;
     17      height: 100px;
     18  }
     19 </style>
     20 <div class="target" id="parent">
     21  <div class="target" id="child">child</div>
     22 </div>
     23 <div id="done">done</div>
     24 
     25 <script>
     26  'use strict';
     27  const pointer_type = location.search.substring(1);
     28 
     29  const parent = document.getElementById("parent");
     30  const child = document.getElementById("child");
     31  const done = document.getElementById("done");
     32 
     33  let event_log = [];
     34  let logged_event_prefix = "";
     35  let received_compat_mouse_events = false;
     36 
     37  function logEvent(e) {
     38    if (e.type.startsWith(logged_event_prefix) && e.eventPhase == e.AT_TARGET) {
     39      event_log.push(e.type + "@" + e.target.id);
     40    }
     41    if (e.type.startsWith("mouse")) {
     42      received_compat_mouse_events = true;
     43    }
     44  }
     45 
     46  function removeChild() {
     47    child.remove();
     48    event_log.push("(child-removed)");
     49  }
     50 
     51  function setup() {
     52    const logged_event_suffixes =
     53        ["over", "out", "enter", "leave", "down", "up"];
     54    let targets = document.getElementsByClassName("target");
     55    for (let i = 0; i < targets.length; i++) {
     56      logged_event_suffixes.forEach(suffix => {
     57        targets[i].addEventListener("pointer" + suffix, logEvent);
     58        targets[i].addEventListener("mouse" + suffix, logEvent);
     59      });
     60    }
     61  }
     62 
     63  function addPromiseTest(remover_event, tested_event_prefix, expected_events) {
     64    const test_name = `${tested_event_prefix} events from ${pointer_type} `+
     65          `received before/after child removal at ${remover_event}`;
     66 
     67    promise_test(async test => {
     68      event_log = [];
     69      logged_event_prefix = tested_event_prefix;
     70 
     71      child.addEventListener(remover_event, removeChild);
     72      test.add_cleanup(() => {
     73        child.removeEventListener(remover_event, removeChild);
     74        if (!child.parentElement) {
     75          parent.appendChild(child);
     76        }
     77      });
     78 
     79      let done_click_promise = getEvent("click", done);
     80 
     81      let actions = new test_driver.Actions()
     82          .addPointer("TestPointer", pointer_type)
     83          .pointerMove(-30, -30, {origin: parent})
     84          .pointerDown()
     85          .pointerUp()
     86          .pointerMove(30, 30, {origin: parent})
     87          .pointerDown()
     88          .pointerUp()
     89          .pointerMove(0, 0, {origin: done})
     90          .pointerDown()
     91          .pointerUp();
     92 
     93      await actions.send();
     94      await done_click_promise;
     95 
     96      if (tested_event_prefix == "mouse" && !received_compat_mouse_events) {
     97        expected_events = [];
     98      }
     99 
    100      assert_equals(event_log.toString(), expected_events.toString(),
    101          "events received");
    102    }, test_name);
    103  }
    104 
    105  setup();
    106 
    107  const hoverable = pointer_type != "touch";
    108 
    109  // Tests for dispatched pointer events.
    110  addPromiseTest(
    111    "pointerdown",
    112    "pointer",
    113    hoverable
    114      ? ["pointerover@child", "pointerenter@parent", "pointerenter@child",
    115        "pointerdown@child", "(child-removed)", "pointerover@parent", "pointerup@parent",
    116        "pointerdown@parent", "pointerup@parent",
    117        "pointerout@parent", "pointerleave@parent"]
    118      : ["pointerover@child", "pointerenter@parent", "pointerenter@child", "pointerdown@child",
    119        "(child-removed)", "pointerover@parent",
    120        // pointerup should cause pointerout/pointerleave if the input source is not hoverable.
    121        "pointerup@parent", "pointerout@parent", "pointerleave@parent",
    122        // then, pointerdown should imply a pointermove again.
    123        "pointerover@parent", "pointerenter@parent", "pointerdown@parent",
    124        "pointerup@parent", "pointerout@parent", "pointerleave@parent"]
    125  );
    126  addPromiseTest(
    127    "pointerup",
    128    "pointer",
    129    hoverable
    130      ? ["pointerover@child", "pointerenter@parent", "pointerenter@child",
    131        "pointerdown@child", "pointerup@child", "(child-removed)",
    132        "pointerover@parent", "pointerdown@parent", "pointerup@parent",
    133        "pointerout@parent", "pointerleave@parent"]
    134      : ["pointerover@child", "pointerenter@parent", "pointerenter@child",
    135        "pointerdown@child", "pointerup@child", "(child-removed)",
    136        // only pointerleave should be fired if the input source is not hoverable
    137        // because pointerup removed the pointerout event target which is not
    138        // received pointerover event, but the pointer becomes invalid.
    139        "pointerleave@parent",
    140        // then, pointerdown should imply a pointermove again.
    141        "pointerover@parent", "pointerenter@parent", "pointerdown@parent", "pointerup@parent",
    142        "pointerout@parent", "pointerleave@parent"]
    143  );
    144 
    145  // Same tests for dispatched compatibility mouse events.
    146  addPromiseTest("mousedown", "mouse", [
    147    "mouseover@child", "mouseenter@parent", "mouseenter@child",
    148    "mousedown@child", "(child-removed)", "mouseover@parent", "mouseup@parent",
    149    "mousedown@parent", "mouseup@parent",
    150    "mouseout@parent", "mouseleave@parent"
    151  ]);
    152  addPromiseTest("mouseup", "mouse", [
    153    "mouseover@child", "mouseenter@parent", "mouseenter@child",
    154    "mousedown@child", "mouseup@child", "(child-removed)",
    155    "mouseover@parent", "mousedown@parent", "mouseup@parent",
    156    "mouseout@parent", "mouseleave@parent"
    157  ]);
    158 </script>