Bug 989947 - test UITour interaction with modal popup, r=MattN, a=lsblakk
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 11 Nov 2014 15:38:37 +0000
changeset 233952 8651ad90ff2f7240a322595531b84564ef987ad1
parent 233951 c55df95bdf6d47c3fdf460dd56ff458104660c93
child 233953 c8ebeea28f1998ab512216aa7f853d50fe9cb104
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN, lsblakk
bugs989947
milestone35.0a2
Bug 989947 - test UITour interaction with modal popup, r=MattN, a=lsblakk
browser/modules/test/browser.ini
browser/modules/test/browser_UITour_modalDialog.js
browser/modules/test/head.js
--- a/browser/modules/test/browser.ini
+++ b/browser/modules/test/browser.ini
@@ -23,16 +23,19 @@ skip-if = e10s # Bug 941428 - UITour.jsm
 [browser_UITour3.js]
 skip-if = os == "linux" || e10s # Linux: Bug 986760, Bug 989101; e10s: Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_availableTargets.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_detach_tab.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_annotation_size_attributes.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
+[browser_UITour_modalDialog.js]
+run-if = os == "mac" # modal dialog disabling only working on OS X
+skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_panel_close_annotation.js]
 skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
 [browser_UITour_registerPageID.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_sync.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_resetProfile.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser_UITour_modalDialog.js
@@ -0,0 +1,112 @@
+"use strict";
+
+let gTestTab;
+let gContentAPI;
+let gContentWindow;
+let handleDialog;
+
+// Modified from toolkit/components/passwordmgr/test/prompt_common.js
+var didDialog;
+
+var timer; // keep in outer scope so it's not GC'd before firing
+function startCallbackTimer() {
+    didDialog = false;
+
+    // Delay before the callback twiddles the prompt.
+    const dialogDelay = 10;
+
+    // Use a timer to invoke a callback to twiddle the authentication dialog
+    timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT);
+}
+
+
+var observer = SpecialPowers.wrapCallbackObject({
+    QueryInterface : function (iid) {
+        const interfaces = [Ci.nsIObserver,
+                            Ci.nsISupports, Ci.nsISupportsWeakReference];
+
+        if (!interfaces.some( function(v) { return iid.equals(v) } ))
+            throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
+        return this;
+    },
+
+    observe : function (subject, topic, data) {
+        var doc = getDialogDoc();
+        if (doc)
+            handleDialog(doc);
+        else
+            startCallbackTimer(); // try again in a bit
+    }
+});
+
+function getDialogDoc() {
+  // Find the <browser> which contains notifyWindow, by looking
+  // through all the open windows and all the <browsers> in each.
+  var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
+           getService(Ci.nsIWindowMediator);
+  //var enumerator = wm.getEnumerator("navigator:browser");
+  var enumerator = wm.getXULWindowEnumerator(null);
+
+  while (enumerator.hasMoreElements()) {
+    var win = enumerator.getNext();
+    var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
+
+    var containedDocShells = windowDocShell.getDocShellEnumerator(
+                                      Ci.nsIDocShellTreeItem.typeChrome,
+                                      Ci.nsIDocShell.ENUMERATE_FORWARDS);
+    while (containedDocShells.hasMoreElements()) {
+        // Get the corresponding document for this docshell
+        var childDocShell = containedDocShells.getNext();
+        childDocShell.QueryInterface(Ci.nsIDocShell);
+        // We don't want it if it's not done loading.
+        if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
+          continue;
+        var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
+                                    .contentViewer
+                                    .DOMDocument;
+
+        //ok(true, "Got window: " + childDoc.location.href);
+        if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
+          return childDoc;
+    }
+  }
+
+  return null;
+}
+
+Components.utils.import("resource:///modules/UITour.jsm");
+
+function test() {
+  UITourTest();
+}
+
+
+let tests = [
+  taskify(function* test_modal_dialog_while_opening_tooltip(done) {
+    let panelShown;
+    let popup;
+
+    handleDialog = (doc) => {
+      popup = document.getElementById("UITourTooltip");
+      gContentAPI.showInfo("appMenu", "test title", "test text");
+      doc.defaultView.setTimeout(function() {
+        is(popup.state, "closed", "Popup shouldn't be shown while dialog is up");
+        panelShown = promisePanelElementShown(window, popup);
+        let dialog = doc.getElementById("commonDialog");
+        dialog.acceptDialog();
+      }, 1000);
+    };
+    startCallbackTimer();
+    executeSoon(() => alert("test"));
+    let panelShownPromiseExists = Promise.defer();
+    waitForCondition(() => panelShown, panelShownPromiseExists.resolve, "Timed out waiting for panel promise to be assigned", 100);
+    yield panelShownPromiseExists.promise;
+    yield panelShown;
+
+    popup = document.getElementById("UITourTooltip");
+    let hiddenPromise = promisePanelElementHidden(window, popup);
+    gContentAPI.hideInfo();
+    yield hiddenPromise;
+  })
+];
--- a/browser/modules/test/head.js
+++ b/browser/modules/test/head.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Promise.jsm");
 
-function waitForCondition(condition, nextTest, errorMsg) {
+function waitForCondition(condition, nextTest, errorMsg, maxTries=30) {
   var tries = 0;
   var interval = setInterval(function() {
-    if (tries >= 30) {
+    if (tries >= maxTries) {
       ok(false, errorMsg);
       moveOn();
     }
     var conditionPassed;
     try {
       conditionPassed = condition();
     } catch (e) {
       ok(false, e + "\n" + e.stack);
@@ -20,16 +20,28 @@ function waitForCondition(condition, nex
     if (conditionPassed) {
       moveOn();
     }
     tries++;
   }, 100);
   var moveOn = function() { clearInterval(interval); nextTest(); };
 }
 
+/**
+ * Wrapper to partially transition tests to Task.
+ */
+function taskify(fun) {
+  return (done) => {
+    return Task.spawn(fun).then(done, (reason) => {
+      ok(false, reason);
+      done();
+    });
+  }
+}
+
 function is_hidden(element) {
   var style = element.ownerDocument.defaultView.getComputedStyle(element, "");
   if (style.display == "none")
     return true;
   if (style.visibility != "visible")
     return true;
   if (style.display == "-moz-popup")
     return ["hiding","closed"].indexOf(element.state) != -1;
@@ -103,16 +115,29 @@ function promisePanelElementShown(win, a
   aPanel.addEventListener("popupshown", function onPanelOpen(e) {
     aPanel.removeEventListener("popupshown", onPanelOpen);
     win.clearTimeout(timeoutId);
     deferred.resolve();
   });
   return deferred.promise;
 }
 
+function promisePanelElementHidden(win, aPanel) {
+  let deferred = Promise.defer();
+  let timeoutId = win.setTimeout(() => {
+    deferred.reject("Panel did not show within 5 seconds.");
+  }, 5000);
+  aPanel.addEventListener("popuphidden", function onPanelOpen(e) {
+    aPanel.removeEventListener("popuphidden", onPanelOpen);
+    win.clearTimeout(timeoutId);
+    deferred.resolve();
+  });
+  return deferred.promise;
+}
+
 function is_element_hidden(element, msg) {
   isnot(element, null, "Element should not be null, when checking visibility");
   ok(is_hidden(element), msg);
 }
 
 function loadUITourTestPage(callback, host = "https://example.com/") {
   if (gTestTab)
     gBrowser.removeTab(gTestTab);