<!doctype html>
<html>
  <head>
    <title>Lostpointercapture fires on document when target in shadow dom  is removed</title>
    <meta name="viewport" content="width=device-width">
    <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=810882">
    <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>
    <style>
      #shadowhost{
        height:200px;
        width:200px;
        background-color:magenta;
      }
    </style>
  </head>
  <body onload="onLoad()">
    <template id="template">
      <style>
          #content{
              height:100px;
              width:100px;
              background-color: lightgrey;
          }
      </style>
      <div id="content"></div>
    </template>
    <h1>Pointer Events - lostpointercapture when capturing element in shadow dom is removed by removing the shadow host</h1>
    <h4>
        Test Description:
        This test checks if lostpointercapture is fired at the document when the capturing node is removed from the document by removing the shadow host.
        The shadow host is colored magenta and the shadow dom element is colored gray.
        Complete the following actions:
        <ol>
            <li>Press left mouse button over "Set Capture" button. Pointer should be captured by the gray rectangle.</li>
            <li>Shadow host magenta rectangle including the gray rectangle will be removed from shadow dom.</li>
            <li>"lostpointercapture" should be received on the document not on the gray rectangle.</li>
        </ol>
    </h4>
    <div id="shadowhost"></div>
    <br>
    <input type="button" id="btnCapture" value="Set Capture">
    <div id="log"></div>
    <script>
      async function onLoad(){
        var logDiv = document.getElementById("log");
        function logMessage(message){
          var log = document.createElement("div");
          var messageNode = document.createTextNode(message);
          log.appendChild(messageNode);
          logDiv.appendChild(log);
        }
        var events = [];

        var host = document.getElementById("shadowhost");
        var shadowRoot = host.attachShadow({mode: "open"});
        var template = document.getElementById("template");
        var node = template.content.cloneNode(true);
        shadowRoot.appendChild(node);

        var content = host.shadowRoot.getElementById("content");
        var captureButton = document.getElementById("btnCapture");

        captureButton.addEventListener("pointerdown", function(event){
          logMessage("Pointer will be captured by the shadow dom gray rectangle.");
          content.setPointerCapture(event.pointerId);
          events.push("pointerdown@captureButton");
        });
        content.addEventListener("gotpointercapture", function(event){
          logMessage("Gray rectangle received pointercapture.");
          logMessage("Removing magenta rectangle (which includes gray rectangle) from shadow dom.")
          host.parentNode.removeChild(host);
          events.push("gotpointercapture@content");
        });
        content.addEventListener("lostpointercapture", function(event){
          logMessage("Test Failed! The element removed from shadow dom should not receive lostpointercapture.")
          events.push("lostpointercapture@content");
          if(window.promise_test && shadow_dom_test){
            shadow_dom_test.step(function(){
              assert_unreached("lostpointercapture must be fired on the document, not the capturing element");
              reject_test("lostpointercapture must not be dispatched on the disconnected node");
              shadow_dom_test.done();
            });
          }
        });
        document.addEventListener("lostpointercapture", function(event){
          logMessage("Test Passed! Document received lostpointercapture.");
          events.push("lostpointercapture@document");
          if(window.promise_test && shadow_dom_test){
            shadow_dom_test.step(function(){
              assert_array_equals(events, ["pointerdown@captureButton",
                "gotpointercapture@content",
                "lostpointercapture@document"]);
              resolve_test();
            });
          }
        });

        var shadow_dom_test = null;
          var resolve_test = null;
          var reject_test = null;

        function cleanup(){
          events = [];
          shadow_dom_test = null;
          resolve_test = null;
          reject_test = null;
        }
        if(window.promise_test){
          promise_test(async function(t){
            var actions_promise;
            return new Promise(function(resolve, reject){
              shadow_dom_test = t;
              resolve_test = resolve;
              reject_test = reject;
              t.add_cleanup(function(){
                cleanup();
              });
              var actions = new test_driver.Actions();
              actions_promise = actions
                .pointerMove(0, 0, {origin:captureButton})
                .pointerDown({button: actions.ButtonType.LEFT})
                .pointerUp({button: actions.ButtonType.LEFT})
                .send();
            }).finally(async () => {
              await actions_promise;
              t.done();
            });
          }, "lostpointercapture is dispatched on the document when shadow host is removed");
        }
      }
    </script>
  </body>
</html>

