Bug 1157789 - Add a test for the Inspector's collapse/expandAll context menu items. r=janx
authorAvik Pal <avikpal.me@gmail.com>
Wed, 07 Oct 2015 11:33:00 +0200
changeset 266915 ddc16c7d513d09f5b1e1bbea1abfac268105dc97
parent 266914 cd09b70dd073e06259126900a1af6b9c6207c6ef
child 266916 c175bf2dfde6e1b98d5c84e3336b8c0aeb985ee3
push id29503
push usercbook@mozilla.com
push dateFri, 09 Oct 2015 09:36:47 +0000
treeherdermozilla-central@462074ffada4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanx
bugs1157789
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1157789 - Add a test for the Inspector's collapse/expandAll context menu items. r=janx
devtools/client/inspector/test/browser.ini
devtools/client/inspector/test/browser_inspector_expand-collapse.js
devtools/client/inspector/test/head.js
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -34,16 +34,17 @@ support-files =
 [browser_inspector_breadcrumbs_keybinding.js]
 [browser_inspector_breadcrumbs_menu.js]
 [browser_inspector_breadcrumbs_mutations.js]
 [browser_inspector_delete-selected-node-01.js]
 [browser_inspector_delete-selected-node-02.js]
 [browser_inspector_delete-selected-node-03.js]
 [browser_inspector_destroy-after-navigation.js]
 [browser_inspector_destroy-before-ready.js]
+[browser_inspector_expand-collapse.js]
 [browser_inspector_gcli-inspect-command.js]
 skip-if = e10s # GCLI isn't e10s compatible. See bug 1128988.
 [browser_inspector_highlighter-01.js]
 [browser_inspector_highlighter-02.js]
 [browser_inspector_highlighter-03.js]
 [browser_inspector_highlighter-04.js]
 [browser_inspector_highlighter-by-type.js]
 [browser_inspector_highlighter-comments.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_expand-collapse.js
@@ -0,0 +1,54 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that context menu items exapnd all and collapse are shown properly.
+
+const TEST_URL = "data:text/html;charset=utf-8,<div id='parent-node'><div id='child-node'></div></div>";
+
+add_task(function* () {
+
+    // Test is often exceeding time-out threshold, similar to Bug 1137765
+    requestLongerTimeout(2);
+
+    let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
+
+    let nodeMenuCollapseElement = inspector.panelDoc.getElementById("node-menu-collapse");
+    let nodeMenuExpandElement = inspector.panelDoc.getElementById("node-menu-expand");
+
+    info("Selecting the parent node");
+
+    let front = yield getNodeFrontForSelector("#parent-node", inspector);
+
+    yield selectNode(front, inspector);
+
+    info("Simulating context menu click on the selected node container.");
+    contextMenuClick(getContainerForNodeFront(front, inspector).tagLine);
+
+    ok(nodeMenuCollapseElement.hasAttribute("disabled"), "Collapse option is disabled");
+
+    ok(!nodeMenuExpandElement.hasAttribute("disabled"), "ExpandAll option is enabled");
+
+    info("Testing whether expansion works properly");
+    dispatchCommandEvent(nodeMenuExpandElement);
+    info("Waiting for expansion to occur");
+    yield waitForMultipleChildrenUpdates(inspector);
+    let markUpContainer = getContainerForNodeFront(front, inspector);
+    ok(markUpContainer.expanded, "node has been successfully expanded");
+
+    //reslecting node after expansion
+    yield selectNode(front, inspector);
+
+    info("Testing whether collapse works properly");
+    info("Simulating context menu click on the selected node container.");
+    contextMenuClick(getContainerForNodeFront(front, inspector).tagLine);
+
+    ok(!nodeMenuCollapseElement.hasAttribute("disabled"), "Collapse option is enabled");
+
+    dispatchCommandEvent(nodeMenuCollapseElement);
+    info("Waiting for collapse to occur");
+    yield waitForMultipleChildrenUpdates(inspector);
+    ok(!markUpContainer.expanded, "node has been successfully collapsed");
+});
\ No newline at end of file
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -477,16 +477,45 @@ function dispatchCommandEvent(node) {
   info("Dispatching command event on " + node);
   let commandEvent = document.createEvent("XULCommandEvent");
   commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
                                 false, false, null);
   node.dispatchEvent(commandEvent);
 }
 
 /**
+ * A helper that simulates a contextmenu event on the given chrome DOM element.
+ */
+function contextMenuClick(element) {
+  let evt = element.ownerDocument.createEvent('MouseEvents');
+  let button = 2;  // right click
+
+  evt.initMouseEvent('contextmenu', true, true,
+       element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false,
+       false, false, false, button, null);
+
+  element.dispatchEvent(evt);
+}
+
+/**
+ * A helper that fetches a front for a node that matches the given selector or
+ * doctype node if the selector is falsy.
+ */
+function* getNodeFrontForSelector(selector, inspector) {
+  if (selector) {
+    info("Retrieving front for selector " + selector);
+    return getNodeFront(selector, inspector);
+  } else {
+    info("Retrieving front for doctype node");
+    let {nodes} = yield inspector.walker.children(inspector.walker.rootNode);
+    return nodes[0];
+  }
+}
+
+/**
  * Encapsulate some common operations for highlighter's tests, to have
  * the tests cleaner, without exposing directly `inspector`, `highlighter`, and
  * `testActor` if not needed.
  *
  * @param  {String}
  *    The highlighter's type
  * @return
  *    A generator function that takes an object with `inspector` and `testActor`
@@ -529,8 +558,38 @@ const getHighlighterHelperFor = (type) =
       },
 
       finalize: function*() {
         yield highlighter.finalize();
       }
     };
   }
 );
+
+// The expand all operation of the markup-view calls itself recursively and
+// there's not one event we can wait for to know when it's done
+// so use this helper function to wait until all recursive children updates are done.
+function* waitForMultipleChildrenUpdates(inspector) {
+// As long as child updates are queued up while we wait for an update already
+// wait again
+    if (inspector.markup._queuedChildUpdates &&
+        inspector.markup._queuedChildUpdates.size) {
+        yield waitForChildrenUpdated(inspector);
+        return yield waitForMultipleChildrenUpdates(inspector);
+    }
+}
+
+/**
+ * Using the markupview's _waitForChildren function, wait for all queued
+ * children updates to be handled.
+ * @param {InspectorPanel} inspector The instance of InspectorPanel currently
+ * loaded in the toolbox
+ * @return a promise that resolves when all queued children updates have been
+ * handled
+ */
+function waitForChildrenUpdated({markup}) {
+    info("Waiting for queued children updates to be handled");
+    let def = promise.defer();
+    markup._waitForChildren().then(() => {
+        executeSoon(def.resolve);
+    });
+    return def.promise;
+}