<!doctype html>
<html>
  <head>
    <title>Pointer Event: Suppress compatibility mouse events on drag</title>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
    <link rel="author" title="Google" href="http://www.google.com "/>
    <meta name="assert" content="When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events."/>
    <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
    <script src="/resources/testharness.js"></script>
    <script src="/resources/testharnessreport.js"></script>
    <script src="/resources/testdriver.js"></script>
    <script src="/resources/testdriver-actions.js"></script>
    <script src="/resources/testdriver-vendor.js"></script>
    <script type="text/javascript" src="pointerevent_support.js"></script>
    <script type="text/javascript">
      var test_pointerEvent = async_test("Suppress compat mouse events on drag");
      add_completion_callback(end_of_test);
      var actions_promise;

      var detected_pointertypes = {};
      var event_log = [];

      function end_of_test() {
          showLoggedEvents();
          showPointerTypes();
      }

      var include_next_mousemove = false;

      // Limits logging/testing of mousemove.
      function drop_event(event_type) {
          return (event_type == "mousemove" && !include_next_mousemove);
      }

      function end_of_interaction() {
          test(function () {
              assert_equals(event_log.join(", "),
                  "mousedown@target1, mousemove@target1, mouseup@target1");
          }, "Event log");

          // Make sure the test finishes after all the input actions are completed.
          actions_promise.then( () => {
              test_pointerEvent.done();
          });
      }

      function run() {
          var targetDone = document.getElementById('done');
          on_event(targetDone, "click", end_of_interaction);

          var target_list = ["target0", "target1"];
          var pointer_event_list = ["pointerdown" , "pointermove", "pointerup"];
          var mouse_event_list = ["mousedown", "mouseup", "mousemove"];

          target_list.forEach(function(targetId) {
              var target = document.getElementById(targetId);

              pointer_event_list.forEach(function(eventName) {
                  on_event(target, eventName, function (event) {
                      detected_pointertypes[event.pointerType] = true;
                      var label = event.type + "@" + targetId;

                      if (event.type == "pointerdown") {
                          test(function () {
                              assert_true(event.isPrimary);
                          }, "primary pointer " + label);
                      }

                      if (label === "pointerdown@target0")
                          event.preventDefault();
                  });
              });

              mouse_event_list.forEach(function(eventName) {
                  on_event(target, eventName, function (event) {
                      if (drop_event(event.type))
                          return;

                      event_log.push(event.type + "@" + targetId);

                      include_next_mousemove = (event.type == "mousedown");
                  });
              });
          });

          // Inject mouse inputs.
          actions_promise = new test_driver.Actions()
              .pointerMove(0, 0, {origin: target0})
              .pointerDown()
              .pointerMove(10, 0, {origin: target0})
              .pointerUp()
              .pointerMove(0, 0, {origin: target1})
              .pointerDown()
              .pointerMove(10, 0, {origin: target1})
              .pointerUp()
              .pointerMove(0, 0, {origin: targetDone})
              .pointerDown()
              .pointerUp()
              .send();
      }
    </script>
    <style>
      #target0, #target1 {
        margin: 20px;
        touch-action: none;
      }

      #done {
        margin: 20px;
        border: 2px solid black;
      }
    </style>
  </head>
  <body onload="run()">
    <h1>Pointer Event: Suppress compatibility mouse events on drag</h1>
    <h4>
      When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events.
    </h4>
    <ol>
      <li> Drag mouse within Target0 &amp; release.</li>
      <li> Drag mouse within Target1 &amp; release.</li>
      <li> Click Done.</li>
    </ol>
    <div id="target0">
      Target0
    </div>
    <div id="target1">
      Target1
    </div>
    <div id="done">
      Done
    </div>
    <div id="complete-notice">
      <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
      <p>The following events were logged: <span id="event-log"></span>.</p>
    </div>
    <div id="log"></div>
  </body>
</html>
