Bug 1139187 - Unit Test for Geometry Editor; r=pbro
authorMatteo Ferretti <mferretti@mozilla.com>
Thu, 17 Mar 2016 10:59:39 -0400
changeset 291317 5fd9689bcac1185b7c228ac3d1bdd1eadb5c9f00
parent 291316 bc7bd1234a7f992045ceb5e271abe8f9834bf4ba
child 291318 0d60f0d8b5e04ef009a7ec87ecba1e311bb23c5b
push id74545
push userkwierso@gmail.com
push dateFri, 01 Apr 2016 23:05:42 +0000
treeherdermozilla-inbound@c410d4e20586 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1139187
milestone48.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 1139187 - Unit Test for Geometry Editor; r=pbro MozReview-Commit-ID: 9smoBjNt1St
devtools/client/inspector/test/browser_inspector_highlighter-geometry_01.js
devtools/client/inspector/test/browser_inspector_highlighter-geometry_02.js
devtools/client/inspector/test/browser_inspector_highlighter-geometry_03.js
devtools/client/inspector/test/browser_inspector_highlighter-geometry_04.js
devtools/client/inspector/test/browser_inspector_highlighter-geometry_05.js
devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html
devtools/client/inspector/test/head.js
devtools/client/shared/test/test-actor.js
--- a/devtools/client/inspector/test/browser_inspector_highlighter-geometry_01.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-geometry_01.js
@@ -1,95 +1,89 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // Test the creation of the geometry highlighter elements.
 
-const TEST_URL = "data:text/html;charset=utf-8," +
-                 "<span id='inline'></span>" +
-                 "<div id='positioned' style='background:yellow;position:absolute;left:5rem;top:30px;right:300px;bottom:10em;'></div>" +
-                 "<div id='sized' style='background:red;width:5em;height:50%;'></div>";
+const TEST_URL = `data:text/html;charset=utf-8,
+                  <span id='inline'></span>
+                  <div id='positioned' style='
+                    background:yellow;
+                    position:absolute;
+                    left:5rem;
+                    top:30px;
+                    right:300px;
+                    bottom:10em;'></div>
+                  <div id='sized' style='
+                    background:red;
+                    width:5em;
+                    height:50%;'></div>`;
+
+const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
+
 const ID = "geometry-editor-";
 const SIDES = ["left", "right", "top", "bottom"];
-const SIZES = ["width", "height"];
 
-add_task(function*() {
-  let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
-  let front = inspector.inspector;
+add_task(function* () {
+  let helper = yield openInspectorForURL(TEST_URL)
+                       .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
+
+  let { finalize } = helper;
 
-  let highlighter = yield front.getHighlighterByType("GeometryEditorHighlighter");
+  helper.prefix = ID;
 
-  yield hasArrowsAndLabels(highlighter, inspector, testActor);
-  yield isHiddenForNonPositionedNonSizedElement(highlighter, inspector, testActor);
-  yield sideArrowsAreDisplayedForPositionedNode(highlighter, inspector, testActor);
-  yield sizeLabelIsDisplayedForSizedNode(highlighter, inspector, testActor);
+  yield hasArrowsAndLabelsAndHandlers(helper);
+  yield isHiddenForNonPositionedNonSizedElement(helper);
+  yield sideArrowsAreDisplayedForPositionedNode(helper);
 
-  yield highlighter.finalize();
+  finalize();
 });
 
-function* hasArrowsAndLabels(highlighterFront, inspector, testActor) {
+function* hasArrowsAndLabelsAndHandlers({getElementAttribute}) {
   info("Checking that the highlighter has the expected arrows and labels");
 
   for (let name of [...SIDES]) {
-    let value = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "class", highlighterFront);
+    let value = yield getElementAttribute("arrow-" + name, "class");
     is(value, ID + "arrow " + name, "The " + name + " arrow exists");
 
-    value = yield testActor.getHighlighterNodeAttribute(ID + "label-text-" + name, "class", highlighterFront);
+    value = yield getElementAttribute("label-text-" + name, "class");
     is(value, ID + "label-text", "The " + name + " label exists");
-  }
-
-  let value = yield testActor.getHighlighterNodeAttribute(ID + "label-text-size", "class", highlighterFront);
-  is(value, ID + "label-text", "The size label exists");
-}
-
-function* isHiddenForNonPositionedNonSizedElement(highlighterFront, inspector, testActor) {
-  info("Asking to show the highlighter on an inline, non positioned element");
 
-  let node = yield getNodeFront("#inline", inspector);
-  yield highlighterFront.show(node);
-
-  for (let name of [...SIDES]) {
-    let hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "hidden", highlighterFront);
-    is(hidden, "true", "The " + name + " arrow is hidden");
+    value = yield getElementAttribute("handler-" + name, "class");
+    is(value, ID + "handler-" + name, "The " + name + " handler exists");
   }
-
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "label-size", "hidden", highlighterFront);
-  is(hidden, "true", "The size label is hidden");
 }
 
-function* sideArrowsAreDisplayedForPositionedNode(highlighterFront, inspector, testActor) {
+function* isHiddenForNonPositionedNonSizedElement(
+  {show, hide, isElementHidden}) {
+  info("Asking to show the highlighter on an inline, non p  ositioned element");
+
+  yield show("#inline");
+
+  for (let name of [...SIDES]) {
+    let hidden = yield isElementHidden("arrow-" + name);
+    ok(hidden, "The " + name + " arrow is hidden");
+
+    hidden = yield isElementHidden("handler-" + name);
+    ok(hidden, "The " + name + " handler is hidden");
+  }
+}
+
+function* sideArrowsAreDisplayedForPositionedNode(
+  {show, hide, isElementHidden}) {
   info("Asking to show the highlighter on the positioned node");
 
-  let node = yield getNodeFront("#positioned", inspector);
-  yield highlighterFront.show(node);
+  yield show("#positioned");
 
   for (let name of SIDES) {
-    let hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "hidden", highlighterFront);
+    let hidden = yield isElementHidden("arrow-" + name);
     ok(!hidden, "The " + name + " arrow is visible for the positioned node");
-  }
-
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "label-size", "hidden", highlighterFront);
-  is(hidden, "true", "The size label is hidden");
-
-  info("Hiding the highlighter");
-  yield highlighterFront.hide();
-}
 
-function* sizeLabelIsDisplayedForSizedNode(highlighterFront, inspector, testActor) {
-  info("Asking to show the highlighter on the sized node");
-
-  let node = yield getNodeFront("#sized", inspector);
-  yield highlighterFront.show(node);
-
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "label-size", "hidden", highlighterFront);
-  ok(!hidden, "The size label is visible");
-
-  for (let name of SIDES) {
-    let hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "hidden", highlighterFront);
-    is(hidden, "true", "The " + name + " arrow is hidden for the sized node");
+    hidden = yield isElementHidden("handler-" + name);
+    ok(!hidden, "The " + name + " handler is visible for the positioned node");
   }
 
   info("Hiding the highlighter");
-  yield highlighterFront.hide();
+  yield hide();
 }
--- a/devtools/client/inspector/test/browser_inspector_highlighter-geometry_02.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-geometry_02.js
@@ -1,24 +1,48 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* Globals defined in: devtools/client/inspector/test/head.js */
+
 "use strict";
 
 // Test that the geometry highlighter labels are correct.
 
-const TEST_URL = "data:text/html;charset=utf-8," +
-                 "<div id='positioned' style='background:yellow;position:absolute;left:5rem;top:30px;right:300px;bottom:10em;'></div>" +
-                 "<div id='positioned2' style='background:blue;position:absolute;right:10%;top:5vmin;'>test element</div>" +
-                 "<div id='relative' style='background:green;position:relative;top:10px;left:20px;bottom:30px;right:40px;width:100px;height:100px;'></div>" +
-                 "<div id='relative2' style='background:grey;position:relative;top:0;bottom:-50px;height:3em;'>relative</div>" +
-                 "<div id='sized' style='background:red;width:5em;height:50%;'></div>" +
-                 "<div id='sized2' style='background:orange;width:40px;position:absolute;right:0;bottom:0'>wow</div>";
+const TEST_URL = `data:text/html;charset=utf-8,
+                  <div id='positioned' style='
+                    background:yellow;
+                    position:absolute;
+                    left:5rem;
+                    top:30px;
+                    right:300px;
+                    bottom:10em;'></div>
+                  <div id='positioned2' style='
+                    background:blue;
+                    position:absolute;
+                    right:10%;
+                    top:5vmin;'>test element</div>
+                 <div id='relative' style='
+                    background:green;
+                    position:relative;
+                    top:10px;
+                    left:20px;
+                    bottom:30px;
+                    right:40px;
+                    width:100px;
+                    height:100px;'></div>
+                 <div id='relative2' style='
+                    background:grey;
+                    position:relative;
+                    top:0;bottom:-50px;
+                    height:3em;'>relative</div>`;
+
 const ID = "geometry-editor-";
+const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
 
 const POSITIONED_ELEMENT_TESTS = [{
   selector: "#positioned",
   expectedLabels: [
     {side: "left", visible: true, label: "5rem"},
     {side: "top", visible: true, label: "30px"},
     {side: "right", visible: true, label: "300px"},
     {side: "bottom", visible: true, label: "10em"}
@@ -27,24 +51,16 @@ const POSITIONED_ELEMENT_TESTS = [{
   selector: "#positioned2",
   expectedLabels: [
     {side: "left", visible: false},
     {side: "top", visible: true, label: "5vmin"},
     {side: "right", visible: true, label: "10%"},
     {side: "bottom", visible: false}
   ]
 }, {
-  selector: "#sized",
-  expectedLabels: [
-    {side: "left", visible: false},
-    {side: "top", visible: false},
-    {side: "right", visible: false},
-    {side: "bottom", visible: false}
-  ]
-}, {
   selector: "#relative",
   expectedLabels: [
     {side: "left", visible: true, label: "20px"},
     {side: "top", visible: true, label: "10px"},
     {side: "right", visible: false},
     {side: "bottom", visible: false}
   ]
 }, {
@@ -52,91 +68,49 @@ const POSITIONED_ELEMENT_TESTS = [{
   expectedLabels: [
     {side: "left", visible: false},
     {side: "top", visible: true, label: "0px"},
     {side: "right", visible: false},
     {side: "bottom", visible: false}
   ]
 }];
 
-const SIZED_ELEMENT_TESTS = [{
-  selector: "#positioned",
-  visible: false
-}, {
-  selector: "#sized",
-  visible: true,
-  expected: "\u2194 5em \u2195 50%"
-}, {
-  selector: "#relative",
-  visible: true,
-  expected: "\u2194 100px \u2195 100px"
-}, {
-  selector: "#relative2",
-  visible: true,
-  expected: "\u2195 3em"
-}, {
-  selector: "#sized2",
-  visible: true,
-  expected: "\u2194 40px"
-}];
+add_task(function* () {
+  let helper = yield openInspectorForURL(TEST_URL)
+                       .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
+
+  helper.prefix = ID;
 
-add_task(function*() {
-  let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
-  let front = inspector.inspector;
+  let { finalize } = helper;
 
-  let highlighter = yield front.getHighlighterByType("GeometryEditorHighlighter");
+  yield positionLabelsAreCorrect(helper);
 
-  yield positionLabelsAreCorrect(highlighter, inspector, testActor);
-  yield sizeLabelIsCorrect(highlighter, inspector, testActor);
-
-  yield highlighter.finalize();
+  yield finalize();
 });
 
-function* positionLabelsAreCorrect(highlighterFront, inspector, testActor) {
+function* positionLabelsAreCorrect(
+  {show, hide, isElementHidden, getElementTextContent}
+) {
   info("Highlight nodes and check position labels");
 
   for (let {selector, expectedLabels} of POSITIONED_ELEMENT_TESTS) {
     info("Testing node " + selector);
-    let node = yield getNodeFront(selector, inspector);
-    yield highlighterFront.show(node);
+
+    yield show(selector);
 
     for (let {side, visible, label} of expectedLabels) {
-      let id = ID + "label-" + side;
+      let id = "label-" + side;
 
-      let hidden = yield testActor.getHighlighterNodeAttribute(id, "hidden", highlighterFront);
+      let hidden = yield isElementHidden(id);
       if (visible) {
         ok(!hidden, "The " + side + " label is visible");
 
-        let value = yield testActor.getHighlighterNodeTextContent(id, highlighterFront);
+        let value = yield getElementTextContent(id);
         is(value, label, "The " + side + " label textcontent is correct");
       } else {
-        is(hidden, "true", "The " + side + " label is hidden");
+        ok(hidden, "The " + side + " label is hidden");
       }
     }
 
     info("Hiding the highlighter");
-    yield highlighterFront.hide();
+    yield hide();
   }
 }
-
-function* sizeLabelIsCorrect(highlighterFront, inspector, testActor) {
-  info("Highlight nodes and check size labels");
-
-  let id = ID + "label-size";
-  for (let {selector, visible, expected} of SIZED_ELEMENT_TESTS) {
-    info("Testing node " + selector);
-    let node = yield getNodeFront(selector, inspector);
-    yield highlighterFront.show(node);
-
-    let hidden = yield testActor.getHighlighterNodeAttribute(id, "hidden", highlighterFront);
-    if (!visible) {
-      is(hidden, "true", "The size label is hidden");
-    } else {
-      ok(!hidden, "The size label is visible");
-
-      let label = yield testActor.getHighlighterNodeTextContent(id, highlighterFront);
-      is(label, expected, "The size label textcontent is correct");
-    }
-
-    info("Hiding the highlighter");
-    yield highlighterFront.hide();
-  }
-}
--- a/devtools/client/inspector/test/browser_inspector_highlighter-geometry_03.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-geometry_03.js
@@ -1,60 +1,61 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* Globals defined in: devtools/client/inspector/test/head.js */
+
 "use strict";
 
 // Test that the right arrows/labels are shown even when the css properties are
 // in several different css rules.
 
 const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html";
 const ID = "geometry-editor-";
+const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
 const PROPS = ["left", "right", "top", "bottom"];
 
-add_task(function*() {
-  let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
-  let front = inspector.inspector;
+add_task(function* () {
+  let helper = yield openInspectorForURL(TEST_URL)
+                       .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
 
-  let highlighter = yield front.getHighlighterByType("GeometryEditorHighlighter");
+  helper.prefix = ID;
+
+  let { finalize } = helper;
 
-  yield checkArrowsLabels("#node1", ["size"],
-                          highlighter, inspector, testActor);
+  yield checkArrowsLabelsAndHandlers(
+    "#node2", ["top", "left", "bottom", "right"],
+     helper);
 
-  yield checkArrowsLabels("#node2", ["top", "left", "bottom", "right"],
-                          highlighter, inspector, testActor);
+  yield checkArrowsLabelsAndHandlers("#node3", ["top", "left"], helper);
 
-  yield checkArrowsLabels("#node3", ["top", "left", "size"],
-                          highlighter, inspector, testActor);
-
-  yield highlighter.finalize();
+  yield finalize();
 });
 
-function* checkArrowsLabels(selector, expectedProperties, highlighterFront, inspector, testActor) {
+function* checkArrowsLabelsAndHandlers(selector, expectedProperties,
+  {show, hide, isElementHidden}
+) {
   info("Getting node " + selector + " from the page");
-  let node = yield getNodeFront(selector, inspector);
 
-  info("Highlighting the node");
-  yield highlighterFront.show(node);
+  yield show(selector);
 
   for (let name of expectedProperties) {
-    let hidden;
-    if (name === "size") {
-      hidden = yield testActor.getHighlighterNodeAttribute(ID + "label-size", "hidden", highlighterFront);
-    } else {
-      hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "hidden", highlighterFront);
-    }
-    ok(!hidden, "The " + name + " arrow/label is visible for node " + selector);
+    let hidden = (yield isElementHidden("arrow-" + name)) &&
+                 (yield isElementHidden("handler-" + name));
+    ok(!hidden,
+      "The " + name + " label/arrow & handler is visible for node " + selector);
   }
 
   // Testing that the other arrows are hidden
   for (let name of PROPS) {
     if (expectedProperties.indexOf(name) !== -1) {
       continue;
     }
-    let hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, "hidden", highlighterFront);
-    is(hidden, "true", "The " + name + " arrow is hidden for node " + selector);
+    let hidden = (yield isElementHidden("arrow-" + name)) &&
+                 (yield isElementHidden("handler-" + name));
+    ok(hidden,
+      "The " + name + " arrow & handler is hidden for node " + selector);
   }
 
   info("Hiding the highlighter");
-  yield highlighterFront.hide();
+  yield hide();
 }
--- a/devtools/client/inspector/test/browser_inspector_highlighter-geometry_04.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-geometry_04.js
@@ -1,56 +1,85 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+ /* Globals defined in: devtools/client/inspector/test/head.js */
+
 "use strict";
 
-// Test that the arrows are positioned correctly and have the right size.
+// Test that the arrows and handlers are positioned correctly and have the right
+// size.
 
 const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html";
 const ID = "geometry-editor-";
+const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
 
-add_task(function*() {
-  let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
-  let front = inspector.inspector;
+const handlerMap = {
+  "top": {"cx": "x2", "cy": "y2"},
+  "bottom": {"cx": "x2", "cy": "y2"},
+  "left": {"cx": "x2", "cy": "y2"},
+  "right": {"cx": "x2", "cy": "y2"}
+};
 
-  let highlighter = yield front.getHighlighterByType("GeometryEditorHighlighter");
+add_task(function* () {
+  let helper = yield openInspectorForURL(TEST_URL)
+                       .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
+
+  helper.prefix = ID;
 
-  yield checkArrows(highlighter, inspector, testActor, ".absolute-all-4", {
-   "top": {x1: 506, y1: 51, x2: 506, y2: 61},
-   "bottom": {x1: 506, y1: 451, x2: 506, y2: 251},
-   "left": {x1: 401, y1: 156, x2: 411, y2: 156},
-   "right": {x1: 901, y1: 156, x2: 601, y2: 156}
+  let { hide, finalize } = helper;
+
+  yield checkArrowsAndHandlers(helper, ".absolute-all-4", {
+    "top": {x1: 506, y1: 51, x2: 506, y2: 61},
+    "bottom": {x1: 506, y1: 451, x2: 506, y2: 251},
+    "left": {x1: 401, y1: 156, x2: 411, y2: 156},
+    "right": {x1: 901, y1: 156, x2: 601, y2: 156}
   });
 
-  yield checkArrows(highlighter, inspector, testActor, ".relative", {
-   "top": {x1: 901, y1: 51, x2: 901, y2: 91},
-   "left": {x1: 401, y1: 97, x2: 651, y2: 97}
+  yield checkArrowsAndHandlers(helper, ".relative", {
+    "top": {x1: 901, y1: 51, x2: 901, y2: 91},
+    "left": {x1: 401, y1: 97, x2: 651, y2: 97}
   });
 
-  yield checkArrows(highlighter, inspector, testActor, ".fixed", {
-   "top": {x1: 25, y1: 0, x2: 25, y2: 400},
-   "left": {x1: 0, y1: 425, x2: 0, y2: 425}
+  yield checkArrowsAndHandlers(helper, ".fixed", {
+    "top": {x1: 25, y1: 0, x2: 25, y2: 400},
+    "left": {x1: 0, y1: 425, x2: 0, y2: 425}
   });
 
   info("Hiding the highlighter");
-  yield highlighter.hide();
-  yield highlighter.finalize();
+  yield hide();
+  yield finalize();
 });
 
-function* checkArrows(highlighter, inspector, testActor, selector, arrows) {
+function* checkArrowsAndHandlers(helper, selector, arrows) {
   info("Highlighting the test node " + selector);
-  let node = yield getNodeFront(selector, inspector);
-  yield highlighter.show(node);
+
+  yield helper.show(selector);
 
   for (let side in arrows) {
-    yield checkArrow(highlighter, testActor, side, arrows[side]);
+    yield checkArrowAndHandler(helper, side, arrows[side]);
   }
 }
 
-function* checkArrow(highlighter, testActor, name, expectedCoordinates) {
-  for (let coordinate in expectedCoordinates) {
-    let value = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + name, coordinate, highlighter);
-    is(Math.floor(value), expectedCoordinates[coordinate],
+function* checkArrowAndHandler({getElementAttribute}, name, expectedCoords) {
+  info("Checking " + name + "arrow and handler coordinates are correct");
+
+  let handlerX = yield getElementAttribute("handler-" + name, "cx");
+  let handlerY = yield getElementAttribute("handler-" + name, "cy");
+
+  let expectedHandlerX = yield getElementAttribute("arrow-" + name,
+                                handlerMap[name].cx);
+  let expectedHandlerY = yield getElementAttribute("arrow-" + name,
+                                handlerMap[name].cy);
+
+  is(handlerX, expectedHandlerX,
+    "coordinate X for handler " + name + " is correct.");
+  is(handlerY, expectedHandlerY,
+    "coordinate Y for handler " + name + " is correct.");
+
+  for (let coordinate in expectedCoords) {
+    let value = yield getElementAttribute("arrow-" + name, coordinate);
+
+    is(Math.floor(value), expectedCoords[coordinate],
       coordinate + " coordinate for arrow " + name + " is correct");
   }
 }
--- a/devtools/client/inspector/test/browser_inspector_highlighter-geometry_05.js
+++ b/devtools/client/inspector/test/browser_inspector_highlighter-geometry_05.js
@@ -1,134 +1,119 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+ /* Globals defined in: devtools/client/inspector/test/head.js */
+
 "use strict";
 
-// Test that the arrows and offsetparent and currentnode elements of the
-// geometry highlighter only appear when needed.
+// Test that the arrows/handlers and offsetparent and currentnode elements of
+// the geometry highlighter only appear when needed.
 
 const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_02.html";
 const ID = "geometry-editor-";
+const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
 
 const TEST_DATA = [{
   selector: "body",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: false,
-  hasVisibleArrows: false,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: false
 }, {
   selector: "h1",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: false,
-  hasVisibleArrows: false,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: false
 }, {
   selector: ".absolute",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: true
 }, {
   selector: "#absolute-container",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: false,
-  isSizeVisible: true
+  hasVisibleArrowsAndHandlers: false
 }, {
   selector: ".absolute-bottom-right",
   isOffsetParentVisible: true,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: true
 }, {
   selector: ".absolute-width-margin",
   isOffsetParentVisible: true,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: true
+  hasVisibleArrowsAndHandlers: true
 }, {
   selector: ".absolute-all-4",
   isOffsetParentVisible: true,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: true
 }, {
   selector: ".relative",
   isOffsetParentVisible: true,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: true
 }, {
   selector: ".static",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: false,
-  hasVisibleArrows: false,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: false
 }, {
   selector: ".static-size",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: false,
-  isSizeVisible: true
+  hasVisibleArrowsAndHandlers: false
 }, {
   selector: ".fixed",
   isOffsetParentVisible: false,
   isCurrentNodeVisible: true,
-  hasVisibleArrows: true,
-  isSizeVisible: false
+  hasVisibleArrowsAndHandlers: true
 }];
 
-add_task(function*() {
-  let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
-  let front = inspector.inspector;
+add_task(function* () {
+  let helper = yield openInspectorForURL(TEST_URL)
+                       .then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
 
-  let highlighter = yield front.getHighlighterByType("GeometryEditorHighlighter");
+  helper.prefix = ID;
+
+  let { hide, finalize } = helper;
 
   for (let data of TEST_DATA) {
-    yield testNode(inspector, highlighter, testActor, data);
+    yield testNode(helper, data);
   }
 
   info("Hiding the highlighter");
-  yield highlighter.hide();
-  yield highlighter.finalize();
+  yield hide();
+  yield finalize();
 });
 
-function* testNode(inspector, highlighter, testActor, data) {
-  info("Highlighting the test node " + data.selector);
-  let node = yield getNodeFront(data.selector, inspector);
-  yield highlighter.show(node);
+function* testNode(helper, data) {
+  let { selector } = data;
+  yield helper.show(data.selector);
 
-  is((yield isOffsetParentVisible(highlighter, testActor)), data.isOffsetParentVisible,
-    "The offset-parent highlighter visibility is correct for node " + data.selector);
-  is((yield isCurrentNodeVisible(highlighter, testActor)), data.isCurrentNodeVisible,
-    "The current-node highlighter visibility is correct for node " + data.selector);
-  is((yield hasVisibleArrows(highlighter, testActor)), data.hasVisibleArrows,
-    "The arrows visibility is correct for node " + data.selector);
-  is((yield isSizeVisible(highlighter, testActor)), data.isSizeVisible,
-    "The size label visibility is correct for node " + data.selector);
+  is((yield isOffsetParentVisible(helper)), data.isOffsetParentVisible,
+    "The offset-parent highlighter visibility is correct for node " + selector);
+  is((yield isCurrentNodeVisible(helper)), data.isCurrentNodeVisible,
+    "The current-node highlighter visibility is correct for node " + selector);
+  is((yield hasVisibleArrowsAndHandlers(helper)),
+    data.hasVisibleArrowsAndHandlers,
+    "The arrows visibility is correct for node " + selector);
 }
 
-function* isOffsetParentVisible(highlighter, testActor) {
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "offset-parent", "hidden", highlighter);
-  return !hidden;
+function* isOffsetParentVisible({isElementHidden}) {
+  return !(yield isElementHidden("offset-parent"));
 }
 
-function* isCurrentNodeVisible(highlighter, testActor) {
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "current-node", "hidden", highlighter);
-  return !hidden;
+function* isCurrentNodeVisible({isElementHidden}) {
+  return !(yield isElementHidden("current-node"));
 }
 
-function* hasVisibleArrows(highlighter, testActor) {
+function* hasVisibleArrowsAndHandlers({isElementHidden}) {
   for (let side of ["top", "left", "bottom", "right"]) {
-    let hidden = yield testActor.getHighlighterNodeAttribute(ID + "arrow-" + side, "hidden", highlighter);
+    let hidden = yield isElementHidden("arrow-" + side);
     if (!hidden) {
-      return true;
+      return !(yield isElementHidden("handler-" + side));
     }
   }
   return false;
 }
-
-function* isSizeVisible(highlighter, testActor) {
-  let hidden = yield testActor.getHighlighterNodeAttribute(ID + "label-size", "hidden", highlighter);
-  return !hidden;
-}
--- a/devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html
+++ b/devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html
@@ -23,17 +23,17 @@
       position: absolute;
       background: #f06;
     }
     .pos-top-left {
       top: 30px;
       left: 25%;
     }
     .pos-bottom-right {
-      bottom: 5em;
+      bottom: 10em;
       right: -10px;
     }
 
     .inline-positioned {
       background: yellow;
     }
 
     #absolute-container {
--- a/devtools/client/inspector/test/head.js
+++ b/devtools/client/inspector/test/head.js
@@ -470,24 +470,46 @@ function* getNodeFrontForSelector(select
  */
 const getHighlighterHelperFor = (type) => Task.async(
   function*({inspector, testActor}) {
     let front = inspector.inspector;
     let highlighter = yield front.getHighlighterByType(type);
 
     let prefix = "";
 
+    // Internals for mouse events
+    let prevX, prevY;
+
+    // Highlighted node
+    let  highlightedNode = null;
+
     return {
       set prefix(value) {
         prefix = value;
       },
+      get highlightedNode() {
+        if (!highlightedNode) {
+          return null;
+        }
+
+        return {
+          getComputedStyle: function*(options = {}) {
+            return yield inspector.pageStyle.getComputed(
+              highlightedNode, options);
+          }
+        };
+      },
 
       show: function*(selector = ":root") {
-        let node = yield getNodeFront(selector, inspector);
-        yield highlighter.show(node);
+        highlightedNode = yield getNodeFront(selector, inspector);
+        return yield highlighter.show(highlightedNode);
+      },
+
+      hide: function*() {
+        yield highlighter.hide();
       },
 
       isElementHidden: function*(id) {
         return (yield testActor.getHighlighterNodeAttribute(
           prefix + id, "hidden", highlighter)) === "true";
       },
 
       getElementTextContent: function*(id) {
@@ -496,20 +518,45 @@ const getHighlighterHelperFor = (type) =
       },
 
       getElementAttribute: function*(id, name) {
         return yield testActor.getHighlighterNodeAttribute(
           prefix + id, name, highlighter);
       },
 
       synthesizeMouse: function*(options) {
+        options = Object.assign({selector: ":root"}, options);
         yield testActor.synthesizeMouse(options);
       },
 
+      // This object will synthesize any "mouse" prefixed event to the
+      // `testActor`, using the name of method called as suffix for the
+      // event's name.
+      // If no x, y coords are given, the previous ones are used.
+      //
+      // For example:
+      //   mouse.down(10, 20); // synthesize "mousedown" at 10,20
+      //   mouse.move(20, 30); // synthesize "mousemove" at 20,30
+      //   mouse.up();         // synthesize "mouseup" at 20,30
+      mouse: new Proxy({}, {
+        get: (target, name) =>
+          function*(x = prevX, y = prevY) {
+            prevX = x;
+            prevY = y;
+            yield testActor.synthesizeMouse({
+              selector: ":root", x, y, options: {type: "mouse" + name}});
+          }
+      }),
+
+      reflow: function*() {
+        yield testActor.reflow();
+      },
+
       finalize: function*() {
+        highlightedNode = null;
         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
--- a/devtools/client/shared/test/test-actor.js
+++ b/devtools/client/shared/test/test-actor.js
@@ -615,16 +615,27 @@ var TestActor = exports.TestActor = prot
       y: Arg(1, "number"),
       relative: Arg(2, "nullable:boolean"),
     },
     response: {
       value: RetVal("json")
     }
   }),
 
+  /**
+   * Forces the reflow and waits for the next repaint.
+   */
+  reflow: protocol.method(function () {
+    let deferred = promise.defer();
+    this.content.document.documentElement.offsetWidth;
+    this.content.requestAnimationFrame(deferred.resolve);
+
+    return deferred.promise;
+  }),
+
   getNodeRect: protocol.method(Task.async(function* (selector) {
     let node = this._querySelector(selector);
     return getRect(this.content, node, this.content);
   }), {
     request: {
       selector: Arg(0, "string")
     },
     response: {