<!doctype html>
<meta charset="utf-8">
<title>Mousemove handling between elements</title>
<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 src="/uievents/resources/eventrecorder.js"></script>
<style>
#a {
  height: 120px;
  width: 200px;
  background: blue;
  display: flex;
  justify-content: center;
}
#b {
  height: 60px;
  width: 100px;
  margin: auto;
  background: green;
}
#c {
  height: 120px;
  width: 200px;
  background: yellow;
}
</style>
<p>
  Steps:

  <ol>
    <li>Move your mouse over the blue <code>&lt;div&gt;</code> element, later
      over the green one, later back to the blue one.
    <li>Move the mouse from the blue element to the yellow one, later to the
      white background.
  </ol>
</p>


<div id="a">
  <div id="b" align="center"></div>
</div>
<div id="c"></div>

<script>
setup({explicit_timeout: true});

var relevantEvents = [
  "mousemove",
  "mouseover",
  "mouseenter",
  "mouseout",
  "mouseleave"
];

function stopPropagation(e) {
  if (e.type != "mouseenter" && e.type != "mouseleave")
    assert_true(e.bubbles);
  event.stopPropagation();
}

window.onload = async function() {
  var a = document.getElementById("a");
  var b = document.getElementById("b");
  var c = document.getElementById("c");
  var inputs = [a, b, c];
  EventRecorder.configure({
      mergeEventTypes: ["mousemove"],
      objectMap: {
         "a": a,
         "b": b,
         "c": c
      }
    });
  EventRecorder.addEventListenersForNodes(relevantEvents, inputs, stopPropagation);
  var expected = [
    {type: "mouseover", target: "a"},
    {type: "mouseenter", target: "a"},
    {type: "mousemove", target: "a", optional: true},
    {type: "mouseout", target: "a"},
    {type: "mouseover", target: "b"},
    {type: "mouseenter", target: "b"},
    {type: "mousemove", target: "b", optional: true},
    {type: "mouseout", target: "b"},
    {type: "mouseleave", target: "b"},
    {type: "mouseover", target: "a"},
    {type: "mousemove", target: "a", optional: true},
    {type: "mouseout", target: "a"},
    {type: "mouseleave", target: "a"},
    {type: "mouseover", target: "c"},
    {type: "mouseenter", target: "c"},
    {type: "mousemove", target: "c", optional: true},
    {type: "mouseout", target: "c"},
    {type: "mouseleave", target: "c"}
  ];
  async_test(function(t) {
    c.addEventListener("mouseleave", function() {
      EventRecorder.stop();
      t.step(function() {
        assert_true(EventRecorder.checkRecords(expected));
        t.done();
      });
    }, false);
  }, "Mousemove events between elements should fire in the correct order.");
  EventRecorder.start();

  var a_rect = a.getClientRects()[0];
  var b_rect = b.getClientRects()[0];
  var c_rect = c.getClientRects()[0];
  var center_b_y = Math.round((b_rect.top + b_rect.bottom) / 2);
  var center_c_y = Math.round((c_rect.top + c_rect.bottom) / 2);

  // Inject mouse inputs.
  await new test_driver.Actions()
      .pointerMove(b_rect.right + 10, center_b_y)
      .pause(50)
      .pointerMove(0, 0, {origin: b})
      .pause(50)
      .pointerMove(b_rect.right + 10, center_b_y)
      .pause(50)
      .pointerMove(a_rect.right + 10, center_b_y)
      .pause(50)
      .pointerMove(c_rect.right + 10, center_c_y)
      .pause(50)
      .pointerMove(0, 0, {origin: c})
      .pause(50)
      .pointerMove(c_rect.right + 20, c_rect.bottom + 20)
      .send();
};
</script>
