<!DOCTYPE HTML>
<title>Enter/leave events fired to parent after child is removed</title>
<meta name="variant" content="?mouse">
<meta name="variant" content="?touch">
<meta name="variant" content="?pen">
<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="pointerevent_support.js"></script>

<style>
  div.target {
      width: 100px;
      height: 50px;
  }
</style>
<div class="target" id="parent">
  <div class="target" id="child">child</div>
</div>
<div id="done">done</div>

<script>
  'use strict';
  const pointer_type = location.search.substring(1);

  const parent = document.getElementById("parent");
  const child = document.getElementById("child");
  const done = document.getElementById("done");

  let event_log = [];
  let logged_event_prefix = "";

  function logEvent(e) {
    if (e.type.startsWith(logged_event_prefix) && e.eventPhase == e.AT_TARGET)
      event_log.push(e.type);
  }

  function setup() {
    const logged_events = [
      "pointerover", "pointerout", "pointerenter", "pointerleave",
      "mouseover", "mouseout", "mouseenter", "mouseleave"
    ];
    logged_events.forEach(ename => parent.addEventListener(ename, logEvent));
  }

  function addPromiseTest(remover_event, tested_event_prefix) {
    const test_name = `${tested_event_prefix} events from ${pointer_type} `+
        `at parent after child is removed at ${remover_event}`;
    const expected_events = ["enter", "over", "out", "leave"]
        .map(suffix => tested_event_prefix + suffix);

    promise_test(async () => {
      event_log = [];
      logged_event_prefix = tested_event_prefix;

      // Bring the child back if it was removed in the previous promise_test.
      if (!child.parentElement)
        parent.appendChild(child);

      child.addEventListener(remover_event,
          () => parent.removeChild(child),
          { once:true });

      let done_click_promise = getEvent("click", done);

      let actions = new test_driver.Actions()
          .addPointer("TestPointer", pointer_type)
          .pointerMove(0, 0, {origin: parent})
          .pointerDown()
          .pointerUp()
          .pointerMove(0, 0, {origin: done})
          .pointerDown()
          .pointerUp();

      await actions.send();
      await done_click_promise;

      assert_equals(event_log.toString(), expected_events.toString(),
          "received events");
    }, test_name);
  }

  setup();
  addPromiseTest("pointerdown", "pointer");
  addPromiseTest("pointerdown", "mouse");
  addPromiseTest("pointerup", "pointer");
  addPromiseTest("pointerup", "mouse");
</script>
