<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1157469
-->
<head>
  <meta charset="utf-8">
  <title>Test for Bug 1157469</title>
  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
  <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
  <script type="application/javascript;version=1.8">

window.onload = function() {

  const Cu = Components.utils;
  const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
  const {InspectorFront} = require("devtools/shared/fronts/inspector");

  SimpleTest.waitForExplicitFinish();

  let inspectee = null;
  let inspector = null;
  let walker = null;
  let eventListener1 = function () {};
  let eventListener2 = function () {};
  let eventNode1;
  let eventNode2;
  let eventFront1;
  let eventFront2;

  addAsyncTest(function* setup() {
    info ("Setting up inspector and walker actors.");
    let url = document.getElementById("inspectorContent").href;

    yield new Promise(resolve => {
      attachURL(url, function(err, client, tab, doc) {
        inspectee = doc;
        inspector = InspectorFront(client, tab);
        resolve();
      });
    });

    walker = yield inspector.getWalker();
    ok(walker, "getWalker() should return an actor.");

    runNextTest();
  });

  addAsyncTest(function* setupEventTest() {
    eventNode1 = inspectee.querySelector("#a")
    eventNode2 = inspectee.querySelector("#b")

    eventFront1 = yield walker.querySelector(walker.rootNode, "#a");
    eventFront2 = yield walker.querySelector(walker.rootNode, "#b");

    runNextTest();
  });

  addAsyncTest(function* testChangeEventListenerOnSingleNode() {
    checkNodesHaveNoEventListener();

    info("add event listener on a single node");
    eventNode1.addEventListener("click", eventListener1);

    let mutations = yield waitForMutations();
    is(mutations.length, 1, "one mutation expected");
    is(mutations[0].target, eventFront1, "mutation targets eventFront1");
    is(mutations[0].type, "events", "mutation type is events");
    is(mutations[0].hasEventListeners, true, "mutation target should have event listeners");
    is(eventFront1.hasEventListeners, true, "eventFront1 should have event listeners");

    info("remove event listener on a single node");
    eventNode1.removeEventListener("click", eventListener1);

    mutations = yield waitForMutations();
    is(mutations.length, 1, "one mutation expected");
    is(mutations[0].target, eventFront1, "mutation targets eventFront1");
    is(mutations[0].type, "events", "mutation type is events");
    is(mutations[0].hasEventListeners, false, "mutation target should have no event listeners");
    is(eventFront1.hasEventListeners, false, "eventFront1 should have no event listeners");

    info("perform several event listener changes on a single node")
    eventNode1.addEventListener("click", eventListener1);
    eventNode1.addEventListener("click", eventListener2);
    eventNode1.removeEventListener("click", eventListener1);
    eventNode1.removeEventListener("click", eventListener2);

    mutations = yield waitForMutations();
    is(mutations.length, 1, "one mutation expected");
    is(mutations[0].target, eventFront1, "mutation targets eventFront1");
    is(mutations[0].type, "events", "mutation type is events");
    is(mutations[0].hasEventListeners, false, "no event listener expected on mutation target");
    is(eventFront1.hasEventListeners, false, "no event listener expected on node");

    runNextTest();
  });

  addAsyncTest(function* testChangeEventsOnSeveralNodes() {
    checkNodesHaveNoEventListener();

    info("add event listeners on both nodes");
    eventNode1.addEventListener("click", eventListener1);
    eventNode2.addEventListener("click", eventListener2);

    let mutations = yield waitForMutations();
    is(mutations.length, 2, "two mutations expected, one for each modified node");
    // first mutation
    is(mutations[0].target, eventFront1, "first mutation targets eventFront1");
    is(mutations[0].type, "events", "mutation type is events");
    is(mutations[0].hasEventListeners, true, "mutation target should have event listeners");
    is(eventFront1.hasEventListeners, true, "eventFront1 should have event listeners");
    // second mutation
    is(mutations[1].target, eventFront2, "second mutation targets eventFront2");
    is(mutations[1].type, "events", "mutation type is events");
    is(mutations[1].hasEventListeners, true, "mutation target should have event listeners");
    is(eventFront2.hasEventListeners, true, "eventFront1 should have event listeners");

    info("remove event listeners on both nodes");
    eventNode1.removeEventListener("click", eventListener1);
    eventNode2.removeEventListener("click", eventListener2);

    mutations = yield waitForMutations();
    is(mutations.length, 2, "one mutation registered for event listener change");
    // first mutation
    is(mutations[0].target, eventFront1, "first mutation targets eventFront1");
    is(mutations[0].type, "events", "mutation type is events");
    is(mutations[0].hasEventListeners, false, "mutation target should have no event listeners");
    is(eventFront1.hasEventListeners, false, "eventFront2 should have no event listeners");
    // second mutation
    is(mutations[1].target, eventFront2, "second mutation targets eventFront2");
    is(mutations[1].type, "events", "mutation type is events");
    is(mutations[1].hasEventListeners, false, "mutation target should have no event listeners");
    is(eventFront2.hasEventListeners, false, "eventFront2 should have no event listeners");

    runNextTest();
  });

  addAsyncTest(function* testRemoveMissingEvent() {
    checkNodesHaveNoEventListener();

    info("try to remove an event listener not previously added");
    eventNode1.removeEventListener("click", eventListener1);

    info("set any attribute on the node to trigger a mutation")
    eventNode1.setAttribute("data-attr", "somevalue");

    let mutations = yield waitForMutations();
    is(mutations.length, 1, "expect only one mutation");
    isnot(mutations.type, "events", "mutation type should not be events");

    runNextTest();
  });

  function checkNodesHaveNoEventListener() {
    is(eventFront1.hasEventListeners, false, "eventFront1 hasEventListeners should be false");
    is(eventFront2.hasEventListeners, false, "eventFront2 hasEventListeners should be false");
  };

  function waitForMutations() {
    return new Promise(resolve => {
      walker.once("mutations", mutations => {
        resolve(mutations);
      });
    });
  }

  runNextTest();
}

  </script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1157469">Mozilla Bug 1157469</a>
<a id="inspectorContent" target="_blank" href="inspector-traversal-data.html">Test Document</a>
<p id="display"></p>
<div id="content" style="display: none">

</div>
<pre id="test">
</pre>
</body>
</html>