Bug 1373134 - Unit tests. r?pbro
MozReview-Commit-ID: KF7hfGf8XmC
--- a/devtools/client/inspector/grids/test/browser.ini
+++ b/devtools/client/inspector/grids/test/browser.ini
@@ -24,13 +24,14 @@ support-files =
[browser_grids_grid-list-on-iframe-reloaded.js]
[browser_grids_grid-list-on-mutation-element-added.js]
[browser_grids_grid-list-on-mutation-element-removed.js]
[browser_grids_grid-list-toggle-multiple-grids.js]
[browser_grids_grid-list-toggle-single-grid.js]
[browser_grids_grid-outline-cannot-show-outline.js]
[browser_grids_grid-outline-highlight-area.js]
[browser_grids_grid-outline-highlight-cell.js]
+[browser_grids_grid-outline-scroll-into-view-of-grid.js]
[browser_grids_grid-outline-selected-grid.js]
[browser_grids_grid-outline-updates-on-grid-change.js]
[browser_grids_highlighter-setting-rules-grid-toggle.js]
[browser_grids_number-of-css-grids-telemetry.js]
[browser_grids_restored-after-reload.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-scroll-into-view-of-grid.js
@@ -0,0 +1,167 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that a grid is scrolled into view when it is toggled or when the
+// grid outline is hovered over.
+
+const TEST_URI = `
+ <style>
+ .container {
+ display: grid;
+ grid-template-columns: repeat(2, 20vw);
+ grid-template-rows: repeat(10, 20vh);
+ }
+ .container2 {
+ display: grid;
+ grid-template-columns: repeat(2, 20vw);
+ grid-template-rows: repeat(20, 20vh);
+ }
+ </style>
+ <div id="grid1" class="container">
+ <div>Grid 1</div>
+ </div>
+ <div id="grid2" class="container2">
+ <div>Grid 2</div>
+ </div>
+ <div id="grid3" class="container">
+ <div>Grid 3</div>
+ </div>
+`;
+
+const SCROLL_INTO_VIEW_OF_GRID_PREF = "devtools.gridinspector.scrollIntoViewOfGridNode";
+const AUTOSCROLL_TO_GRID_CELLS = "devtools.gridinspector.autoScrollToGridCells";
+
+add_task(function* () {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+
+ let { inspector, gridInspector, testActor } = yield openLayoutView();
+ let { document: doc } = gridInspector;
+
+ info("Setting 'scrollIntoViewOfGridNode' pref to true.");
+ Services.prefs.setBoolPref(SCROLL_INTO_VIEW_OF_GRID_PREF, true);
+ ok(Services.prefs.getBoolPref(SCROLL_INTO_VIEW_OF_GRID_PREF),
+ "Scrolling into view of grid is true.");
+
+ let gridList = doc.getElementById("grid-list");
+ let { store, highlighters } = inspector;
+
+ info("Select the #grid3 node to scroll to it.");
+ yield selectGrid(2, gridList, highlighters, store);
+
+ info("#grid1 should be scrolled away from and #grid3 should be in view.");
+ yield checkElementIsInViewport("#grid1", false, testActor);
+ yield checkElementIsInViewport("#grid3", true, testActor);
+
+ info("Select the #grid2 node to scroll to it.");
+ yield selectGrid(1, gridList, highlighters, store);
+
+ info("#grid3 should be scrolled away from and #grid2 should be in view.");
+ yield checkElementIsInViewport("#grid3", false, testActor);
+ yield checkElementIsInViewport("#grid2", true, testActor);
+
+ let checkbox = doc.getElementById("grid-setting-scroll-to-grid-cell");
+ ok(checkbox, "'Automatically scroll to grid cell' checkbox label "
+ + "should be shown");
+
+ info("Checking the initial state of auto scrolling grid cell view pref setting.");
+ ok(!Services.prefs.getBoolPref(AUTOSCROLL_TO_GRID_CELLS),
+ "'Automatically scroll to grid cells' pref is off by default.");
+
+ info("Toggling ON the 'Automatically scroll to grid cells' setting.");
+ let onCheckboxChange = waitUntilState(store, state =>
+ state.highlighterSettings.scrollToGridCell);
+ checkbox.click();
+ yield onCheckboxChange;
+
+ ok(Services.prefs.getBoolPref(AUTOSCROLL_TO_GRID_CELLS),
+ "'Automatically scroll to grid cells' pref is on.");
+
+ info("Hovering over last grid cell in the grid outline for grid#2.");
+ let outline = yield doc.getElementById("grid-cell-group");
+ let lastCellIndex = outline.children.length - 1;
+ let gridCell = outline.children[lastCellIndex];
+
+ gridCell.scrollIntoView();
+
+ let onCellHighlight = highlighters.once("grid-highlighter-shown");
+ EventUtils.synthesizeMouse(gridCell, 5, 5, {type: "mouseover"}, doc.defaultView);
+ yield onCellHighlight;
+
+ info("#grid3 should be in view.");
+ yield checkElementIsInViewport("#grid3", true, testActor);
+
+ info("Toggling OFF the 'Automatically scroll to grid cells' setting.");
+ onCheckboxChange = waitUntilState(store, state =>
+ !state.highlighterSettings.scrollToGridCell);
+ checkbox.click();
+ yield onCheckboxChange;
+
+ ok(!Services.prefs.getBoolPref(AUTOSCROLL_TO_GRID_CELLS),
+ "'Automatically scroll to grid cells' pref is off.");
+
+ info("Hovering over last grid cell in the grid outline for grid#1.");
+ yield selectGrid(0, gridList, highlighters, store);
+ outline = yield doc.getElementById("grid-cell-group");
+ lastCellIndex = outline.children.length - 1;
+ gridCell = outline.children[lastCellIndex];
+ let onGridOutlineRendered = waitForDOM(doc, ".grid-outline-cell", 20);
+
+ yield gridCell.scrollIntoView();
+
+ info("Press down ctrlKey as mouse hovers over outline.");
+ EventUtils.synthesizeMouse(gridCell, 5, 5, { type: "mousemove", ctrlKey: true },
+ doc.defaultView);
+
+ yield onCellHighlight;
+ yield onGridOutlineRendered;
+
+ info("#grid2 should be in view.");
+ yield checkElementIsInViewport("#grid2", true, testActor);
+
+ info("Clearing 'scrollIntoViewOfGridNode' pref");
+ Services.prefs.clearUserPref(SCROLL_INTO_VIEW_OF_GRID_PREF);
+ ok(!Services.prefs.getBoolPref(SCROLL_INTO_VIEW_OF_GRID_PREF),
+ "Scrolling into view of grid is false by default.");
+});
+
+/**
+ * Verify that the element matching the provided selector is either in or out
+ * of the viewport, depending on the provided "expected" argument.
+ * Returns a promise that will resolve when the test has been performed.
+ *
+ * @param {String} selector
+ * css selector for the element to test
+ * @param {Boolean} expected
+ * true if the element is expected to be in the viewport, false otherwise
+ * @param {TestActor} testActor
+ * current test actor
+ * @return {Promise} promise
+ */
+function* checkElementIsInViewport(selector, expected, testActor) {
+ let isInViewport = yield testActor.isInViewport(selector);
+ is(isInViewport, expected, selector + " in the viewport: expected to be " + expected);
+}
+
+/**
+ * Simulate selecting a grid from the grid list.
+ *
+ * @param {Number} gridIndex
+ * Index of grid node to select.
+ * @param {Object} gridList
+ * List of grid items.
+ * @param {Highlighters} highlighters
+ * Grid inspector highlighters.
+ * @param {Store} store
+ * Store for the grid inspector state.
+ */
+function* selectGrid(gridIndex, gridList, highlighters, store) {
+ let gridCheckBox = gridList.children[gridIndex].querySelector("input");
+ let onHighlighterShown = highlighters.once("grid-highlighter-shown");
+ let onGridCheckboxChange = waitUntilState(store, state =>
+ state.grids[gridIndex].highlighted);
+ gridCheckBox.click();
+ yield onHighlighterShown;
+ yield onGridCheckboxChange;
+}
--- a/devtools/client/inspector/grids/test/head.js
+++ b/devtools/client/inspector/grids/test/head.js
@@ -12,16 +12,17 @@ Services.scriptloader.loadSubScript(
this);
// Load the shared Redux helpers into this compartment.
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-redux-head.js",
this);
Services.prefs.setBoolPref("devtools.promote.layoutview.showPromoteBar", false);
+Services.prefs.setBoolPref("devtools.gridinspector.scrollIntoViewOfGridNode", true);
Services.prefs.setIntPref("devtools.toolbox.footer.height", 350);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.promote.layoutview.showPromoteBar");
Services.prefs.clearUserPref("devtools.toolbox.footer.height");
});
const HIGHLIGHTER_TYPE = "CssGridHighlighter";
--- a/devtools/client/shared/test/test-actor.js
+++ b/devtools/client/shared/test/test-actor.js
@@ -292,16 +292,24 @@ var testSpec = protocol.generateActorSpe
value: RetVal("json")
}
},
getWindowDimensions: {
request: {},
response: {
value: RetVal("json")
}
+ },
+ isInViewport: {
+ request: {
+ selector: Arg(0, "string")
+ },
+ response: {
+ value: RetVal("boolean")
+ }
}
}
});
var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
initialize: function (conn, tabActor, options) {
this.conn = conn;
this.tabActor = tabActor;
@@ -795,17 +803,34 @@ var TestActor = exports.TestActor = prot
/**
* Returns the window's dimensions for the `window` given.
*
* @return {Object} An object with `width` and `height` properties, representing the
* number of pixels for the document's size.
*/
getWindowDimensions: function () {
return getWindowDimensions(this.content);
- }
+ },
+
+ /**
+ * Verifies whether or not an element matching the specified selector is visible in the
+ * viewport.
+ *
+ * @param {String} selector
+ * CSS selector for the element to test
+ *
+ * @return {Boolean}
+ * Whether or not the element is visible in the viewport.
+ */
+ isInViewport: function (selector) {
+ const rect = this.getBoundingClientRect(selector);
+
+ return rect.bottom >= 0 && rect.right >= 0 &&
+ rect.top <= this.content.innerHeight && rect.left <= this.content.innerWidth;
+ },
});
var TestActorFront = exports.TestActorFront = protocol.FrontClassWithSpec(testSpec, {
initialize: function (client, { testActor }, toolbox) {
protocol.Front.prototype.initialize.call(this, client, { actor: testActor });
this.manage(this);
this.toolbox = toolbox;
},