Bug 1259055 - Use window management class for handling of new tabs.
MozReview-Commit-ID: Le8ltn1IbU4
--- a/testing/marionette/harness/marionette/__init__.py
+++ b/testing/marionette/harness/marionette/__init__.py
@@ -5,16 +5,17 @@
__version__ = '3.2.0'
from .marionette_test import (
CommonTestCase,
expectedFailure,
MarionetteJSTestCase,
MarionetteTestCase,
skip,
+ skip_if_chrome,
skip_if_desktop,
skip_if_mobile,
SkipTest,
skip_unless_protocol,
)
from .runner import (
BaseMarionetteArguments,
BaseMarionetteTestRunner,
@@ -27,9 +28,10 @@ from .runner import (
Marionette,
MarionetteTest,
MarionetteTestResult,
MarionetteTextTestRunner,
MemoryEnduranceTestCaseMixin,
TestManifest,
TestResult,
TestResultCollection,
+ WindowManagerMixin,
)
--- a/testing/marionette/harness/marionette/runner/__init__.py
+++ b/testing/marionette/harness/marionette/runner/__init__.py
@@ -19,9 +19,10 @@ from .mixins import (
EnduranceTestCaseMixin,
HTMLReportingArguments,
HTMLReportingTestResultMixin,
HTMLReportingTestRunnerMixin,
MemoryEnduranceTestCaseMixin,
BrowserMobProxyTestCaseMixin,
BrowserMobProxyArguments,
BrowserMobTestCase,
+ WindowManagerMixin,
)
--- a/testing/marionette/harness/marionette/runner/mixins/__init__.py
+++ b/testing/marionette/harness/marionette/runner/mixins/__init__.py
@@ -14,8 +14,12 @@ from .reporting import (
HTMLReportingTestRunnerMixin,
)
from .browsermob import (
BrowserMobProxyTestCaseMixin,
BrowserMobProxyArguments,
BrowserMobTestCase,
)
+
+from .window_manager import (
+ WindowManagerMixin,
+)
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette/runner/mixins/window_manager.py
@@ -0,0 +1,67 @@
+# 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/.
+
+import sys
+
+from marionette_driver import By, Wait
+
+
+class WindowManagerMixin(object):
+
+ _menu_item_new_tab = (By.ID, "menu_newNavigatorTab")
+
+ def setUp(self):
+ super(WindowManagerMixin, self).setUp()
+
+ self.start_tab = self.marionette.current_window_handle
+ self.start_tabs = self.marionette.window_handles
+
+ def tearDown(self):
+ try:
+ if len(self.marionette.window_handles) != len(self.start_tabs):
+ raise Exception("Not all tabs as opened by the test have been closed")
+ finally:
+ super(WindowManagerMixin, self).tearDown()
+
+ def close_all_tabs(self):
+ current_window_handles = self.marionette.window_handles
+
+ # If the start tab is not present anymore, use the next one of the list
+ if self.start_tab not in current_window_handles:
+ self.start_tab = current_window_handles[0]
+
+ current_window_handles.remove(self.start_tab)
+ for handle in current_window_handles:
+ self.marionette.switch_to_window(handle)
+ self.marionette.close()
+
+ # Bug 1311350 - close() doesn't wait for tab to be closed.
+ Wait(self.marionette).until(
+ lambda mn: handle not in mn.window_handles,
+ message="Failed to close tab with handle {}".format(handle)
+ )
+
+ self.marionette.switch_to_window(self.start_tab)
+
+ def open_tab(self, trigger="menu"):
+ current_tabs = self.marionette.window_handles
+
+ try:
+ if callable(trigger):
+ trigger()
+ elif trigger == 'menu':
+ with self.marionette.using_context("chrome"):
+ self.marionette.find_element(*self._menu_item_new_tab).click()
+ except Exception:
+ exc, val, tb = sys.exc_info()
+ raise exc, 'Failed to trigger opening a new tab: {}'.format(val), tb
+ else:
+ Wait(self.marionette).until(
+ lambda mn: len(mn.window_handles) == len(current_tabs) + 1,
+ message="No new tab has been opened"
+ )
+
+ [new_tab] = list(set(self.marionette.window_handles) - set(current_tabs))
+
+ return new_tab
--- a/testing/marionette/harness/marionette/tests/unit/test_about_pages.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_about_pages.py
@@ -1,93 +1,107 @@
# 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 import MarionetteTestCase
-from marionette.marionette_test import skip_if_e10s
+from marionette import MarionetteTestCase, WindowManagerMixin
from marionette_driver.keys import Keys
from marionette_driver.by import By
-class TestAboutPages(MarionetteTestCase):
+class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
def setUp(self):
- MarionetteTestCase.setUp(self)
+ super(TestAboutPages, self).setUp()
+
if self.marionette.session_capabilities['platformName'] == 'darwin':
self.mod_key = Keys.META
else:
self.mod_key = Keys.CONTROL
self.remote_uri = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(self.remote_uri)
+ def tearDown(self):
+ self.close_all_tabs()
+
+ super(TestAboutPages, self).tearDown()
+
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')
+ 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.go_back()
self.wait_for_condition(
lambda mn: mn.get_url() == self.remote_uri)
+ self.marionette.close()
+ self.marionette.switch_to_window(self.start_tab)
+
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')
+ 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")
- def test_navigate_shortcut_key(self):
- self.marionette.navigate("about:preferences")
- self.marionette.navigate(self.remote_uri)
- self.marionette.navigate("about:blank")
+ self.marionette.close()
+ self.marionette.switch_to_window(self.start_tab)
- start_win = self.marionette.current_window_handle
- start_win_handles = self.marionette.window_handles
- 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')
+ def test_navigate_shortcut_key(self):
+ def open_with_shortcut():
+ 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')
+
+ new_tab = self.open_tab(trigger=open_with_shortcut)
+ self.marionette.switch_to_window(new_tab)
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 2)
- self.assertEqual(start_win, self.marionette.current_window_handle)
- [new_tab] = list(set(self.marionette.window_handles) - set(start_win_handles))
+ self.wait_for_condition(lambda mn: mn.get_url() == "about:addons")
+
+ self.marionette.close()
+ self.marionette.switch_to_window(self.start_tab)
+
+ 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')
self.marionette.switch_to_window(new_tab)
- self.wait_for_condition(lambda mn: mn.get_url() == "about:addons")
- self.marionette.close()
- self.marionette.switch_to_window(start_win)
- @skip_if_e10s
- def test_type_to_non_remote_tab(self):
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")
+ self.marionette.close()
+ self.marionette.switch_to_window(self.start_tab)
+
def test_type_to_remote_tab(self):
- self.marionette.navigate("about:preferences")
+ # 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)
def test_hang(self):
- self.marionette.set_context('chrome')
- initial_tab = self.marionette.window_handles[0]
-
# Open a new tab and close the first one
- new_tab = self.marionette.find_element(By.ID, 'menu_newNavigatorTab')
- new_tab.click()
-
- new_tab = [handle for handle in self.marionette.window_handles if
- handle != initial_tab][0]
+ new_tab = self.open_tab(trigger="menu")
self.marionette.close()
self.marionette.switch_to_window(new_tab)
- with self.marionette.using_context('content'):
- self.marionette.navigate(self.remote_uri)
+ self.marionette.navigate(self.remote_uri)
--- a/testing/marionette/harness/marionette/tests/unit/test_window_handles.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_window_handles.py
@@ -1,98 +1,99 @@
# 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 import MarionetteTestCase
+from marionette import MarionetteTestCase, WindowManagerMixin
from marionette_driver.keys import Keys
-from marionette_driver import By
+from marionette_driver import By, Wait
-class TestWindowHandles(MarionetteTestCase):
+class TestWindowHandles(WindowManagerMixin, MarionetteTestCase):
+
+ def tearDown(self):
+ try:
+ self.close_all_tabs()
+ finally:
+ 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')
- origin_win = self.marionette.current_window_handle
+ 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)
- with self.marionette.using_context("chrome"):
- main_win = self.marionette.find_element(By.ID, "main-window")
- main_win.send_keys(*keys)
-
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 2)
- handles = self.marionette.window_handles
- handles.remove(origin_win)
- new_tab = handles.pop()
+ 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(origin_win)
- self.assertEqual(self.marionette.get_url(), "about:blank")
+ 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()
- with self.marionette.using_context("chrome"):
- menu_new_tab = self.marionette.find_element(By.ID, 'menu_newNavigatorTab')
- menu_new_tab.click()
-
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 2)
+ 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(), "about:blank")
- self.marionette.switch_to_window(self.marionette.window_handles[1])
+ self.marionette.switch_to_window(new_tab)
self.marionette.close()
- self.marionette.switch_to_window(self.marionette.window_handles[0])
+ self.marionette.switch_to_window(self.start_tab)
def test_link_opened_tab_window_handles(self):
tab_testpage = self.marionette.absolute_url("windowHandles.html")
self.marionette.navigate(tab_testpage)
- start_win = self.marionette.current_window_handle
- link = self.marionette.find_element(By.ID, "new-tab")
- link.click()
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 2)
+
+ def open_with_link():
+ link = self.marionette.find_element(By.ID, "new-tab")
+ link.click()
- handles = self.marionette.window_handles
- handles.remove(start_win)
- dest_win = handles.pop()
+ new_tab = self.open_tab(trigger=open_with_link)
+ self.assertEqual(self.marionette.current_window_handle, self.start_tab)
- self.marionette.switch_to_window(dest_win)
+ 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(start_win)
+ self.marionette.switch_to_window(self.start_tab)
- self.assertIn('windowHandles.html', self.marionette.get_url())
+ self.assertEqual(self.marionette.get_url(), tab_testpage)
self.assertEqual(self.marionette.title, "Marionette New Tab Link")
self.marionette.close()
- self.marionette.switch_to_window(dest_win)
+ self.marionette.switch_to_window(new_tab)
self.assertEqual(self.marionette.get_url(), "about:blank")
def test_chrome_windows(self):
opener_page = self.marionette.absolute_url("windowHandles.html")
self.marionette.navigate(opener_page)
start_win = self.marionette.current_chrome_window_handle
@@ -146,68 +147,60 @@ class TestWindowHandles(MarionetteTestCa
self.marionette.switch_to_window(start_tab)
self.assertEqual(len(self.marionette.chrome_window_handles), 1)
self.assertEqual(len(self.marionette.window_handles), 1)
self.assertEqual(self.marionette.current_window_handle, start_tab)
def test_tab_and_window_handles(self):
- start_tab = self.marionette.current_window_handle
start_chrome_window = self.marionette.current_chrome_window_handle
+
tab_open_page = self.marionette.absolute_url("windowHandles.html")
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.
- self.marionette.navigate(tab_open_page)
- link = self.marionette.find_element(By.ID, "new-tab")
- link.click()
+ def open_tab_with_link():
+ self.marionette.navigate(tab_open_page)
+ link = self.marionette.find_element(By.ID, "new-tab")
+ link.click()
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 2)
+ 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, start_chrome_window)
- handles = self.marionette.window_handles
- handles.remove(start_tab)
-
- new_tab = handles.pop()
- self.marionette.switch_to_window(new_tab)
+ self.marionette.switch_to_window(second_tab)
self.assertEqual(self.marionette.get_url(), "about:blank")
- # Open a new window from the new tab.
- self.marionette.navigate(window_open_page)
+ # Open a new window from the new tab and only care about the second new tab
+ def open_win_with_link():
+ self.marionette.navigate(window_open_page)
+ link = self.marionette.find_element(By.LINK_TEXT, "Open new window")
+ link.click()
- link = self.marionette.find_element(By.LINK_TEXT, "Open new window")
- link.click()
- self.wait_for_condition(lambda mn: len(mn.window_handles) == 3)
-
+ third_tab = self.open_tab(trigger=open_win_with_link)
self.assertEqual(len(self.marionette.chrome_window_handles), 2)
self.assertEqual(self.marionette.current_chrome_window_handle, start_chrome_window)
- # Find the new window and switch to it.
- handles = self.marionette.window_handles
- handles.remove(start_tab)
- handles.remove(new_tab)
- new_window = handles.pop()
-
- self.marionette.switch_to_window(new_window)
- results_page = self.marionette.absolute_url("resultPage.html")
+ # 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.assertEqual(len(self.marionette.chrome_window_handles), 2)
self.assertNotEqual(self.marionette.current_chrome_window_handle, start_chrome_window)
# Return to our original tab and close it.
- self.marionette.switch_to_window(start_tab)
+ 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 new tab.
- self.marionette.switch_to_window(new_window)
+ # 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(new_tab)
+ 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, start_chrome_window)
--- a/testing/marionette/harness/marionette/tests/unit/test_window_management.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_window_management.py
@@ -4,38 +4,39 @@
import time
from marionette import MarionetteTestCase
from marionette_driver import By, Wait
class TestSwitchWindow(MarionetteTestCase):
def open_new_window(self):
- self.marionette.set_context("chrome")
- self.marionette.set_script_timeout(5000)
- self.marionette.execute_async_script("""
-var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(Components.interfaces.nsIWindowWatcher);
-var win = ww.openWindow(null, "chrome://browser/content/browser.xul", "testWin", null, null);
-win.addEventListener("load", function() {
- win.removeEventListener("load", arguments.callee, true);
- marionetteScriptFinished();
-}, null);
-""")
- self.marionette.set_context("content")
+ with self.marionette.using_context("chrome"):
+ print '**** %s' % self.marionette.execute_async_script("""
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Components.interfaces.nsIWindowWatcher);
+ var win = ww.openWindow(null, "chrome://browser/content/browser.xul",
+ "testWin", null, null);
+ win.addEventListener("load", function() {
+ marionetteScriptFinished(true);
+ }, {once: true});
+ dump(win.readyState);
+ if (win.readyState == 'loaded')
+ marionetteScriptFinished(true);
+ """)
def close_new_window(self):
self.marionette.set_context("chrome")
self.marionette.execute_script("""
-var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(Components.interfaces.nsIWindowWatcher);
-var win = ww.getWindowByName("testWin", null);
-if (win != null)
- win.close();
-""")
+ var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Components.interfaces.nsIWindowWatcher);
+ var win = ww.getWindowByName("testWin", null);
+ if (win != null)
+ win.close();
+ """)
self.marionette.set_context("content")
def test_windows(self):
orig_win = self.marionette.current_chrome_window_handle
orig_available = self.marionette.chrome_window_handles
self.open_new_window()
# assert we're still in the original window
self.assertEqual(self.marionette.current_chrome_window_handle, orig_win)