Bug 1262946 - Add focus tests for newly opened windows. r?Gijs draft
authorMike Conley <mconley@mozilla.com>
Thu, 07 Apr 2016 17:05:54 -0400
changeset 348991 c9e3478db083fe20e1b2996bc05d09f6812ed309
parent 348980 10bc9d81e54629d74a1e9530a057b8b646d48dfc
child 348992 19718b967acfc4cb7da8c8e6f35d4d9397bf79b9
push id14986
push usermconley@mozilla.com
push dateFri, 08 Apr 2016 19:29:06 +0000
reviewersGijs
bugs1262946
milestone48.0a1
Bug 1262946 - Add focus tests for newly opened windows. r?Gijs MozReview-Commit-ID: 2353D0oA0yO
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_newwindow_focus.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -573,8 +573,10 @@ skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_clearEmail.js]
 skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_showForm.js]
 skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_withoutDump.js]
 skip-if = !e10s
 [browser_csp_block_all_mixedcontent.js]
 tags = mcb
+[browser_newwindow_focus.js]
+skip-if = (os == "linux" && !e10s) # Bug 1263254 - Perma fails on Linux without e10s for some reason.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_newwindow_focus.js
@@ -0,0 +1,96 @@
+"use strict";
+
+/**
+ * These tests are for the auto-focus behaviour on the initial browser
+ * when a window is opened from content.
+ */
+
+const PAGE = `data:text/html,<a id="target" href="%23" onclick="window.open('http://www.example.com', '_blank', 'width=100,height=100');">Click me</a>`;
+
+/**
+ * Returns a Promise that resolves when a new window has
+ * opened, and the "load" event has fired in that window.
+ * We can't use BrowserTestUtils.domWindowOpened directly,
+ * because by the time the "then" on the Promise runs,
+ * DOMContentLoaded and load may have already run in the new
+ * window. However, we want to be very explicit about what
+ * events we're waiting for, and not rely on a quirk of our
+ * Promises infrastructure.
+ */
+function promiseNewWindow() {
+  return new Promise((resolve) => {
+    let observer = (subject, topic, data) => {
+      if (topic == "domwindowopened") {
+        Services.ww.unregisterNotification(observer);
+        let win = subject.QueryInterface(Ci.nsIDOMWindow);
+        win.addEventListener("load", function onLoad() {
+          win.removeEventListener("load", onLoad);
+          resolve(win);
+        });
+      }
+    };
+
+    Services.ww.registerNotification(observer);
+  });
+}
+
+/**
+ * Test that when a new window is opened from content, focus moves
+ * to the initial browser in that window once the window has finished
+ * painting.
+ */
+add_task(function* test_focus_browser() {
+  yield BrowserTestUtils.withNewTab({
+    url: PAGE,
+    gBrowser,
+  }, function*(browser) {
+    let newWinPromise = promiseNewWindow();
+    let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
+
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#target", {}, browser);
+    let newWin = yield newWinPromise;
+    yield BrowserTestUtils.contentPainted(newWin.gBrowser.selectedBrowser);
+    yield delayedStartupPromise;
+
+    let focusedElement =
+      Services.focus.getFocusedElementForWindow(newWin, false, {});
+
+    Assert.equal(focusedElement, newWin.gBrowser.selectedBrowser,
+                 "Initial browser should be focused");
+
+    yield BrowserTestUtils.closeWindow(newWin);
+  });
+});
+
+/**
+ * Test that when a new window is opened from content and focus
+ * shifts in that window before the content has a chance to paint
+ * that we _don't_ steal focus once content has painted.
+ */
+add_task(function* test_no_steal_focus() {
+  yield BrowserTestUtils.withNewTab({
+    url: PAGE,
+    gBrowser,
+  }, function*(browser) {
+    let newWinPromise = promiseNewWindow();
+    let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
+
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#target", {}, browser);
+    let newWin = yield newWinPromise;
+
+    // Because we're switching focus, we shouldn't steal it once
+    // content paints.
+    newWin.gURLBar.focus();
+
+    yield BrowserTestUtils.contentPainted(newWin.gBrowser.selectedBrowser);
+    yield delayedStartupPromise;
+
+    let focusedElement =
+      Services.focus.getFocusedElementForWindow(newWin, false, {});
+
+    Assert.equal(focusedElement, newWin.gURLBar.inputField,
+                 "URLBar should be focused");
+
+    yield BrowserTestUtils.closeWindow(newWin);
+  });
+});
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -1040,9 +1040,29 @@ this.BrowserTestUtils = {
       BrowserTestUtils.waitForEvent(notificationBox, "AlertActive",
                                     false, check).then((event) => {
         // The originalTarget of the AlertActive on a notificationbox
         // will be the notification itself.
         resolve(event.originalTarget);
       });
     });
   },
+
+  /**
+   * Returns a Promise that will resolve once MozAfterPaint
+   * has been fired in the content of a browser.
+   *
+   * @param browser (<xul:browser>)
+   *        The browser for which we're waiting for the MozAfterPaint
+   *        event to occur in.
+   * @returns Promise
+   */
+  contentPainted(browser) {
+    return ContentTask.spawn(browser, null, function*() {
+      return new Promise((resolve) => {
+        addEventListener("MozAfterPaint", function onPaint() {
+          removeEventListener("MozAfterPaint", onPaint);
+          resolve();
+        })
+      });
+    });
+  },
 };