Bug 1190663: [webext] Add tests for window.close() in browserAction and pageAction popups. r?rpl
MozReview-Commit-ID: 8r08YRw7IGr
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -125,16 +125,29 @@ global.IconDetails = {
};
global.makeWidgetId = id => {
id = id.toLowerCase();
// FIXME: This allows for collisions.
return id.replace(/[^a-z0-9_-]/g, "_");
};
+function promisePopupShown(popup) {
+ return new Promise(resolve => {
+ if (popup.state == "open") {
+ resolve();
+ } else {
+ popup.addEventListener("popupshown", function onPopupShown(event) {
+ popup.removeEventListener("popupshown", onPopupShown);
+ resolve();
+ });
+ }
+ });
+}
+
class BasePopup {
constructor(extension, viewNode, popupURL) {
let popupURI = Services.io.newURI(popupURL, null, extension.baseURI);
Services.scriptSecurityManager.checkLoadURIWithPrincipal(
extension.principal, popupURI,
Services.scriptSecurityManager.DISALLOW_SCRIPT);
@@ -254,16 +267,20 @@ class BasePopup {
this.browser.addEventListener("load", this, true);
this.browser.addEventListener("DOMTitleChanged", this, true);
this.browser.addEventListener("DOMWindowClose", this, true);
});
}
// Resizes the browser to match the preferred size of the content.
resizeBrowser() {
+ if (!this.browser) {
+ return;
+ }
+
let width, height;
try {
let w = {}, h = {};
this.browser.docShell.contentViewer.getContentSize(w, h);
width = w.value / this.window.devicePixelRatio;
height = h.value / this.window.devicePixelRatio;
@@ -310,17 +327,22 @@ global.PanelPopup = class PanelPopup ext
}
destroy() {
super.destroy();
this.viewNode.remove();
}
closePopup() {
- this.viewNode.hidePopup();
+ promisePopupShown(this.viewNode).then(() => {
+ // Make sure we're not already destroyed.
+ if (this.viewNode) {
+ this.viewNode.hidePopup();
+ }
+ });
}
};
global.ViewPopup = class ViewPopup extends BasePopup {
get DESTROY_EVENT() {
return "ViewHiding";
}
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -1,35 +1,42 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* testInArea(area) {
+ let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head></html>`;
+
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"background": {
"page": "data/background.html",
},
"browser_action": {
"default_popup": "popup-a.html",
},
},
files: {
- "popup-a.html": `<script src="popup-a.js"></script>`,
+ "popup-a.html": scriptPage("popup-a.js"),
"popup-a.js": function() {
browser.runtime.sendMessage("from-popup-a");
+ browser.runtime.onMessage.addListener(msg => {
+ if (msg == "close-popup") {
+ window.close();
+ }
+ });
},
- "data/popup-b.html": `<script src="popup-b.js"></script>`,
+ "data/popup-b.html": scriptPage("popup-b.js"),
"data/popup-b.js": function() {
browser.runtime.sendMessage("from-popup-b");
},
- "data/background.html": `<script src="background.js"></script>`,
+ "data/background.html": scriptPage("background.js"),
"data/background.js": function() {
let sendClick;
let tests = [
() => {
sendClick({expectEvent: false, expectPopup: "a"});
},
() => {
@@ -46,36 +53,47 @@ function* testInArea(area) {
browser.browserAction.setPopup({popup: ""});
sendClick({expectEvent: true, expectPopup: null});
},
() => {
sendClick({expectEvent: true, expectPopup: null});
},
() => {
browser.browserAction.setPopup({popup: "/popup-a.html"});
- sendClick({expectEvent: false, expectPopup: "a"});
+ sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
+ },
+ () => {
+ browser.test.sendMessage("next-test", {expectClosed: true});
+ browser.runtime.sendMessage("close-popup");
},
];
let expect = {};
- sendClick = ({expectEvent, expectPopup}) => {
- expect = {event: expectEvent, popup: expectPopup};
+ sendClick = ({expectEvent, expectPopup, runNextTest}) => {
+ expect = {event: expectEvent, popup: expectPopup, runNextTest};
browser.test.sendMessage("send-click");
};
browser.runtime.onMessage.addListener(msg => {
- if (expect.popup) {
+ if (msg == "close-popup") {
+ return;
+ } else if (expect.popup) {
browser.test.assertEq(msg, `from-popup-${expect.popup}`,
"expected popup opened");
} else {
- browser.test.fail("unexpected popup");
+ browser.test.fail(`unexpected popup: ${msg}`);
}
expect.popup = null;
- browser.test.sendMessage("next-test");
+ if (expect.runNextTest) {
+ expect.runNextTest = false;
+ tests.shift()();
+ } else {
+ browser.test.sendMessage("next-test");
+ }
});
browser.browserAction.onClicked.addListener(() => {
if (expect.event) {
browser.test.succeed("expected click event received");
} else {
browser.test.fail("unexpected click event");
}
@@ -102,23 +120,30 @@ function* testInArea(area) {
},
});
extension.onMessage("send-click", () => {
clickBrowserAction(extension);
});
let widget;
- extension.onMessage("next-test", Task.async(function* () {
+ extension.onMessage("next-test", Task.async(function* (expecting = {}) {
if (!widget) {
widget = getBrowserActionWidget(extension);
CustomizableUI.addWidgetToArea(widget.id, area);
}
-
- yield closeBrowserAction(extension);
+ if (expecting.expectClosed) {
+ let panel = getBrowserActionPopup(extension);
+ ok(panel, "Expect panel to exist");
+ yield promisePopupShown(panel);
+ yield promisePopupHidden(panel);
+ ok(true, "Panel is closed");
+ } else {
+ yield closeBrowserAction(extension);
+ }
extension.sendMessage("next-test");
}));
yield Promise.all([extension.startup(), extension.awaitFinish("browseraction-tests-done")]);
yield extension.unload();
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
@@ -14,16 +14,21 @@ add_task(function* testPageActionPopup()
"default_popup": "popup-a.html",
},
},
files: {
"popup-a.html": scriptPage("popup-a.js"),
"popup-a.js": function() {
browser.runtime.sendMessage("from-popup-a");
+ browser.runtime.onMessage.addListener(msg => {
+ if (msg == "close-popup") {
+ window.close();
+ }
+ });
},
"data/popup-b.html": scriptPage("popup-b.js"),
"data/popup-b.js": function() {
browser.runtime.sendMessage("from-popup-b");
},
"data/background.html": scriptPage("background.js"),
@@ -50,36 +55,47 @@ add_task(function* testPageActionPopup()
browser.pageAction.setPopup({tabId, popup: ""});
sendClick({expectEvent: true, expectPopup: null});
},
() => {
sendClick({expectEvent: true, expectPopup: null});
},
() => {
browser.pageAction.setPopup({tabId, popup: "/popup-a.html"});
- sendClick({expectEvent: false, expectPopup: "a"});
+ sendClick({expectEvent: false, expectPopup: "a", runNextTest: true});
+ },
+ () => {
+ browser.test.sendMessage("next-test", {expectClosed: true});
+ browser.runtime.sendMessage("close-popup");
},
];
let expect = {};
- sendClick = ({expectEvent, expectPopup}) => {
- expect = {event: expectEvent, popup: expectPopup};
+ sendClick = ({expectEvent, expectPopup, runNextTest}) => {
+ expect = {event: expectEvent, popup: expectPopup, runNextTest};
browser.test.sendMessage("send-click");
};
browser.runtime.onMessage.addListener(msg => {
- if (expect.popup) {
+ if (msg == "close-popup") {
+ return;
+ } else if (expect.popup) {
browser.test.assertEq(msg, `from-popup-${expect.popup}`,
"expected popup opened");
} else {
- browser.test.fail("unexpected popup");
+ browser.test.fail(`unexpected popup: ${msg}`);
}
expect.popup = null;
- browser.test.sendMessage("next-test");
+ if (expect.runNextTest) {
+ expect.runNextTest = false;
+ tests.shift()();
+ } else {
+ browser.test.sendMessage("next-test");
+ }
});
browser.pageAction.onClicked.addListener(() => {
if (expect.event) {
browser.test.succeed("expected click event received");
} else {
browser.test.fail("unexpected click event");
}
@@ -113,22 +129,29 @@ add_task(function* testPageActionPopup()
let pageActionId = makeWidgetId(extension.id) + "-page-action";
let panelId = makeWidgetId(extension.id) + "-panel";
extension.onMessage("send-click", () => {
clickPageAction(extension);
});
- extension.onMessage("next-test", Task.async(function* () {
+ extension.onMessage("next-test", Task.async(function* (expecting = {}) {
let panel = document.getElementById(panelId);
- if (panel) {
+ if (expecting.expectClosed) {
+ ok(panel, "Expect panel to exist");
+ yield promisePopupShown(panel);
+ yield promisePopupHidden(panel);
+ ok(true, `Panel is closed`);
+ } else if (panel) {
yield promisePopupShown(panel);
panel.hidePopup();
+ }
+ if (panel) {
panel = document.getElementById(panelId);
is(panel, null, "panel successfully removed from document after hiding");
}
extension.sendMessage("next-test");
}));
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -2,17 +2,17 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
/* exported CustomizableUI makeWidgetId focusWindow forceGC
* getBrowserActionWidget
* clickBrowserAction clickPageAction
* getBrowserActionPopup getPageActionPopup
* closeBrowserAction closePageAction
- * promisePopupShown
+ * promisePopupShown promisePopupHidden
*/
var {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
var {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
// Bug 1239884: Our tests occasionally hit a long GC pause at unpredictable
// times in debug builds, which results in intermittent timeouts. Until we have
// a better solution, we force a GC after certain strategic tests, which tend to
@@ -54,25 +54,37 @@ function promisePopupShown(popup) {
popup.removeEventListener("popupshown", onPopupShown);
resolve();
};
popup.addEventListener("popupshown", onPopupShown);
}
});
}
+function promisePopupHidden(popup) {
+ return new Promise(resolve => {
+ let onPopupHidden = event => {
+ popup.removeEventListener("popuphidden", onPopupHidden);
+ resolve();
+ };
+ popup.addEventListener("popuphidden", onPopupHidden);
+ });
+}
+
function getBrowserActionWidget(extension) {
return CustomizableUI.getWidget(makeWidgetId(extension.id) + "-browser-action");
}
function getBrowserActionPopup(extension, win = window) {
let group = getBrowserActionWidget(extension);
if (group.areaType == CustomizableUI.TYPE_TOOLBAR) {
return win.document.getElementById("customizationui-widget-panel");
+ } else {
+ return win.PanelUI.panel;
}
return null;
}
var clickBrowserAction = Task.async(function* (extension, win = window) {
let group = getBrowserActionWidget(extension);
let widget = group.forWindow(win);