Bug 1287209: Make popup tests compatible with remote browsers. r=aswan

MozReview-Commit-ID: 79Xa3j5Kzov
This commit is contained in:
Kris Maglione
2016-10-19 15:13:25 -07:00
parent c0448e9939
commit d2dfc382dc
6 changed files with 167 additions and 135 deletions

View File

@@ -345,6 +345,12 @@ class PanelPopup extends BasePopup {
this.contentReady.then(() => {
panel.openPopup(imageNode, "bottomcenter topright", 0, 0, false, false);
let event = new this.window.CustomEvent("WebExtPopupLoaded", {
bubbles: true,
detail: {extension},
});
this.browser.dispatchEvent(event);
});
}
@@ -458,6 +464,12 @@ class ViewPopup extends BasePopup {
this.tempPanel.remove();
this.tempPanel = null;
let event = new this.window.CustomEvent("WebExtPopupLoaded", {
bubbles: true,
detail: {extension: this.extension},
});
this.browser.dispatchEvent(event);
return true;
}.bind(this));
}

View File

@@ -8,17 +8,6 @@ function* openPanel(extension, win = window) {
return yield awaitExtensionPanel(extension, win);
}
function* awaitResize(browser) {
// Debouncing code makes this a bit racy.
// Try to skip the first, early resize, and catch the resize event we're
// looking for, but don't wait longer than a few seconds.
return Promise.race([
BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized", event => event.detail === "delayed"),
new Promise(resolve => setTimeout(resolve, 5000)),
]);
}
add_task(function* testBrowserActionPopupResize() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
@@ -29,7 +18,7 @@ add_task(function* testBrowserActionPopupResize() {
},
files: {
"popup.html": '<html><head><meta charset="utf-8"></head></html>',
"popup.html": '<!DOCTYPE html><html><head><meta charset="utf-8"></head></html>',
},
});
@@ -38,24 +27,26 @@ add_task(function* testBrowserActionPopupResize() {
clickBrowserAction(extension, window);
let browser = yield openPanel(extension);
let panelWindow = browser.contentWindow;
let panelBody = panelWindow.document.body;
function checkSize(expected) {
is(panelWindow.innerHeight, expected, `Panel window should be ${expected}px tall`);
is(panelBody.clientHeight, panelBody.scrollHeight,
function* checkSize(expected) {
let dims = yield promiseContentDimensions(browser);
is(dims.window.innerHeight, expected, `Panel window should be ${expected}px tall`);
is(dims.body.clientHeight, dims.body.scrollHeight,
"Panel body should be tall enough to fit its contents");
// Tolerate if it is 1px too wide, as that may happen with the current resizing method.
ok(Math.abs(panelWindow.innerWidth - expected) <= 1, `Panel window should be ${expected}px wide`);
is(panelBody.clientWidth, panelBody.scrollWidth,
ok(Math.abs(dims.window.innerWidth - expected) <= 1, `Panel window should be ${expected}px wide`);
is(dims.body.clientWidth, dims.body.scrollWidth,
"Panel body should be wide enough to fit its contents");
}
/* eslint-disable mozilla/no-cpows-in-tests */
function setSize(size) {
panelBody.style.height = `${size}px`;
panelBody.style.width = `${size}px`;
content.document.body.style.height = `${size}px`;
content.document.body.style.width = `${size}px`;
}
/* eslint-enable mozilla/no-cpows-in-tests */
let sizes = [
200,
@@ -64,9 +55,8 @@ add_task(function* testBrowserActionPopupResize() {
];
for (let size of sizes) {
setSize(size);
yield awaitResize(browser);
checkSize(size);
yield alterContent(browser, setSize, size);
yield checkSize(size);
}
yield closeBrowserAction(extension);
@@ -121,27 +111,32 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
yield extension.startup();
/* eslint-disable mozilla/no-cpows-in-tests */
if (arrowSide == "top") {
// Test the standalone panel for a toolbar button.
let browser = yield openPanel(extension, browserWin);
let win = browser.contentWindow;
let body = win.document.body;
let isStandards = win.document.compatMode != "BackCompat";
is(isStandards, standardsMode, "Document has the expected compat mode");
let dims = yield promiseContentDimensions(browser);
let {innerWidth, innerHeight} = win;
is(dims.isStandards, standardsMode, "Document has the expected compat mode");
body.classList.add("bigger");
yield awaitResize(browser);
let {innerWidth, innerHeight} = dims.window;
dims = yield alterContent(browser, () => {
content.document.body.classList.add("bigger");
});
let win = dims.window;
is(win.innerHeight, innerHeight, "Window height should not change");
ok(win.innerWidth > innerWidth, `Window width should increase (${win.innerWidth} > ${innerWidth})`);
body.classList.remove("bigger");
yield awaitResize(browser);
dims = yield alterContent(browser, () => {
content.document.body.classList.remove("bigger");
});
win = dims.window;
is(win.innerHeight, innerHeight, "Window height should not change");
// The getContentSize calculation is not always reliable to single-pixel
@@ -158,8 +153,6 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
CustomizableUI.addWidgetToArea(widget.id, CustomizableUI.AREA_PANEL);
let browser = yield openPanel(extension, browserWin);
let win = browser.contentWindow;
let body = win.document.body;
let {panel} = browserWin.PanelUI;
let origPanelRect = panel.getBoundingClientRect();
@@ -173,7 +166,7 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
ok(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
ok(panelRect.bottom >= origPanelRect.bottom, `Panel has not shrunk from original size (${panelRect.bottom} >= ${origPanelRect.bottom})`);
let screenBottom = browserWin.screen.availTop + win.screen.availHeight;
let screenBottom = browserWin.screen.availTop + browserWin.screen.availHeight;
let panelBottom = browserWin.mozInnerScreenY + panelRect.bottom;
ok(panelBottom <= screenBottom, `Bottom of popup should be on-screen. (${panelBottom} <= ${screenBottom})`);
} else {
@@ -185,28 +178,33 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
}
};
let isStandards = win.document.compatMode != "BackCompat";
is(isStandards, standardsMode, "Document has the expected compat mode");
// Wait long enough to make sure the initial resize debouncing timer has
// expired.
yield new Promise(resolve => setTimeout(resolve, 100));
let dims = yield promiseContentDimensions(browser);
is(dims.isStandards, standardsMode, "Document has the expected compat mode");
// If the browser's preferred height is smaller than the initial height of the
// panel, then it will still take up the full available vertical space. Even
// so, we need to check that we've gotten the preferred height calculation
// correct, so check that explicitly.
let getHeight = () => parseFloat(browser.style.height);
let {innerWidth, innerHeight} = win;
let {innerWidth, innerHeight} = dims.window;
let height = getHeight();
let setClass = className => {
content.document.body.className = className;
};
info("Increase body children's width. " +
"Expect them to wrap, and the frame to grow vertically rather than widen.");
body.className = "big";
yield awaitResize(browser);
dims = yield alterContent(browser, setClass, "big");
let win = dims.window;
ok(getHeight() > height, `Browser height should increase (${getHeight()} > ${height})`);
@@ -219,8 +217,9 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
info("Increase body children's width and height. " +
"Expect them to wrap, and the frame to grow vertically rather than widen.");
body.className = "bigger";
yield awaitResize(browser);
dims = yield alterContent(browser, setClass, "bigger");
win = dims.window;
ok(getHeight() > height, `Browser height should increase (${getHeight()} > ${height})`);
@@ -233,8 +232,9 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
info("Increase body height beyond the height of the screen. " +
"Expect the panel to grow to accommodate, but not larger than the height of the screen.");
body.className = "huge";
yield awaitResize(browser);
dims = yield alterContent(browser, setClass, "huge");
win = dims.window;
ok(getHeight() > height, `Browser height should increase (${getHeight()} > ${height})`);
@@ -247,8 +247,8 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
info("Restore original styling. Expect original dimensions.");
body.className = "";
yield awaitResize(browser);
dims = yield alterContent(browser, setClass, "");
win = dims.window;
is(getHeight(), height, "Browser height should return to its original value");

View File

@@ -2,18 +2,6 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* awaitResize(browser) {
// Debouncing code makes this a bit racy.
// Try to skip the first, early resize, and catch the resize event we're
// looking for, but don't wait longer than a few seconds.
return Promise.race([
BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")
.then(() => BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")),
new Promise(resolve => setTimeout(resolve, 5000)),
]);
}
add_task(function* testPageActionPopupResize() {
let browser;
@@ -47,31 +35,29 @@ add_task(function* testPageActionPopupResize() {
browser = yield awaitExtensionPanel(extension);
let panelWindow = browser.contentWindow;
let panelDocument = panelWindow.document;
let panelBody = panelDocument.body.firstChild;
let body = panelDocument.body;
let root = panelDocument.documentElement;
function* checkSize(expected) {
let dims = yield promiseContentDimensions(browser);
let {body, root} = dims;
function checkSize(expected) {
is(panelWindow.innerHeight, expected, `Panel window should be ${expected}px tall`);
is(dims.window.innerHeight, expected, `Panel window should be ${expected}px tall`);
is(body.clientHeight, body.scrollHeight,
"Panel body should be tall enough to fit its contents");
is(root.clientHeight, root.scrollHeight,
"Panel root should be tall enough to fit its contents");
// Tolerate if it is 1px too wide, as that may happen with the current resizing method.
ok(Math.abs(panelWindow.innerWidth - expected) <= 1, `Panel window should be ${expected}px wide`);
ok(Math.abs(dims.window.innerWidth - expected) <= 1, `Panel window should be ${expected}px wide`);
is(body.clientWidth, body.scrollWidth,
"Panel body should be wide enough to fit its contents");
}
/* eslint-disable mozilla/no-cpows-in-tests */
function setSize(size) {
panelBody.style.height = `${size}px`;
panelBody.style.width = `${size}px`;
return BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized");
let elem = content.document.body.firstChild;
elem.style.height = `${size}px`;
elem.style.width = `${size}px`;
}
/* eslint-enable mozilla/no-cpows-in-tests */
let sizes = [
200,
@@ -80,22 +66,25 @@ add_task(function* testPageActionPopupResize() {
];
for (let size of sizes) {
yield setSize(size);
checkSize(size);
yield alterContent(browser, setSize, size);
yield checkSize(size);
}
yield setSize(1400);
yield alterContent(browser, setSize, 1400);
let dims = yield promiseContentDimensions(browser);
let {body, root} = dims;
if (AppConstants.platform == "win") {
ok(panelWindow.innerWidth >= 750 && panelWindow.innerWidth <= 800,
`Panel window width ${panelWindow.innerWidth} is in acceptable range`);
ok(dims.window.innerWidth >= 750 && dims.window.innerWidth <= 800,
`Panel window width ${dims.window.innerWidth} is in acceptable range`);
} else {
is(panelWindow.innerWidth, 800, "Panel window width");
is(dims.window.innerWidth, 800, "Panel window width");
}
ok(body.clientWidth <= 800, `Panel body width ${body.clientWidth} is less than 800`);
is(body.scrollWidth, 1400, "Panel body scroll width");
is(panelWindow.innerHeight, 600, "Panel window height");
is(dims.window.innerHeight, 600, "Panel window height");
ok(root.clientHeight <= 600, `Panel root height (${root.clientHeight}px) is less than 600px`);
is(root.scrollHeight, 1400, "Panel root scroll height");
@@ -142,29 +131,27 @@ add_task(function* testPageActionPopupReflow() {
browser = yield awaitExtensionPanel(extension);
let win = browser.contentWindow;
let body = win.document.body;
let root = win.document.documentElement;
/* eslint-disable mozilla/no-cpows-in-tests */
function setSize(size) {
body.style.fontSize = `${size}px`;
return awaitResize(browser);
content.document.body.style.fontSize = `${size}px`;
}
/* eslint-enable mozilla/no-cpows-in-tests */
yield setSize(18);
yield alterContent(browser, setSize, 18);
is(win.innerWidth, 800, "Panel window should be 800px wide");
is(body.clientWidth, 800, "Panel body should be 800px wide");
is(body.clientWidth, body.scrollWidth,
let dims = yield promiseContentDimensions(browser);
is(dims.window.innerWidth, 800, "Panel window should be 800px wide");
is(dims.body.clientWidth, 800, "Panel body should be 800px wide");
is(dims.body.clientWidth, dims.body.scrollWidth,
"Panel body should be wide enough to fit its contents");
ok(win.innerHeight > 36,
`Panel window height (${win.innerHeight}px) should be taller than two lines of text.`);
ok(dims.window.innerHeight > 36,
`Panel window height (${dims.window.innerHeight}px) should be taller than two lines of text.`);
is(body.clientHeight, body.scrollHeight,
is(dims.body.clientHeight, dims.body.scrollHeight,
"Panel body should be tall enough to fit its contents");
is(root.clientHeight, root.scrollHeight,
is(dims.root.clientHeight, dims.root.scrollHeight,
"Panel root should be tall enough to fit its contents");
yield extension.unload();

View File

@@ -2,18 +2,6 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* awaitResize(browser) {
// Debouncing code makes this a bit racy.
// Try to skip the first, early resize, and catch the resize event we're
// looking for, but don't wait longer than a few seconds.
return Promise.race([
BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")
.then(() => BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")),
new Promise(resolve => setTimeout(resolve, 5000)),
]);
}
add_task(function* testPopupBackground() {
let extension = ExtensionTestUtils.loadExtension({
background() {
@@ -79,26 +67,34 @@ add_task(function* testPopupBackground() {
isnot(borderIndex, backgroundIndex, "Border and background fills are separate elements");
};
let win = browser.contentWindow;
let body = win.document.body;
function getBackground(browser) {
return ContentTask.spawn(browser, null, function* () {
return content.getComputedStyle(content.document.body)
.backgroundColor;
});
}
/* eslint-disable mozilla/no-cpows-in-tests */
let setBackground = color => {
content.document.body.style.backgroundColor = color;
};
/* eslint-enable mozilla/no-cpows-in-tests */
yield new Promise(resolve => setTimeout(resolve, 100));
info("Test that initial background color is applied");
checkArrow(win.getComputedStyle(body).backgroundColor);
checkArrow(yield getBackground(browser));
info("Test that dynamically-changed background color is applied");
body.style.backgroundColor = "black";
yield awaitResize(browser);
yield alterContent(browser, setBackground, "black");
checkArrow(win.getComputedStyle(body).backgroundColor);
checkArrow(yield getBackground(browser));
info("Test that non-opaque background color results in default styling");
body.style.backgroundColor = "rgba(1, 2, 3, .9)";
yield awaitResize(browser);
yield alterContent(browser, setBackground, "rgba(1, 2, 3, .9)");
checkArrow(null);
}

View File

@@ -42,17 +42,24 @@ add_task(function* testPopupBorderRadius() {
let viewNode = browser.parentNode === panel ? browser : browser.parentNode;
let viewStyle = getComputedStyle(viewNode);
let win = browser.contentWindow;
let bodyStyle = win.getComputedStyle(win.document.body);
let props = ["borderTopLeftRadius", "borderTopRightRadius",
"borderBottomRightRadius", "borderBottomLeftRadius"];
for (let prop of ["borderTopLeftRadius", "borderTopRightRadius",
"borderBottomRightRadius", "borderBottomLeftRadius"]) {
/* eslint-disable mozilla/no-cpows-in-tests */
let bodyStyle = yield ContentTask.spawn(browser, props, function* (props) {
let bodyStyle = content.getComputedStyle(content.document.body);
return new Map(props.map(prop => [prop, bodyStyle[prop]]));
});
/* eslint-enable mozilla/no-cpows-in-tests */
for (let prop of props) {
if (standAlone) {
is(viewStyle[prop], panelStyle[prop], `Panel and view ${prop} should be the same`);
is(bodyStyle[prop], panelStyle[prop], `Panel and body ${prop} should be the same`);
is(bodyStyle.get(prop), panelStyle[prop], `Panel and body ${prop} should be the same`);
} else {
is(viewStyle[prop], "0px", `View node ${prop} should be 0px`);
is(bodyStyle[prop], "0px", `Body node ${prop} should be 0px`);
is(bodyStyle.get(prop), "0px", `Body node ${prop} should be 0px`);
}
}
}

View File

@@ -11,7 +11,8 @@
* openContextMenu closeContextMenu
* openExtensionContextMenu closeExtensionContextMenu
* imageBuffer getListStyleImage getPanelForNode
* awaitExtensionPanel
* awaitExtensionPanel awaitPopupResize
* promiseContentDimensions alterContent
*/
var {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
@@ -84,6 +85,44 @@ function promisePopupHidden(popup) {
});
}
function promiseContentDimensions(browser) {
return ContentTask.spawn(browser, null, function* () {
function copyProps(obj, props) {
let res = {};
for (let prop of props) {
res[prop] = obj[prop];
}
return res;
}
return {
window: copyProps(content,
["innerWidth", "innerHeight", "outerWidth", "outerHeight",
"scrollX", "scrollY", "scrollMaxX", "scrollMaxY"]),
body: copyProps(content.document.body,
["clientWidth", "clientHeight", "scrollWidth", "scrollHeight"]),
root: copyProps(content.document.documentElement,
["clientWidth", "clientHeight", "scrollWidth", "scrollHeight"]),
isStandards: content.document.compatMode !== "BackCompat",
};
});
}
function* awaitPopupResize(browser) {
return BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized",
event => event.detail === "delayed");
}
function alterContent(browser, task, arg = null) {
return Promise.all([
ContentTask.spawn(browser, arg, task),
awaitPopupResize(browser),
]).then(() => {
return promiseContentDimensions(browser);
});
}
function getPanelForNode(node) {
while (node.localName != "panel") {
node = node.parentNode;
@@ -91,19 +130,10 @@ function getPanelForNode(node) {
return node;
}
var awaitExtensionPanel = Task.async(function* (extension, win = window, filename = "popup.html") {
let {target} = yield BrowserTestUtils.waitForEvent(win.document, "load", true, (event) => {
return event.target.location && event.target.location.href.endsWith(filename);
});
let browser = target.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDocShell)
.chromeEventHandler;
if (browser.matches(".webextension-preload-browser")) {
let event = yield BrowserTestUtils.waitForEvent(browser, "SwapDocShells");
browser = event.detail;
}
var awaitExtensionPanel = Task.async(function* (extension, win = window) {
let {originalTarget: browser} = yield BrowserTestUtils.waitForEvent(
win.document, "WebExtPopupLoaded", true,
event => event.detail.extension.id === extension.id);
yield promisePopupShown(getPanelForNode(browser));