Bug 1144869 - Add BrowserTestUtils.withNewTab. r=smacleod, a=test-only
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Fri, 20 Mar 2015 10:26:01 -0700
changeset 257911 b990527a06e8fd119ffebd5e6d4cb5e8cadd8d1e
parent 257910 408c2cb6f5e7bce1750f68273dac32affbd83faa
child 257912 6b874e2d4d18d05fa9e3197b507611f5614d9170
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmacleod, test-only
bugs1144869
milestone38.0a2
Bug 1144869 - Add BrowserTestUtils.withNewTab. r=smacleod, a=test-only
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -14,33 +14,73 @@
 this.EXPORTED_SYMBOLS = [
   "BrowserTestUtils",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://testing-common/TestUtils.jsm");
 
 Cc["@mozilla.org/globalmessagemanager;1"]
   .getService(Ci.nsIMessageListenerManager)
   .loadFrameScript(
     "chrome://mochikit/content/tests/BrowserTestUtils/content-utils.js", true);
 
 this.BrowserTestUtils = {
   /**
+   * Loads a page in a new tab, executes a Task and closes the tab.
+   *
+   * @param options
+   *        An object with the following properties:
+   *        {
+   *          gBrowser:
+   *            Reference to the "tabbrowser" element where the new tab should
+   *            be opened.
+   *          url:
+   *            String with the URL of the page to load.
+   *        }
+   * @param taskFn
+   *        Generator function representing a Task that will be executed while
+   *        the tab is loaded. The first argument passed to the function is a
+   *        reference to the browser object for the new tab.
+   *
+   * @return {Promise}
+   * @resolves When the tab has been closed.
+   * @rejects Any exception from taskFn is propagated.
+   */
+  withNewTab: Task.async(function* (options, taskFn) {
+    let tab = options.gBrowser.addTab(options.url);
+    yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+    options.gBrowser.selectedTab = tab;
+
+    yield taskFn(tab.linkedBrowser);
+
+    options.gBrowser.removeTab(tab);
+  }),
+
+  /**
+   * Waits for an ongoing page load in a browser window to complete.
+   *
+   * This can be used in conjunction with any synchronous method for starting a
+   * load, like the "addTab" method on "tabbrowser", and must be called before
+   * yielding control to the event loop. This is guaranteed to work because the
+   * way we're listening for the load is in the content-utils.js frame script,
+   * and then sending an async message up, so we can't miss the message.
+   *
    * @param {xul:browser} browser
    *        A xul:browser.
    * @param {Boolean} includeSubFrames
    *        A boolean indicating if loads from subframes should be included.
+   *
    * @return {Promise}
-   *         A Promise which resolves when a load event is triggered
-   *         for browser.
+   * @resolves When a load event is triggered for the browser.
    */
   browserLoaded(browser, includeSubFrames=false) {
     return new Promise(resolve => {
       browser.messageManager.addMessageListener("browser-test-utils:loadEvent",
                                                  function onLoad(msg) {
         if (!msg.data.subframe || includeSubFrames) {
           browser.messageManager.removeMessageListener(
             "browser-test-utils:loadEvent", onLoad);