Bug 1427818 - Fix browser_layoutHelpers-getBoxQuads.js on e10s. r=pbro draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 03 Jan 2018 10:19:03 -0800
changeset 717313 b9702e523b40666b8d55bd294641f10300404c11
parent 717183 ca379fcca95b1f4a3744242ea8647004b99b3507
child 745207 3d06277095c78ccf957fb52db050fb36674a5b16
push id94623
push userbmo:poirot.alex@gmail.com
push dateMon, 08 Jan 2018 16:21:48 +0000
reviewerspbro
bugs1427818
milestone59.0a1
Bug 1427818 - Fix browser_layoutHelpers-getBoxQuads.js on e10s. r=pbro MozReview-Commit-ID: 8nA5FVLLm9H
devtools/client/shared/test/browser.ini
devtools/client/shared/test/browser_layoutHelpers-getBoxQuads.js
--- a/devtools/client/shared/test/browser.ini
+++ b/devtools/client/shared/test/browser.ini
@@ -149,17 +149,16 @@ skip-if = e10s # Bug 1221911, bug 122228
 [browser_inplace-editor_autocomplete_02.js]
 [browser_inplace-editor_autocomplete_offset.js]
 [browser_inplace-editor_maxwidth.js]
 [browser_keycodes.js]
 [browser_key_shortcuts.js]
 [browser_layoutHelpers.js]
 skip-if = e10s # Layouthelpers test should not run in a content page.
 [browser_layoutHelpers-getBoxQuads.js]
-skip-if = e10s # Layouthelpers test should not run in a content page.
 [browser_num-l10n.js]
 [browser_options-view-01.js]
 [browser_outputparser.js]
 skip-if = e10s # Test intermittently fails with e10s. Bug 1124162.
 [browser_poller.js]
 [browser_prefs-01.js]
 [browser_prefs-02.js]
 [browser_require_raw.js]
--- a/devtools/client/shared/test/browser_layoutHelpers-getBoxQuads.js
+++ b/devtools/client/shared/test/browser_layoutHelpers-getBoxQuads.js
@@ -1,219 +1,256 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests getAdjustedQuads works properly in a variety of use cases including
 // iframes, scroll and zoom
 
 "use strict";
 
-const {getAdjustedQuads} = require("devtools/shared/layout/utils");
-
 const TEST_URI = TEST_URI_ROOT + "doc_layoutHelpers-getBoxQuads.html";
 
-add_task(function* () {
-  let tab = yield addTab(TEST_URI);
-  let doc = tab.linkedBrowser.contentDocument;
-
-  ok(typeof getAdjustedQuads === "function", "getAdjustedQuads is defined");
+add_task(async function () {
+  let tab = await addTab(TEST_URI);
 
   info("Running tests");
 
-  returnsTheRightDataStructure(doc);
-  isEmptyForMissingNode(doc);
-  isEmptyForHiddenNodes(doc);
-  defaultsToBorderBoxIfNoneProvided(doc);
-  returnsLikeGetBoxQuadsInSimpleCase(doc);
-  takesIframesOffsetsIntoAccount(doc);
-  takesScrollingIntoAccount(doc);
-  yield takesZoomIntoAccount(doc);
-  returnsMultipleItemsForWrappingInlineElements(doc);
+  // `FullZoom` isn't available from the ContentTask. This code is defined by browser
+  // frontend and runs in the parent process. Here, we use the message manager
+  // to allow the Content Task to call this zoom helper whenever it needs to.
+  let mm = tab.linkedBrowser.messageManager;
+  mm.addMessageListener("devtools-test:command", async function ({ data }) {
+    switch (data) {
+      case "zoom-enlarge":
+        window.FullZoom.enlarge();
+        break;
+      case "zoom-reset":
+        await window.FullZoom.reset();
+        break;
+      case "zoom-reduce":
+        window.FullZoom.reduce();
+        break;
+    }
+    mm.sendAsyncMessage("devtools-test:done");
+  });
+
+  await ContentTask.spawn(tab.linkedBrowser, null, async function () {
+    // This function allows the Content Task to easily call `FullZoom` API via
+    // the message manager.
+    function sendCommand(cmd) {
+      let onDone = new Promise(done => {
+        addMessageListener("devtools-test:done", function listener() {
+          removeMessageListener("devtools-test:done", listener);
+          done();
+        });
+      });
+      sendAsyncMessage("devtools-test:command", cmd);
+      return onDone;
+    }
+
+    const doc = content.document;
+
+    const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
+    const {getAdjustedQuads} = require("devtools/shared/layout/utils");
+
+    ok(typeof getAdjustedQuads === "function", "getAdjustedQuads is defined");
+
+    returnsTheRightDataStructure();
+    isEmptyForMissingNode();
+    isEmptyForHiddenNodes();
+    defaultsToBorderBoxIfNoneProvided();
+    returnsLikeGetBoxQuadsInSimpleCase();
+    takesIframesOffsetsIntoAccount();
+    takesScrollingIntoAccount();
+    await takesZoomIntoAccount();
+    returnsMultipleItemsForWrappingInlineElements();
+
+    function returnsTheRightDataStructure() {
+      info("Checks that the returned data contains bounds and 4 points");
+
+      let node = doc.querySelector("body");
+      let [res] = getAdjustedQuads(doc.defaultView, node, "content");
+
+      ok("bounds" in res, "The returned data has a bounds property");
+      ok("p1" in res, "The returned data has a p1 property");
+      ok("p2" in res, "The returned data has a p2 property");
+      ok("p3" in res, "The returned data has a p3 property");
+      ok("p4" in res, "The returned data has a p4 property");
+
+      for (let boundProp of
+        ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
+        ok(boundProp in res.bounds, "The bounds has a " + boundProp + " property");
+      }
+
+      for (let point of ["p1", "p2", "p3", "p4"]) {
+        for (let pointProp of ["x", "y", "z", "w"]) {
+          ok(pointProp in res[point], point + " has a " + pointProp + " property");
+        }
+      }
+    }
+
+    function isEmptyForMissingNode() {
+      info("Checks that null is returned for invalid nodes");
+
+      for (let input of [null, undefined, "", 0]) {
+        is(getAdjustedQuads(doc.defaultView, input).length, 0,
+          "A 0-length array is returned for input " + input);
+      }
+    }
+
+    function isEmptyForHiddenNodes() {
+      info("Checks that null is returned for nodes that aren't rendered");
+
+      let style = doc.querySelector("#styles");
+      is(getAdjustedQuads(doc.defaultView, style).length, 0,
+        "null is returned for a <style> node");
+
+      let hidden = doc.querySelector("#hidden-node");
+      is(getAdjustedQuads(doc.defaultView, hidden).length, 0,
+        "null is returned for a hidden node");
+    }
+
+    function defaultsToBorderBoxIfNoneProvided() {
+      info("Checks that if no boxtype is passed, then border is the default one");
+
+      let node = doc.querySelector("#simple-node-with-margin-padding-border");
+      let [withBoxType] = getAdjustedQuads(doc.defaultView, node, "border");
+      let [withoutBoxType] = getAdjustedQuads(doc.defaultView, node);
+
+      for (let boundProp of
+        ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
+        is(withBoxType.bounds[boundProp], withoutBoxType.bounds[boundProp],
+          boundProp + " bound is equal with or without the border box type");
+      }
+
+      for (let point of ["p1", "p2", "p3", "p4"]) {
+        for (let pointProp of ["x", "y", "z", "w"]) {
+          is(withBoxType[point][pointProp], withoutBoxType[point][pointProp],
+            point + "." + pointProp +
+            " is equal with or without the border box type");
+        }
+      }
+    }
+
+    function returnsLikeGetBoxQuadsInSimpleCase() {
+      info("Checks that for an element in the main frame, without scroll nor zoom" +
+        "that the returned value is similar to the returned value of getBoxQuads");
+
+      let node = doc.querySelector("#simple-node-with-margin-padding-border");
+
+      for (let region of ["content", "padding", "border", "margin"]) {
+        let expected = node.getBoxQuads({
+          box: region
+        })[0];
+        let [actual] = getAdjustedQuads(doc.defaultView, node, region);
+
+        for (let boundProp of
+          ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
+          is(actual.bounds[boundProp], expected.bounds[boundProp],
+            boundProp + " bound is equal to the one returned by getBoxQuads for " +
+            region + " box");
+        }
+
+        for (let point of ["p1", "p2", "p3", "p4"]) {
+          for (let pointProp of ["x", "y", "z", "w"]) {
+            is(actual[point][pointProp], expected[point][pointProp],
+              point + "." + pointProp +
+              " is equal to the one returned by getBoxQuads for " + region + " box");
+          }
+        }
+      }
+    }
+
+    function takesIframesOffsetsIntoAccount() {
+      info("Checks that the quad returned for a node inside iframes that have " +
+        "margins takes those offsets into account");
+
+      let rootIframe = doc.querySelector("iframe");
+      let subIframe = rootIframe.contentDocument.querySelector("iframe");
+      let innerNode = subIframe.contentDocument.querySelector("#inner-node");
+
+      let [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
+
+      // rootIframe margin + subIframe margin + node margin + node border + node padding
+      let p1x = 10 + 10 + 10 + 10 + 10;
+      is(quad.p1.x, p1x, "The inner node's p1 x position is correct");
+
+      // Same as p1x + the inner node width
+      let p2x = p1x + 100;
+      is(quad.p2.x, p2x, "The inner node's p2 x position is correct");
+    }
+
+    function takesScrollingIntoAccount() {
+      info("Checks that the quad returned for a node inside multiple scrolled " +
+        "containers takes the scroll values into account");
+
+      // For info, the container being tested here is absolutely positioned at 0 0
+      // to simplify asserting the coordinates
+
+      info("Scroll the container nodes down");
+      let scrolledNode = doc.querySelector("#scrolled-node");
+      scrolledNode.scrollTop = 100;
+      let subScrolledNode = doc.querySelector("#sub-scrolled-node");
+      subScrolledNode.scrollTop = 200;
+      let innerNode = doc.querySelector("#inner-scrolled-node");
+
+      let [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
+      is(quad.p1.x, 0, "p1.x of the scrolled node is correct after scrolling down");
+      is(quad.p1.y, -300, "p1.y of the scrolled node is correct after scrolling down");
+
+      info("Scrolling back up");
+      scrolledNode.scrollTop = 0;
+      subScrolledNode.scrollTop = 0;
+
+      [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
+      is(quad.p1.x, 0, "p1.x of the scrolled node is correct after scrolling up");
+      is(quad.p1.y, 0, "p1.y of the scrolled node is correct after scrolling up");
+    }
+
+    async function takesZoomIntoAccount() {
+      info("Checks that if the page is zoomed in/out, the quad returned is correct");
+
+      // Hard-coding coordinates in this zoom test is a bad idea as it can vary
+      // depending on the platform, so we simply test that zooming in produces a
+      // bigger quad and zooming out produces a smaller quad
+
+      let node = doc.querySelector("#simple-node-with-margin-padding-border");
+      let [defaultQuad] = getAdjustedQuads(doc.defaultView, node);
+
+      info("Zoom in");
+      await sendCommand("zoom-enlarge");
+      let [zoomedInQuad] = getAdjustedQuads(doc.defaultView, node);
+
+      ok(zoomedInQuad.bounds.width > defaultQuad.bounds.width,
+        "The zoomed in quad is bigger than the default one");
+      ok(zoomedInQuad.bounds.height > defaultQuad.bounds.height,
+        "The zoomed in quad is bigger than the default one");
+
+      info("Zoom out");
+      await sendCommand("zoom-reset");
+      await sendCommand("zoom-reduce");
+
+      let [zoomedOutQuad] = getAdjustedQuads(doc.defaultView, node);
+
+      ok(zoomedOutQuad.bounds.width < defaultQuad.bounds.width,
+        "The zoomed out quad is smaller than the default one");
+      ok(zoomedOutQuad.bounds.height < defaultQuad.bounds.height,
+        "The zoomed out quad is smaller than the default one");
+
+      await sendCommand("zoom-reset");
+    }
+
+    function returnsMultipleItemsForWrappingInlineElements() {
+      info("Checks that several quads are returned " +
+           "for inline elements that span line-breaks");
+
+      let node = doc.querySelector("#inline");
+      let quads = getAdjustedQuads(doc.defaultView, node, "content");
+      // At least 3 because of the 2 <br />, maybe more depending on the window size.
+      ok(quads.length >= 3, "Multiple quads were returned");
+
+      is(quads.length, node.getBoxQuads().length,
+        "The same number of boxes as getBoxQuads was returned");
+    }
+  });
 
   gBrowser.removeCurrentTab();
 });
-
-function returnsTheRightDataStructure(doc) {
-  info("Checks that the returned data contains bounds and 4 points");
-
-  let node = doc.querySelector("body");
-  let [res] = getAdjustedQuads(doc.defaultView, node, "content");
-
-  ok("bounds" in res, "The returned data has a bounds property");
-  ok("p1" in res, "The returned data has a p1 property");
-  ok("p2" in res, "The returned data has a p2 property");
-  ok("p3" in res, "The returned data has a p3 property");
-  ok("p4" in res, "The returned data has a p4 property");
-
-  for (let boundProp of
-    ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
-    ok(boundProp in res.bounds, "The bounds has a " + boundProp + " property");
-  }
-
-  for (let point of ["p1", "p2", "p3", "p4"]) {
-    for (let pointProp of ["x", "y", "z", "w"]) {
-      ok(pointProp in res[point], point + " has a " + pointProp + " property");
-    }
-  }
-}
-
-function isEmptyForMissingNode(doc) {
-  info("Checks that null is returned for invalid nodes");
-
-  for (let input of [null, undefined, "", 0]) {
-    is(getAdjustedQuads(doc.defaultView, input).length, 0,
-      "A 0-length array is returned for input " + input);
-  }
-}
-
-function isEmptyForHiddenNodes(doc) {
-  info("Checks that null is returned for nodes that aren't rendered");
-
-  let style = doc.querySelector("#styles");
-  is(getAdjustedQuads(doc.defaultView, style).length, 0,
-    "null is returned for a <style> node");
-
-  let hidden = doc.querySelector("#hidden-node");
-  is(getAdjustedQuads(doc.defaultView, hidden).length, 0,
-    "null is returned for a hidden node");
-}
-
-function defaultsToBorderBoxIfNoneProvided(doc) {
-  info("Checks that if no boxtype is passed, then border is the default one");
-
-  let node = doc.querySelector("#simple-node-with-margin-padding-border");
-  let [withBoxType] = getAdjustedQuads(doc.defaultView, node, "border");
-  let [withoutBoxType] = getAdjustedQuads(doc.defaultView, node);
-
-  for (let boundProp of
-    ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
-    is(withBoxType.bounds[boundProp], withoutBoxType.bounds[boundProp],
-      boundProp + " bound is equal with or without the border box type");
-  }
-
-  for (let point of ["p1", "p2", "p3", "p4"]) {
-    for (let pointProp of ["x", "y", "z", "w"]) {
-      is(withBoxType[point][pointProp], withoutBoxType[point][pointProp],
-        point + "." + pointProp +
-        " is equal with or without the border box type");
-    }
-  }
-}
-
-function returnsLikeGetBoxQuadsInSimpleCase(doc) {
-  info("Checks that for an element in the main frame, without scroll nor zoom" +
-    "that the returned value is similar to the returned value of getBoxQuads");
-
-  let node = doc.querySelector("#simple-node-with-margin-padding-border");
-
-  for (let region of ["content", "padding", "border", "margin"]) {
-    let expected = node.getBoxQuads({
-      box: region
-    })[0];
-    let [actual] = getAdjustedQuads(doc.defaultView, node, region);
-
-    for (let boundProp of
-      ["bottom", "top", "right", "left", "width", "height", "x", "y"]) {
-      is(actual.bounds[boundProp], expected.bounds[boundProp],
-        boundProp + " bound is equal to the one returned by getBoxQuads for " +
-        region + " box");
-    }
-
-    for (let point of ["p1", "p2", "p3", "p4"]) {
-      for (let pointProp of ["x", "y", "z", "w"]) {
-        is(actual[point][pointProp], expected[point][pointProp],
-          point + "." + pointProp +
-          " is equal to the one returned by getBoxQuads for " + region + " box");
-      }
-    }
-  }
-}
-
-function takesIframesOffsetsIntoAccount(doc) {
-  info("Checks that the quad returned for a node inside iframes that have " +
-    "margins takes those offsets into account");
-
-  let rootIframe = doc.querySelector("iframe");
-  let subIframe = rootIframe.contentDocument.querySelector("iframe");
-  let innerNode = subIframe.contentDocument.querySelector("#inner-node");
-
-  let [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
-
-  // rootIframe margin + subIframe margin + node margin + node border + node padding
-  let p1x = 10 + 10 + 10 + 10 + 10;
-  is(quad.p1.x, p1x, "The inner node's p1 x position is correct");
-
-  // Same as p1x + the inner node width
-  let p2x = p1x + 100;
-  is(quad.p2.x, p2x, "The inner node's p2 x position is correct");
-}
-
-function takesScrollingIntoAccount(doc) {
-  info("Checks that the quad returned for a node inside multiple scrolled " +
-    "containers takes the scroll values into account");
-
-  // For info, the container being tested here is absolutely positioned at 0 0
-  // to simplify asserting the coordinates
-
-  info("Scroll the container nodes down");
-  let scrolledNode = doc.querySelector("#scrolled-node");
-  scrolledNode.scrollTop = 100;
-  let subScrolledNode = doc.querySelector("#sub-scrolled-node");
-  subScrolledNode.scrollTop = 200;
-  let innerNode = doc.querySelector("#inner-scrolled-node");
-
-  let [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
-  is(quad.p1.x, 0, "p1.x of the scrolled node is correct after scrolling down");
-  is(quad.p1.y, -300, "p1.y of the scrolled node is correct after scrolling down");
-
-  info("Scrolling back up");
-  scrolledNode.scrollTop = 0;
-  subScrolledNode.scrollTop = 0;
-
-  [quad] = getAdjustedQuads(doc.defaultView, innerNode, "content");
-  is(quad.p1.x, 0, "p1.x of the scrolled node is correct after scrolling up");
-  is(quad.p1.y, 0, "p1.y of the scrolled node is correct after scrolling up");
-}
-
-function* takesZoomIntoAccount(doc) {
-  info("Checks that if the page is zoomed in/out, the quad returned is correct");
-
-  // Hard-coding coordinates in this zoom test is a bad idea as it can vary
-  // depending on the platform, so we simply test that zooming in produces a
-  // bigger quad and zooming out produces a smaller quad
-
-  let node = doc.querySelector("#simple-node-with-margin-padding-border");
-  let [defaultQuad] = getAdjustedQuads(doc.defaultView, node);
-
-  info("Zoom in");
-  window.FullZoom.enlarge();
-  let [zoomedInQuad] = getAdjustedQuads(doc.defaultView, node);
-
-  ok(zoomedInQuad.bounds.width > defaultQuad.bounds.width,
-    "The zoomed in quad is bigger than the default one");
-  ok(zoomedInQuad.bounds.height > defaultQuad.bounds.height,
-    "The zoomed in quad is bigger than the default one");
-
-  info("Zoom out");
-  yield window.FullZoom.reset();
-  window.FullZoom.reduce();
-  let [zoomedOutQuad] = getAdjustedQuads(doc.defaultView, node);
-
-  ok(zoomedOutQuad.bounds.width < defaultQuad.bounds.width,
-    "The zoomed out quad is smaller than the default one");
-  ok(zoomedOutQuad.bounds.height < defaultQuad.bounds.height,
-    "The zoomed out quad is smaller than the default one");
-
-  yield window.FullZoom.reset();
-}
-
-function returnsMultipleItemsForWrappingInlineElements(doc) {
-  info("Checks that several quads are returned " +
-       "for inline elements that span line-breaks");
-
-  let node = doc.querySelector("#inline");
-  let quads = getAdjustedQuads(doc.defaultView, node, "content");
-  // At least 3 because of the 2 <br />, maybe more depending on the window size.
-  ok(quads.length >= 3, "Multiple quads were returned");
-
-  is(quads.length, node.getBoxQuads().length,
-    "The same number of boxes as getBoxQuads was returned");
-}