mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1323185 - Add window (tab) handling support for Fennec. r=ato
So far Marionette did support Fennec but not any of its tab handling features. As such most of the commands fail because they do not take BrowserApp into account. This patch adds support for retrieving window handles, switching between windows, and closing tabs. Additionally to those changes a couple of unit tests are getting updated, and added. MozReview-Commit-ID: 7sbVIblm0Hw --HG-- rename : testing/marionette/harness/marionette_harness/tests/unit/test_window_handles.py => testing/marionette/harness/marionette_harness/tests/unit/test_window_handles_content.py extra : rebase_source : 475dd6bee446f58208192202cd4c483e2fd929dc
This commit is contained in:
parent
e328faf19c
commit
fa96c2f9f9
@ -16,6 +16,59 @@ this.browser = {};
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
|
||||
/**
|
||||
* Get the <xul:browser> for the specified tab.
|
||||
*
|
||||
* @param {<xul:tab>} tab
|
||||
* The tab whose browser needs to be returned.
|
||||
*
|
||||
* @return {<xul:browser>}
|
||||
* The linked browser for the tab.
|
||||
*
|
||||
* @throws UnsupportedOperationError
|
||||
* If tab handling for the current application isn't supported.
|
||||
*/
|
||||
browser.getBrowserForTab = function (tab) {
|
||||
if (tab.hasOwnProperty("browser")) {
|
||||
// Fennec
|
||||
return tab.browser;
|
||||
|
||||
} else if (tab.hasOwnProperty("linkedBrowser")) {
|
||||
// Firefox
|
||||
return tab.linkedBrowser;
|
||||
|
||||
} else {
|
||||
new UnsupportedOperationError("getBrowserForTab() not supported.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the tab browser for the specified chrome window.
|
||||
*
|
||||
* @param {nsIDOMWindow} win
|
||||
* The window whose tabbrowser needs to be accessed.
|
||||
*
|
||||
* @return {<xul:tabbrowser>}
|
||||
* Tab browser or null if it's not a browser window.
|
||||
*
|
||||
* @throws UnsupportedOperationError
|
||||
* If tab handling for the current application isn't supported.
|
||||
*/
|
||||
browser.getTabBrowser = function (win) {
|
||||
if (win.hasOwnProperty("BrowserApp")) {
|
||||
// Fennec
|
||||
return win.BrowserApp;
|
||||
|
||||
} else if (win.hasOwnProperty("gBrowser")) {
|
||||
// Firefox
|
||||
return win.gBrowser;
|
||||
|
||||
} else {
|
||||
new UnsupportedOperationError("getBrowserForTab() not supported.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a browsing context wrapper.
|
||||
*
|
||||
@ -41,8 +94,7 @@ browser.Context = class {
|
||||
|
||||
// In Firefox this is <xul:tabbrowser> (not <xul:browser>!)
|
||||
// and BrowserApp in Fennec
|
||||
this.browser = undefined;
|
||||
this.setBrowser(win);
|
||||
this.tabBrowser = browser.getTabBrowser(win);
|
||||
|
||||
this.knownFrames = [];
|
||||
|
||||
@ -78,21 +130,6 @@ browser.Context = class {
|
||||
this._hasRemotenessChange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <xul:browser> for the current tab in this tab browser.
|
||||
*
|
||||
* @return {<xul:browser>}
|
||||
* Browser linked to |this.tab| or the tab browser's
|
||||
* |selectedBrowser|.
|
||||
*/
|
||||
get browserForTab() {
|
||||
if (this.browser.getBrowserForTab) {
|
||||
return this.browser.getBrowserForTab(this.tab);
|
||||
} else {
|
||||
return this.browser.selectedBrowser;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current frame ID is managed per browser element on desktop in
|
||||
* case the ID needs to be refreshed. The currently selected window is
|
||||
@ -103,7 +140,7 @@ browser.Context = class {
|
||||
if (this.driver.appName == "B2G") {
|
||||
rv = this._curFrameId;
|
||||
} else if (this.tab) {
|
||||
rv = this.getIdForBrowser(this.browserForTab);
|
||||
rv = this.getIdForBrowser(browser.getBrowserForTab(this.tab));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -119,7 +156,7 @@ browser.Context = class {
|
||||
* associated with the currently selected tab.
|
||||
*/
|
||||
getTabModalUI() {
|
||||
let br = this.browserForTab;
|
||||
let br = browser.getBrowserForTab(this.tab);
|
||||
if (!br.hasAttribute("tabmodalPromptShowing")) {
|
||||
return null;
|
||||
}
|
||||
@ -131,24 +168,6 @@ browser.Context = class {
|
||||
return modals[0].ui;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the browser if the application is not B2G.
|
||||
*
|
||||
* @param {nsIDOMWindow} win
|
||||
* Current window reference.
|
||||
*/
|
||||
setBrowser(win) {
|
||||
switch (this.driver.appName) {
|
||||
case "Firefox":
|
||||
this.browser = win.gBrowser;
|
||||
break;
|
||||
|
||||
case "Fennec":
|
||||
this.browser = win.BrowserApp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current window.
|
||||
*
|
||||
@ -174,20 +193,32 @@ browser.Context = class {
|
||||
*
|
||||
* @return {Promise}
|
||||
* A promise which is resolved when the current tab has been closed.
|
||||
*
|
||||
* @throws UnsupportedOperationError
|
||||
* If tab handling for the current application isn't supported.
|
||||
*/
|
||||
closeTab() {
|
||||
// If the current window is not a browser then close it directly. Do the
|
||||
// same if only one remaining tab is open, or no tab selected at all.
|
||||
if (!this.browser || !this.tab || this.browser.browsers.length == 1) {
|
||||
if (!this.tabBrowser || this.tabBrowser.tabs.length === 1 || !this.tab) {
|
||||
return this.closeWindow();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.browser.removeTab) {
|
||||
if (this.tabBrowser.closeTab) {
|
||||
// Fennec
|
||||
this.tabBrowser.deck.addEventListener("TabClose", ev => {
|
||||
resolve();
|
||||
}, {once: true});
|
||||
this.tabBrowser.closeTab(this.tab);
|
||||
|
||||
} else if (this.tabBrowser.removeTab) {
|
||||
// Firefox
|
||||
this.tab.addEventListener("TabClose", ev => {
|
||||
resolve();
|
||||
}, {once: true});
|
||||
this.browser.removeTab(this.tab);
|
||||
this.tabBrowser.removeTab(this.tab);
|
||||
|
||||
} else {
|
||||
reject(new UnsupportedOperationError(
|
||||
`closeTab() not supported in ${this.driver.appName}`));
|
||||
@ -202,29 +233,47 @@ browser.Context = class {
|
||||
* URI to open.
|
||||
*/
|
||||
addTab(uri) {
|
||||
return this.browser.addTab(uri, true);
|
||||
return this.tabBrowser.addTab(uri, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-sets current tab and updates remoteness tracking.
|
||||
* Set the current tab and update remoteness tracking if a tabbrowser is available.
|
||||
*
|
||||
* If a window is provided, the internal reference is updated before
|
||||
* proceeding.
|
||||
* @param {number=} index
|
||||
* Tab index to switch to. If the parameter is undefined,
|
||||
* the currently selected tab will be used.
|
||||
* @param {nsIDOMWindow=} win
|
||||
* Switch to this window before selecting the tab.
|
||||
*/
|
||||
switchToTab(ind, win) {
|
||||
switchToTab(index, win) {
|
||||
if (win) {
|
||||
this.window = win;
|
||||
this.setBrowser(win);
|
||||
this.tabBrowser = browser.getTabBrowser(win);
|
||||
}
|
||||
if (this.browser.selectTabAtIndex) {
|
||||
this.browser.selectTabAtIndex(ind);
|
||||
this.tab = this.browser.selectedTab;
|
||||
this._browserWasRemote = this.browserForTab.isRemoteBrowser;
|
||||
|
||||
if (!this.tabBrowser) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.tab = this.browser.selectedTab;
|
||||
|
||||
if (typeof index == "undefined") {
|
||||
this.tab = this.tabBrowser.selectedTab;
|
||||
} else {
|
||||
this.tab = this.tabBrowser.tabs[index];
|
||||
|
||||
if (this.tabBrowser.selectTab) {
|
||||
// Fennec
|
||||
this.tabBrowser.selectTab(this.tab);
|
||||
|
||||
} else {
|
||||
// Firefox
|
||||
this.tabBrowser.selectedTab = this.tab;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.driver.appName == "Firefox") {
|
||||
this._browserWasRemote = browser.getBrowserForTab(this.tab).isRemoteBrowser;
|
||||
this._hasRemotenessChange = false;
|
||||
}
|
||||
this._hasRemotenessChange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,15 +288,15 @@ browser.Context = class {
|
||||
register(uid, target) {
|
||||
let remotenessChange = this.hasRemotenessChange();
|
||||
if (this.curFrameId === null || remotenessChange) {
|
||||
if (this.browser) {
|
||||
if (this.tabBrowser) {
|
||||
// If we're setting up a new session on Firefox, we only process the
|
||||
// registration for this frame if it belongs to the current tab.
|
||||
if (!this.tab) {
|
||||
this.switchToTab(this.browser.selectedIndex);
|
||||
this.switchToTab();
|
||||
}
|
||||
|
||||
if (target == this.browserForTab) {
|
||||
this.updateIdForBrowser(this.browserForTab, uid);
|
||||
if (target == browser.getBrowserForTab(this.tab)) {
|
||||
this.updateIdForBrowser(browser.getBrowserForTab(this.tab), uid);
|
||||
this.mainContentId = uid;
|
||||
}
|
||||
} else {
|
||||
@ -271,7 +320,7 @@ browser.Context = class {
|
||||
// and may not apply on Fennec.
|
||||
if (this.driver.appName != "Firefox" ||
|
||||
this.tab === null ||
|
||||
this.browserForTab === null) {
|
||||
browser.getBrowserForTab(this.tab) === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -279,7 +328,7 @@ browser.Context = class {
|
||||
return true;
|
||||
}
|
||||
|
||||
let currentIsRemote = this.browserForTab.isRemoteBrowser;
|
||||
let currentIsRemote = browser.getBrowserForTab(this.tab).isRemoteBrowser;
|
||||
this._hasRemotenessChange = this._browserWasRemote !== currentIsRemote;
|
||||
this._browserWasRemote = currentIsRemote;
|
||||
return this._hasRemotenessChange;
|
||||
|
@ -191,14 +191,15 @@ Object.defineProperty(GeckoDriver.prototype, "windowHandles", {
|
||||
|
||||
while (winEn.hasMoreElements()) {
|
||||
let win = winEn.getNext();
|
||||
if (win.gBrowser) {
|
||||
let tabbrowser = win.gBrowser;
|
||||
for (let i = 0; i < tabbrowser.browsers.length; ++i) {
|
||||
let winId = this.getIdForBrowser(tabbrowser.getBrowserAtIndex(i));
|
||||
let tabBrowser = browser.getTabBrowser(win);
|
||||
|
||||
if (tabBrowser) {
|
||||
tabBrowser.tabs.forEach(tab => {
|
||||
let winId = this.getIdForBrowser(browser.getBrowserForTab(tab));
|
||||
if (winId !== null) {
|
||||
hs.push(winId);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// For other chrome windows beside the browser window, only count the window itself.
|
||||
let winId = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
@ -655,7 +656,9 @@ GeckoDriver.prototype.newSession = function*(cmd, resp) {
|
||||
yield registerBrowsers;
|
||||
yield browserListening;
|
||||
|
||||
this.curBrowser.browserForTab.focus();
|
||||
if (this.curBrowser.tab) {
|
||||
browser.getBrowserForTab(this.curBrowser.tab).focus();
|
||||
}
|
||||
|
||||
return {
|
||||
sessionId: this.sessionId,
|
||||
@ -814,7 +817,7 @@ GeckoDriver.prototype.executeScript = function*(cmd, resp) {
|
||||
* @param {string=} sandbox
|
||||
* Name of the sandbox to evaluate the script in. The sandbox is
|
||||
* cached for later re-use on the same Window object if
|
||||
* {@code newSandbox} is false. If he parameter is undefined,
|
||||
* {@code newSandbox} is false. If the parameter is undefined,
|
||||
* the script is evaluated in a mutable sandbox. If the parameter
|
||||
* is "system", it will be evaluted in a sandbox with elevated system
|
||||
* privileges, equivalent to chrome space.
|
||||
@ -972,7 +975,7 @@ GeckoDriver.prototype.get = function*(cmd, resp) {
|
||||
});
|
||||
|
||||
yield get;
|
||||
this.curBrowser.browserForTab.focus();
|
||||
browser.getBrowserForTab(this.curBrowser.tab).focus();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1199,7 +1202,6 @@ GeckoDriver.prototype.setWindowPosition = function (cmd, resp) {
|
||||
*/
|
||||
GeckoDriver.prototype.switchToWindow = function* (cmd, resp) {
|
||||
let switchTo = cmd.parameters.name;
|
||||
let isMobile = this.appName == "Fennec";
|
||||
let found;
|
||||
|
||||
let getOuterWindowId = function (win) {
|
||||
@ -1219,12 +1221,13 @@ GeckoDriver.prototype.switchToWindow = function* (cmd, resp) {
|
||||
while (winEn.hasMoreElements()) {
|
||||
let win = winEn.getNext();
|
||||
let outerId = getOuterWindowId(win);
|
||||
let tabbrowser = browser.getTabBrowser(win);
|
||||
|
||||
if (tabbrowser) {
|
||||
for (let i = 0; i < tabbrowser.tabs.length; ++i) {
|
||||
let contentBrowser = browser.getBrowserForTab(tabbrowser.tabs[i]);
|
||||
let contentWindowId = this.getIdForBrowser(contentBrowser);
|
||||
|
||||
if (win.gBrowser && !isMobile) {
|
||||
let tabbrowser = win.gBrowser;
|
||||
for (let i = 0; i < tabbrowser.browsers.length; ++i) {
|
||||
let browser = tabbrowser.getBrowserAtIndex(i);
|
||||
let contentWindowId = this.getIdForBrowser(browser);
|
||||
if (byNameOrId(win.name, contentWindowId, outerId)) {
|
||||
found = {
|
||||
win: win,
|
||||
@ -2114,8 +2117,9 @@ GeckoDriver.prototype.close = function (cmd, resp) {
|
||||
let win = winEn.getNext();
|
||||
|
||||
// For browser windows count the tabs. Otherwise take the window itself.
|
||||
if (win.gBrowser) {
|
||||
nwins += win.gBrowser.browsers.length;
|
||||
let tabbrowser = browser.getTabBrowser(win);
|
||||
if (tabbrowser) {
|
||||
nwins += tabbrowser.tabs.length;
|
||||
} else {
|
||||
nwins++;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette_driver.by import By
|
||||
from marionette_driver import By, Wait
|
||||
from marionette_driver.keys import Keys
|
||||
|
||||
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
|
||||
@ -18,45 +18,54 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
|
||||
else:
|
||||
self.mod_key = Keys.CONTROL
|
||||
|
||||
self.remote_uri = self.marionette.absolute_url("javascriptPage.html")
|
||||
self.marionette.navigate(self.remote_uri)
|
||||
self.remote_uri = self.marionette.absolute_url("windowHandles.html")
|
||||
|
||||
def tearDown(self):
|
||||
self.close_all_tabs()
|
||||
|
||||
super(TestAboutPages, self).tearDown()
|
||||
|
||||
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
|
||||
def open_tab_with_link(self):
|
||||
with self.marionette.using_context("content"):
|
||||
self.marionette.navigate(self.remote_uri)
|
||||
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
@skip_if_mobile("Bug 1333209 - Process killed because of connection loss")
|
||||
def test_back_forward(self):
|
||||
# Bug 1311041 - Prevent changing of window handle by forcing the test
|
||||
# to be run in a new tab.
|
||||
new_tab = self.open_tab(trigger='menu')
|
||||
new_tab = self.open_tab(trigger=self.open_tab_with_link)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
self.marionette.navigate("about:blank")
|
||||
self.marionette.navigate(self.remote_uri)
|
||||
|
||||
self.marionette.navigate("about:preferences")
|
||||
self.marionette.navigate("about:support")
|
||||
|
||||
self.marionette.go_back()
|
||||
Wait(self.marionette).until(lambda mn: mn.get_url() == self.remote_uri,
|
||||
message="'{}' hasn't been loaded".format(self.remote_uri))
|
||||
|
||||
self.wait_for_condition(
|
||||
lambda mn: mn.get_url() == self.remote_uri)
|
||||
# Bug 1332998 - Timeout loading the page
|
||||
# self.marionette.go_forward()
|
||||
# Wait(self.marionette).until(lambda mn: mn.get_url() == self.remote_uri,
|
||||
# message="'about:support' hasn't been loaded")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
|
||||
@skip_if_mobile("Bug 1333209 - Process killed because of connection loss")
|
||||
def test_navigate_non_remote_about_pages(self):
|
||||
# Bug 1311041 - Prevent changing of window handle by forcing the test
|
||||
# to be run in a new tab.
|
||||
new_tab = self.open_tab(trigger='menu')
|
||||
new_tab = self.open_tab(trigger=self.open_tab_with_link)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
self.marionette.navigate("about:blank")
|
||||
self.assertEqual(self.marionette.get_url(), "about:blank")
|
||||
self.marionette.navigate("about:preferences")
|
||||
self.assertEqual(self.marionette.get_url(), "about:preferences")
|
||||
self.marionette.navigate("about:support")
|
||||
self.assertEqual(self.marionette.get_url(), "about:support")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
@ -64,6 +73,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
|
||||
@skip_if_mobile("On Android no shortcuts are available")
|
||||
def test_navigate_shortcut_key(self):
|
||||
def open_with_shortcut():
|
||||
self.marionette.navigate(self.remote_uri)
|
||||
with self.marionette.using_context("chrome"):
|
||||
main_win = self.marionette.find_element(By.ID, "main-window")
|
||||
main_win.send_keys(self.mod_key, Keys.SHIFT, 'a')
|
||||
@ -71,43 +81,55 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
|
||||
new_tab = self.open_tab(trigger=open_with_shortcut)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
self.wait_for_condition(lambda mn: mn.get_url() == "about:addons")
|
||||
Wait(self.marionette).until(lambda mn: mn.get_url() == "about:addons",
|
||||
message="'about:addons' hasn't been loaded")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
|
||||
@skip_if_mobile("Interacting with chrome elements not available for Fennec")
|
||||
def test_type_to_non_remote_tab(self):
|
||||
# Bug 1311041 - Prevent changing of window handle by forcing the test
|
||||
# to be run in a new tab.
|
||||
new_tab = self.open_tab(trigger='menu')
|
||||
new_tab = self.open_tab(trigger=self.open_tab_with_link)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
with self.marionette.using_context("chrome"):
|
||||
urlbar = self.marionette.find_element(By.ID, 'urlbar')
|
||||
urlbar.send_keys(self.mod_key + 'a')
|
||||
urlbar.send_keys(self.mod_key + 'x')
|
||||
urlbar.send_keys('about:preferences' + Keys.ENTER)
|
||||
self.wait_for_condition(lambda mn: mn.get_url() == "about:preferences")
|
||||
urlbar.send_keys('about:support' + Keys.ENTER)
|
||||
Wait(self.marionette).until(lambda mn: mn.get_url() == "about:support",
|
||||
message="'about:support' hasn't been loaded")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
@skip_if_mobile("Interacting with chrome elements not available for Fennec")
|
||||
def test_type_to_remote_tab(self):
|
||||
# Bug 1311041 - Prevent changing of window handle by forcing the test
|
||||
# to be run in a new tab.
|
||||
new_tab = self.open_tab(trigger=self.open_tab_with_link)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
# about:blank keeps remoteness from remote_uri
|
||||
self.marionette.navigate("about:blank")
|
||||
with self.marionette.using_context("chrome"):
|
||||
urlbar = self.marionette.find_element(By.ID, 'urlbar')
|
||||
urlbar.send_keys(self.mod_key + 'a')
|
||||
urlbar.send_keys(self.mod_key + 'x')
|
||||
urlbar.send_keys(self.remote_uri + Keys.ENTER)
|
||||
|
||||
self.wait_for_condition(lambda mn: mn.get_url() == self.remote_uri)
|
||||
Wait(self.marionette).until(lambda mn: mn.get_url() == self.remote_uri,
|
||||
message="'{}' hasn't been loaded".format(self.remote_uri))
|
||||
|
||||
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
|
||||
@skip_if_mobile("Needs application independent method to open a new tab")
|
||||
def test_hang(self):
|
||||
# Open a new tab and close the first one
|
||||
new_tab = self.open_tab(trigger="menu")
|
||||
# Bug 1311041 - Prevent changing of window handle by forcing the test
|
||||
# to be run in a new tab.
|
||||
new_tab = self.open_tab(trigger=self.open_tab_with_link)
|
||||
|
||||
# Close the start tab
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
|
||||
|
@ -1,183 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette_driver import By, Wait
|
||||
from marionette_driver.keys import Keys
|
||||
|
||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||
|
||||
|
||||
class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestWindowHandles, self).setUp()
|
||||
|
||||
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||
self.marionette.navigate(self.test_page)
|
||||
|
||||
def tearDown(self):
|
||||
self.close_all_windows()
|
||||
self.close_all_tabs()
|
||||
|
||||
super(TestWindowHandles, self).tearDown()
|
||||
|
||||
def test_new_tab_window_handles(self):
|
||||
keys = []
|
||||
if self.marionette.session_capabilities['platformName'] == 'darwin':
|
||||
keys.append(Keys.META)
|
||||
else:
|
||||
keys.append(Keys.CONTROL)
|
||||
keys.append('t')
|
||||
|
||||
def open_with_shortcut():
|
||||
with self.marionette.using_context("chrome"):
|
||||
main_win = self.marionette.find_element(By.ID, "main-window")
|
||||
main_win.send_keys(*keys)
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_shortcut)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), "about:newtab")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
def test_new_tab_window_handles_no_switch(self):
|
||||
"""Regression test for bug 1294456.
|
||||
This test is testing the case where Marionette attempts to send a
|
||||
command to a window handle when the browser has opened and selected
|
||||
a new tab. Before bug 1294456 landed, the Marionette driver was getting
|
||||
confused about which window handle the client cared about, and assumed
|
||||
it was the window handle for the newly opened and selected tab.
|
||||
|
||||
This caused Marionette to think that the browser needed to do a remoteness
|
||||
flip in the e10s case, since the tab opened by menu_newNavigatorTab is
|
||||
about:newtab (which is currently non-remote). This meant that commands
|
||||
sent to what should have been the original window handle would be
|
||||
queued and never sent, since the remoteness flip in the new tab was
|
||||
never going to happen.
|
||||
"""
|
||||
def open_with_menu():
|
||||
with self.marionette.using_context("chrome"):
|
||||
menu_new_tab = self.marionette.find_element(By.ID, 'menu_newNavigatorTab')
|
||||
menu_new_tab.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_menu)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
# We still have the default tab set as our window handle. This
|
||||
# get_url command should be sent immediately, and not be forever-queued.
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
def test_link_opened_tab_window_handles(self):
|
||||
def open_with_link():
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), "about:blank")
|
||||
self.assertEqual(self.marionette.title, "")
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
self.assertEqual(self.marionette.title, "Marionette New Tab Link")
|
||||
|
||||
self.marionette.close()
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), "about:blank")
|
||||
|
||||
def test_chrome_windows(self):
|
||||
# We open a chrome window but are actually interested in the new tab.
|
||||
new_window = self.open_window(
|
||||
trigger=lambda: self.marionette.find_element(By.ID, "new-window").click())
|
||||
with self.marionette.using_context("chrome"):
|
||||
self.marionette.switch_to_window(new_window)
|
||||
|
||||
# Check that the new tab is available and wait until it has been loaded.
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
new_tab = self.marionette.current_window_handle
|
||||
Wait(self.marionette).until(lambda _: self.marionette.get_url() == self.test_page,
|
||||
message="Test page hasn't been loaded for newly opened tab")
|
||||
|
||||
link_new_tab = self.marionette.find_element(By.ID, "new-tab")
|
||||
for i in range(3):
|
||||
self.open_tab(trigger=lambda: link_new_tab.click())
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
# No more chrome windows should be opened
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles),
|
||||
len(self.start_windows) + 1)
|
||||
|
||||
self.marionette.close_chrome_window()
|
||||
self.marionette.switch_to_window(self.start_window)
|
||||
|
||||
def test_chrome_window_handles_with_scopes(self):
|
||||
# Ensure that we work in chrome scope so we don't have any limitations
|
||||
with self.marionette.using_context("chrome"):
|
||||
# Open a browser and a non-browser (about window) chrome window
|
||||
self.open_window(
|
||||
trigger=lambda: self.marionette.execute_script("window.open();"))
|
||||
self.open_window(
|
||||
trigger=lambda: self.marionette.find_element(By.ID, "aboutName").click())
|
||||
|
||||
handles_in_chrome_scope = self.marionette.chrome_window_handles
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.chrome_window_handles,
|
||||
handles_in_chrome_scope)
|
||||
|
||||
def test_tab_and_window_handles(self):
|
||||
window_open_page = self.marionette.absolute_url("test_windows.html")
|
||||
results_page = self.marionette.absolute_url("resultPage.html")
|
||||
|
||||
# Open a new tab and switch to it.
|
||||
def open_tab_with_link():
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
second_tab = self.open_tab(trigger=open_tab_with_link)
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), 1)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
self.marionette.switch_to_window(second_tab)
|
||||
self.assertEqual(self.marionette.get_url(), "about:blank")
|
||||
|
||||
# Open a new window from the new tab and only care about the second new tab
|
||||
def open_window_with_link():
|
||||
link = self.marionette.find_element(By.LINK_TEXT, "Open new window")
|
||||
link.click()
|
||||
|
||||
# We open a new window but are actually interested in the new tab
|
||||
self.marionette.navigate(window_open_page)
|
||||
third_tab = self.open_tab(trigger=open_window_with_link)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
# Check that the new tab has the correct page loaded
|
||||
self.marionette.switch_to_window(third_tab)
|
||||
self.assertEqual(self.marionette.get_url(), results_page)
|
||||
|
||||
self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
# Return to our original tab and close it.
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.marionette.close()
|
||||
self.assertEquals(len(self.marionette.window_handles), 2)
|
||||
|
||||
# Close the opened window and carry on in our second tab.
|
||||
self.marionette.switch_to_window(third_tab)
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), 1)
|
||||
|
||||
self.marionette.switch_to_window(second_tab)
|
||||
self.assertEqual(self.marionette.get_url(), results_page)
|
||||
self.marionette.navigate("about:blank")
|
||||
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), 1)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
@ -0,0 +1,181 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette_driver import By, Wait
|
||||
|
||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||
|
||||
|
||||
class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestWindowHandles, self).setUp()
|
||||
|
||||
self.empty_page = self.marionette.absolute_url("empty.html")
|
||||
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||
self.marionette.navigate(self.test_page)
|
||||
|
||||
self.marionette.set_context("chrome")
|
||||
|
||||
def tearDown(self):
|
||||
self.close_all_windows()
|
||||
self.close_all_tabs()
|
||||
|
||||
super(TestWindowHandles, self).tearDown()
|
||||
|
||||
def test_chrome_window_handles_with_scopes(self):
|
||||
# Open a browser and a non-browser (about window) chrome window
|
||||
self.open_window(
|
||||
trigger=lambda: self.marionette.execute_script("window.open();"))
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
self.open_window(
|
||||
trigger=lambda: self.marionette.find_element(By.ID, "aboutName").click())
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 2)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
chrome_window_handles_in_chrome_scope = self.marionette.chrome_window_handles
|
||||
window_handles_in_chrome_scope = self.marionette.window_handles
|
||||
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.chrome_window_handles,
|
||||
chrome_window_handles_in_chrome_scope)
|
||||
self.assertEqual(self.marionette.window_handles,
|
||||
window_handles_in_chrome_scope)
|
||||
|
||||
def test_chrome_window_handles_after_opening_new_window(self):
|
||||
def open_with_link():
|
||||
with self.marionette.using_context("content"):
|
||||
link = self.marionette.find_element(By.ID, "new-window")
|
||||
link.click()
|
||||
|
||||
# We open a new window but are actually interested in the new tab
|
||||
new_win = self.open_window(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows) + 1)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
|
||||
# Check that the new tab has the correct page loaded
|
||||
self.marionette.switch_to_window(new_win)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, new_win)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
# Close the opened window and carry on in our original tab.
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
|
||||
|
||||
self.marionette.switch_to_window(self.start_window)
|
||||
self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
def test_window_handles_after_opening_new_tab(self):
|
||||
def open_with_link():
|
||||
with self.marionette.using_context("content"):
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
def test_window_handles_after_opening_new_window(self):
|
||||
def open_with_link():
|
||||
with self.marionette.using_context("content"):
|
||||
link = self.marionette.find_element(By.ID, "new-window")
|
||||
link.click()
|
||||
|
||||
# We open a new window but are actually interested in the new tab
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
# Check that the new tab has the correct page loaded
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
# Close the opened window and carry on in our original tab.
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
def test_window_handles_after_closing_original_tab(self):
|
||||
def open_with_link():
|
||||
with self.marionette.using_context("content"):
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
def test_window_handles_no_switch(self):
|
||||
"""Regression test for bug 1294456.
|
||||
This test is testing the case where Marionette attempts to send a
|
||||
command to a window handle when the browser has opened and selected
|
||||
a new tab. Before bug 1294456 landed, the Marionette driver was getting
|
||||
confused about which window handle the client cared about, and assumed
|
||||
it was the window handle for the newly opened and selected tab.
|
||||
|
||||
This caused Marionette to think that the browser needed to do a remoteness
|
||||
flip in the e10s case, since the tab opened by menu_newNavigatorTab is
|
||||
about:newtab (which is currently non-remote). This meant that commands
|
||||
sent to what should have been the original window handle would be
|
||||
queued and never sent, since the remoteness flip in the new tab was
|
||||
never going to happen.
|
||||
"""
|
||||
def open_with_menu():
|
||||
menu_new_tab = self.marionette.find_element(By.ID, 'menu_newNavigatorTab')
|
||||
menu_new_tab.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_menu)
|
||||
|
||||
# We still have the default tab set as our window handle. This
|
||||
# get_url command should be sent immediately, and not be forever-queued.
|
||||
with self.marionette.using_context("content"):
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
@ -0,0 +1,85 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette_driver import By
|
||||
|
||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||
|
||||
|
||||
class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestWindowHandles, self).setUp()
|
||||
|
||||
self.empty_page = self.marionette.absolute_url("empty.html")
|
||||
self.test_page = self.marionette.absolute_url("windowHandles.html")
|
||||
self.marionette.navigate(self.test_page)
|
||||
|
||||
def tearDown(self):
|
||||
self.close_all_tabs()
|
||||
|
||||
super(TestWindowHandles, self).tearDown()
|
||||
|
||||
def test_window_handles_after_opening_new_tab(self):
|
||||
def open_with_link():
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
def test_window_handles_after_opening_new_window(self):
|
||||
def open_with_link():
|
||||
link = self.marionette.find_element(By.ID, "new-window")
|
||||
link.click()
|
||||
|
||||
# We open a new window but are actually interested in the new tab
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
|
||||
# Check that the new tab has the correct page loaded
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
||||
|
||||
# Close the opened window and carry on in our original tab.
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(self.start_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, self.start_tab)
|
||||
self.assertEqual(self.marionette.get_url(), self.test_page)
|
||||
|
||||
def test_window_handles_after_closing_original_tab(self):
|
||||
def open_with_link():
|
||||
link = self.marionette.find_element(By.ID, "new-tab")
|
||||
link.click()
|
||||
|
||||
new_tab = self.open_tab(trigger=open_with_link)
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs) + 1)
|
||||
self.assertNotEqual(self.marionette.current_window_handle, new_tab)
|
||||
|
||||
self.marionette.close()
|
||||
self.assertEqual(len(self.marionette.window_handles), len(self.start_tabs))
|
||||
|
||||
self.marionette.switch_to_window(new_tab)
|
||||
self.assertEqual(self.marionette.current_window_handle, new_tab)
|
||||
self.assertEqual(self.marionette.get_url(), self.empty_page)
|
@ -75,7 +75,8 @@ skip-if = appname == 'fennec'
|
||||
[test_window_close_content.py]
|
||||
[test_window_position.py]
|
||||
skip-if = appname == 'fennec'
|
||||
[test_window_handles.py]
|
||||
[test_window_handles_content.py]
|
||||
[test_window_handles_chrome.py]
|
||||
skip-if = appname == 'fennec'
|
||||
|
||||
[test_screenshot.py]
|
||||
|
@ -8,7 +8,7 @@
|
||||
<title>Marionette New Tab Link</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="about:blank" id="new-tab" target="_blank">Click me!</a>
|
||||
<a href="about:blank" id="new-window" onClick='javascript:window.open("windowHandles.html", null, "location=1,toolbar=1");'>Click me!</a>
|
||||
<a href="empty.html" id="new-tab" target="_blank">Click me!</a>
|
||||
<a href="" id="new-window" onClick='javascript:window.open("empty.html", null, "location=1,toolbar=1");'>Click me!</a>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user