diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/firefox-ui/tests/puppeteer | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/firefox-ui/tests/puppeteer')
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/manifest.ini | 24 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_about_window.py | 74 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_appinfo.py | 31 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_l10n.py | 51 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_menubar.py | 30 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_notifications.py | 82 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_page_info_window.py | 100 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_places.py | 85 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_security.py | 45 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_software_update.py | 134 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_tabbar.py | 191 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_toolbars.py | 283 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_update_wizard.py | 67 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_utils.py | 48 | ||||
-rw-r--r-- | testing/firefox-ui/tests/puppeteer/test_windows.py | 259 |
15 files changed, 1504 insertions, 0 deletions
diff --git a/testing/firefox-ui/tests/puppeteer/manifest.ini b/testing/firefox-ui/tests/puppeteer/manifest.ini new file mode 100644 index 000000000..2eb24b6dc --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/manifest.ini @@ -0,0 +1,24 @@ +[DEFAULT] +tags = local + +# API tests +[test_appinfo.py] +[test_l10n.py] +[test_places.py] +[test_security.py] +tags = remote +[test_software_update.py] +tags = remote +[test_utils.py] + +# UI tests +[test_about_window.py] +[test_menubar.py] +[test_notifications.py] +[test_page_info_window.py] +[test_tabbar.py] +[test_toolbars.py] +tags = remote +[test_update_wizard.py] +tags = remote +[test_windows.py] diff --git a/testing/firefox-ui/tests/puppeteer/test_about_window.py b/testing/firefox-ui/tests/puppeteer/test_about_window.py new file mode 100644 index 000000000..c957211bb --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_about_window.py @@ -0,0 +1,74 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.ui.deck import Panel +from marionette_harness import MarionetteTestCase + + +class TestAboutWindow(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestAboutWindow, self).setUp() + + self.about_window = self.browser.open_about_window() + self.deck = self.about_window.deck + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + super(TestAboutWindow, self).tearDown() + + def test_basic(self): + self.assertEqual(self.about_window.window_type, 'Browser:About') + + def test_elements(self): + """Test correct retrieval of elements.""" + self.assertNotEqual(self.about_window.dtds, []) + + self.assertEqual(self.deck.element.get_property('localName'), 'deck') + + # apply panel + panel = self.deck.apply + self.assertEqual(panel.element.get_property('localName'), 'hbox') + self.assertEqual(panel.button.get_property('localName'), 'button') + + # check_for_updates panel + panel = self.deck.check_for_updates + self.assertEqual(panel.element.get_property('localName'), 'hbox') + self.assertEqual(panel.button.get_property('localName'), 'button') + + # checking_for_updates panel + self.assertEqual(self.deck.checking_for_updates.element.get_property('localName'), 'hbox') + + # download_and_install panel + panel = self.deck.download_and_install + self.assertEqual(panel.element.get_property('localName'), 'hbox') + self.assertEqual(panel.button.get_property('localName'), 'button') + + # download_failed panel + self.assertEqual(self.deck.download_failed.element.get_property('localName'), 'hbox') + + # downloading panel + self.assertEqual(self.deck.downloading.element.get_property('localName'), 'hbox') + + # check deck attributes + self.assertIsInstance(self.deck.selected_index, int) + self.assertIsInstance(self.deck.selected_panel, Panel) + + def test_open_window(self): + """Test various opening strategies.""" + def opener(win): + self.browser.menubar.select_by_id('helpMenu', 'aboutName') + + open_strategies = ('menu', + opener, + ) + + self.about_window.close() + for trigger in open_strategies: + about_window = self.browser.open_about_window(trigger=trigger) + self.assertEquals(about_window, self.puppeteer.windows.current) + about_window.close() diff --git a/testing/firefox-ui/tests/puppeteer/test_appinfo.py b/testing/firefox-ui/tests/puppeteer/test_appinfo.py new file mode 100644 index 000000000..f0be0f616 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_appinfo.py @@ -0,0 +1,31 @@ +# 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 mozversion + +from firefox_puppeteer import PuppeteerMixin +from marionette_harness import MarionetteTestCase + + +class TestAppInfo(PuppeteerMixin, MarionetteTestCase): + + def test_valid_properties(self): + binary = self.marionette.bin + version_info = mozversion.get_version(binary=binary) + + self.assertEqual(self.puppeteer.appinfo.ID, version_info['application_id']) + self.assertEqual(self.puppeteer.appinfo.name, version_info['application_name']) + self.assertEqual(self.puppeteer.appinfo.vendor, version_info['application_vendor']) + self.assertEqual(self.puppeteer.appinfo.version, version_info['application_version']) + # Bug 1298328 - Platform buildid mismatch due to incremental builds + # self.assertEqual(self.puppeteer.appinfo.platformBuildID, + # version_info['platform_buildid']) + self.assertEqual(self.puppeteer.appinfo.platformVersion, version_info['platform_version']) + self.assertIsNotNone(self.puppeteer.appinfo.locale) + self.assertIsNotNone(self.puppeteer.appinfo.user_agent) + self.assertIsNotNone(self.puppeteer.appinfo.XPCOMABI) + + def test_invalid_properties(self): + with self.assertRaises(AttributeError): + self.puppeteer.appinfo.unknown diff --git a/testing/firefox-ui/tests/puppeteer/test_l10n.py b/testing/firefox-ui/tests/puppeteer/test_l10n.py new file mode 100644 index 000000000..08f41f9d7 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_l10n.py @@ -0,0 +1,51 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.api.l10n import L10n +from marionette_driver import By +from marionette_driver.errors import NoSuchElementException +from marionette_harness import MarionetteTestCase + + +class TestL10n(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestL10n, self).setUp() + + self.l10n = L10n(self.marionette) + + def test_dtd_entity_chrome(self): + dtds = ['chrome://global/locale/about.dtd', + 'chrome://browser/locale/baseMenuOverlay.dtd'] + + value = self.l10n.localize_entity(dtds, 'helpSafeMode.label') + elm = self.marionette.find_element(By.ID, 'helpSafeMode') + self.assertEqual(value, elm.get_attribute('label')) + + self.assertRaises(NoSuchElementException, + self.l10n.localize_entity, dtds, 'notExistent') + + def test_dtd_entity_content(self): + dtds = ['chrome://global/locale/about.dtd', + 'chrome://global/locale/aboutSupport.dtd'] + + value = self.l10n.localize_entity(dtds, 'aboutSupport.pageTitle') + + self.marionette.set_context(self.marionette.CONTEXT_CONTENT) + self.marionette.navigate('about:support') + + elm = self.marionette.find_element(By.TAG_NAME, 'title') + self.assertEqual(value, elm.text) + + def test_properties(self): + properties = ['chrome://global/locale/filepicker.properties', + 'chrome://global/locale/findbar.properties'] + + # TODO: Find a way to verify the retrieved translated string + value = self.l10n.localize_property(properties, 'NotFound') + self.assertNotEqual(value, '') + + self.assertRaises(NoSuchElementException, + self.l10n.localize_property, properties, 'notExistent') diff --git a/testing/firefox-ui/tests/puppeteer/test_menubar.py b/testing/firefox-ui/tests/puppeteer/test_menubar.py new file mode 100644 index 000000000..ddc6117bf --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_menubar.py @@ -0,0 +1,30 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from marionette_driver.errors import NoSuchElementException +from marionette_harness import MarionetteTestCase + + +class TestMenuBar(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestMenuBar, self).setUp() + + def test_click_item_in_menubar(self): + def opener(_): + self.browser.menubar.select_by_id('file-menu', + 'menu_newNavigatorTab') + + self.browser.tabbar.open_tab(trigger=opener) + + self.browser.tabbar.tabs[-1].close() + + def test_click_non_existent_menu_and_item(self): + with self.assertRaises(NoSuchElementException): + self.browser.menubar.select_by_id('foobar-menu', + 'menu_newNavigatorTab') + + with self.assertRaises(NoSuchElementException): + self.browser.menubar.select_by_id('file-menu', 'menu_foobar') diff --git a/testing/firefox-ui/tests/puppeteer/test_notifications.py b/testing/firefox-ui/tests/puppeteer/test_notifications.py new file mode 100644 index 000000000..de44c7434 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_notifications.py @@ -0,0 +1,82 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.ui.browser.notifications import ( + AddOnInstallFailedNotification, + AddOnInstallConfirmationNotification, +) +from marionette_driver import By +from marionette_driver.errors import TimeoutException +from marionette_harness import MarionetteTestCase + + +class TestNotifications(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestNotifications, self).setUp() + + self.marionette.set_pref('extensions.install.requireSecureOrigin', False) + + self.addons_url = self.marionette.absolute_url('addons/extensions/') + self.puppeteer.utils.permissions.add(self.marionette.baseurl, 'install') + + def tearDown(self): + try: + self.marionette.clear_pref('extensions.install.requireSecureOrigin') + self.marionette.clear_pref('xpinstall.signatures.required') + + self.puppeteer.utils.permissions.remove(self.addons_url, 'install') + + if self.browser.notification: + self.browser.notification.close(force=True) + finally: + super(TestNotifications, self).tearDown() + + def test_open_close_notification(self): + """Trigger and dismiss a notification""" + self.assertIsNone(self.browser.notification) + self.trigger_addon_notification('restartless_addon_signed.xpi') + self.browser.notification.close() + self.assertIsNone(self.browser.notification) + + def test_wait_for_notification_timeout(self): + """Wait for a notification when one is not shown""" + message = 'No notification was shown' + with self.assertRaisesRegexp(TimeoutException, message): + self.browser.wait_for_notification() + + def test_wait_for_specific_notification_timeout(self): + """Wait for a notification when one is not shown""" + message = 'AddOnInstallFailedNotification was not shown' + with self.assertRaisesRegexp(TimeoutException, message): + self.browser.wait_for_notification(AddOnInstallFailedNotification) + + def test_wait_for_no_notification_timeout(self): + """Wait for no notification when one is shown""" + message = 'Unexpected notification shown' + self.trigger_addon_notification('restartless_addon_signed.xpi') + with self.assertRaisesRegexp(TimeoutException, message): + self.browser.wait_for_notification(None) + + def test_notification_with_origin(self): + """Trigger a notification with an origin""" + self.trigger_addon_notification('restartless_addon_signed.xpi') + self.assertIn(self.browser.notification.origin, self.marionette.baseurl) + self.assertIsNotNone(self.browser.notification.label) + + def test_addon_install_failed_notification(self): + """Trigger add-on blocked notification using an unsigned add-on""" + # Ensure that installing unsigned extensions will fail + self.marionette.set_pref('xpinstall.signatures.required', True) + + self.trigger_addon_notification( + 'restartless_addon_unsigned.xpi', + notification=AddOnInstallFailedNotification) + + def trigger_addon_notification(self, addon, notification=AddOnInstallConfirmationNotification): + with self.marionette.using_context('content'): + self.marionette.navigate(self.addons_url) + self.marionette.find_element(By.LINK_TEXT, addon).click() + self.browser.wait_for_notification(notification) diff --git a/testing/firefox-ui/tests/puppeteer/test_page_info_window.py b/testing/firefox-ui/tests/puppeteer/test_page_info_window.py new file mode 100644 index 000000000..d86cbee3c --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_page_info_window.py @@ -0,0 +1,100 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from marionette_harness import MarionetteTestCase + + +class TestPageInfoWindow(PuppeteerMixin, MarionetteTestCase): + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + super(TestPageInfoWindow, self).tearDown() + + def test_elements(self): + """Test correct retrieval of elements.""" + page_info = self.browser.open_page_info_window() + + self.assertNotEqual(page_info.dtds, []) + self.assertNotEqual(page_info.properties, []) + + self.assertEqual(page_info.deck.element.get_property('localName'), 'deck') + + # feed panel + self.assertEqual(page_info.deck.feed.element.get_property('localName'), 'vbox') + + # general panel + self.assertEqual(page_info.deck.general.element.get_property('localName'), 'vbox') + + # media panel + self.assertEqual(page_info.deck.media.element.get_property('localName'), 'vbox') + + # permissions panel + self.assertEqual(page_info.deck.permissions.element.get_property('localName'), 'vbox') + + # security panel + panel = page_info.deck.select(page_info.deck.security) + + self.assertEqual(panel.element.get_property('localName'), 'vbox') + + self.assertEqual(panel.domain.get_property('localName'), 'textbox') + self.assertEqual(panel.owner.get_property('localName'), 'textbox') + self.assertEqual(panel.verifier.get_property('localName'), 'textbox') + + self.assertEqual(panel.view_certificate.get_property('localName'), 'button') + self.assertEqual(panel.view_cookies.get_property('localName'), 'button') + self.assertEqual(panel.view_passwords.get_property('localName'), 'button') + + def test_select(self): + """Test properties and methods for switching between panels.""" + page_info = self.browser.open_page_info_window() + deck = page_info.deck + + self.assertEqual(deck.selected_panel, deck.general) + + self.assertEqual(deck.select(deck.security), deck.security) + self.assertEqual(deck.selected_panel, deck.security) + + def test_open_window(self): + """Test various opening strategies.""" + def opener(win): + self.browser.menubar.select_by_id('tools-menu', 'menu_pageInfo') + + open_strategies = ('menu', + 'shortcut', + opener, + ) + + for trigger in open_strategies: + if trigger == 'shortcut' and self.puppeteer.platform == 'windows_nt': + # The shortcut for page info window does not exist on windows. + self.assertRaises(ValueError, self.browser.open_page_info_window, + trigger=trigger) + continue + + page_info = self.browser.open_page_info_window(trigger=trigger) + self.assertEquals(page_info, self.puppeteer.windows.current) + page_info.close() + + def test_close_window(self): + """Test various closing strategies.""" + def closer(win): + win.send_shortcut(win.localize_entity('closeWindow.key'), + accel=True) + + # Close a tab by each trigger method + close_strategies = ('menu', + 'shortcut', + closer, + ) + for trigger in close_strategies: + # menu only works on OS X + if trigger == 'menu' and self.puppeteer.platform != 'darwin': + continue + + page_info = self.browser.open_page_info_window() + page_info.close(trigger=trigger) + self.assertTrue(page_info.closed) diff --git a/testing/firefox-ui/tests/puppeteer/test_places.py b/testing/firefox-ui/tests/puppeteer/test_places.py new file mode 100644 index 000000000..95d0f23a4 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_places.py @@ -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 firefox_puppeteer import PuppeteerMixin +from marionette_driver import By, Wait +from marionette_harness import MarionetteTestCase + + +class TestPlaces(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestPlaces, self).setUp() + + self.urls = [self.marionette.absolute_url('layout/mozilla_governance.html'), + self.marionette.absolute_url('layout/mozilla_grants.html'), + ] + + def tearDown(self): + try: + self.puppeteer.places.restore_default_bookmarks() + self.puppeteer.places.remove_all_history() + finally: + super(TestPlaces, self).tearDown() + + def get_all_urls_in_history(self): + return self.marionette.execute_script(""" + let hs = Components.classes["@mozilla.org/browser/nav-history-service;1"] + .getService(Components.interfaces.nsINavHistoryService); + let urls = []; + + let options = hs.getNewQueryOptions(); + options.resultType = options.RESULTS_AS_URI; + + let root = hs.executeQuery(hs.getNewQuery(), options).root + root.containerOpen = true; + for (let i = 0; i < root.childCount; i++) { + urls.push(root.getChild(i).uri) + } + root.containerOpen = false; + + return urls; + """) + + def test_plugins(self): + # TODO: Once we use a plugin, add a test case to verify that the data will be removed + self.puppeteer.places.clear_plugin_data() + + def test_bookmarks(self): + star_button = self.marionette.find_element(By.ID, 'bookmarks-menu-button') + + # Visit URLs and bookmark them all + for url in self.urls: + with self.marionette.using_context('content'): + self.marionette.navigate(url) + + Wait(self.marionette).until( + lambda _: self.puppeteer.places.is_bookmark_star_button_ready()) + star_button.click() + Wait(self.marionette).until(lambda _: self.puppeteer.places.is_bookmarked(url)) + + ids = self.puppeteer.places.get_folder_ids_for_url(url) + self.assertEqual(len(ids), 1) + self.assertEqual(ids[0], self.puppeteer.places.bookmark_folders.unfiled) + + # Restore default bookmarks, so the added URLs are gone + self.puppeteer.places.restore_default_bookmarks() + for url in self.urls: + self.assertFalse(self.puppeteer.places.is_bookmarked(url)) + + def test_history(self): + self.assertEqual(len(self.get_all_urls_in_history()), 0) + + # Visit pages and check that they are all present + def load_urls(): + with self.marionette.using_context('content'): + for url in self.urls: + self.marionette.navigate(url) + self.puppeteer.places.wait_for_visited(self.urls, load_urls) + + self.assertEqual(self.get_all_urls_in_history(), self.urls) + + # Check that both pages are no longer in the remove_all_history + self.puppeteer.places.remove_all_history() + self.assertEqual(len(self.get_all_urls_in_history()), 0) diff --git a/testing/firefox-ui/tests/puppeteer/test_security.py b/testing/firefox-ui/tests/puppeteer/test_security.py new file mode 100644 index 000000000..879053e5a --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_security.py @@ -0,0 +1,45 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.errors import NoCertificateError +from marionette_harness import MarionetteTestCase + + +class TestSecurity(PuppeteerMixin, MarionetteTestCase): + + def test_get_address_from_certificate(self): + url = 'https://ssl-ev.mozqa.com' + + with self.marionette.using_context(self.marionette.CONTEXT_CONTENT): + self.marionette.navigate(url) + + cert = self.browser.tabbar.tabs[0].certificate + self.assertIn(cert['commonName'], url) + self.assertEqual(cert['organization'], 'Mozilla Corporation') + self.assertEqual(cert['issuerOrganization'], 'DigiCert Inc') + + address = self.puppeteer.security.get_address_from_certificate(cert) + self.assertIsNotNone(address) + self.assertIsNotNone(address['city']) + self.assertIsNotNone(address['country']) + self.assertIsNotNone(address['postal_code']) + self.assertIsNotNone(address['state']) + self.assertIsNotNone(address['street']) + + def test_get_certificate(self): + url_http = self.marionette.absolute_url('layout/mozilla.html') + url_https = 'https://ssl-ev.mozqa.com' + + # Test EV certificate + with self.marionette.using_context(self.marionette.CONTEXT_CONTENT): + self.marionette.navigate(url_https) + cert = self.browser.tabbar.tabs[0].certificate + self.assertIn(cert['commonName'], url_https) + + # HTTP connections do not have a SSL certificate + with self.marionette.using_context(self.marionette.CONTEXT_CONTENT): + self.marionette.navigate(url_http) + with self.assertRaises(NoCertificateError): + self.browser.tabbar.tabs[0].certificate diff --git a/testing/firefox-ui/tests/puppeteer/test_software_update.py b/testing/firefox-ui/tests/puppeteer/test_software_update.py new file mode 100644 index 000000000..4bad47d94 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_software_update.py @@ -0,0 +1,134 @@ +# 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 os + +from firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.api.software_update import SoftwareUpdate +from marionette_harness import MarionetteTestCase + + +class TestSoftwareUpdate(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestSoftwareUpdate, self).setUp() + + self.software_update = SoftwareUpdate(self.marionette) + + self.saved_mar_channels = self.software_update.mar_channels.channels + self.software_update.mar_channels.channels = set(['expected', 'channels']) + + def tearDown(self): + try: + self.software_update.mar_channels.channels = self.saved_mar_channels + finally: + super(TestSoftwareUpdate, self).tearDown() + + def test_abi(self): + self.assertTrue(self.software_update.ABI) + + def test_allowed(self): + self.assertTrue(self.software_update.allowed) + + def test_build_info(self): + build_info = self.software_update.build_info + self.assertEqual(build_info['disabled_addons'], None) + self.assertIn('Mozilla/', build_info['user_agent']) + self.assertEqual(build_info['mar_channels'], set(['expected', 'channels'])) + self.assertTrue(build_info['version']) + self.assertTrue(build_info['buildid'].isdigit()) + self.assertTrue(build_info['locale']) + self.assertIn('force=1', build_info['update_url']) + self.assertIn('xml', build_info['update_snippet']) + self.assertEqual(build_info['channel'], self.software_update.update_channel) + + def test_force_fallback(self): + status_file = os.path.join(self.software_update.staging_directory, 'update.status') + + try: + self.software_update.force_fallback() + with open(status_file, 'r') as f: + content = f.read() + self.assertEqual(content, 'failed: 6\n') + finally: + os.remove(status_file) + + def test_get_update_url(self): + update_url = self.software_update.get_update_url() + self.assertIn('Firefox', update_url) + self.assertNotIn('force=1', update_url) + update_url = self.software_update.get_update_url(True) + self.assertIn('Firefox', update_url) + self.assertIn('force=1', update_url) + + def test_os_version(self): + self.assertTrue(self.software_update.os_version) + + def test_staging_directory(self): + self.assertTrue(self.software_update.staging_directory) + + +class TestUpdateChannel(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestUpdateChannel, self).setUp() + + self.software_update = SoftwareUpdate(self.marionette) + + self.saved_channel = self.software_update.update_channel + self.software_update.update_channel = 'expected_channel' + + def tearDown(self): + try: + self.software_update.update_channel = self.saved_channel + finally: + super(TestUpdateChannel, self).tearDown() + + def test_update_channel_default_channel(self): + # Without a restart the update channel will not change. + self.assertEqual(self.software_update.update_channel, self.saved_channel) + + def test_update_channel_set_channel(self): + try: + # Use the clean option to force a non in_app restart, which would allow + # Firefox to dump the logs to the console. + self.restart(clean=True) + self.assertEqual(self.software_update.update_channel, 'expected_channel') + finally: + self.software_update.update_channel = self.saved_channel + self.restart(clean=True) + + +class TestMARChannels(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestMARChannels, self).setUp() + + self.software_update = SoftwareUpdate(self.marionette) + + self.saved_mar_channels = self.software_update.mar_channels.channels + self.software_update.mar_channels.channels = set(['expected', 'channels']) + + def tearDown(self): + try: + self.software_update.mar_channels.channels = self.saved_mar_channels + finally: + super(TestMARChannels, self).tearDown() + + def test_mar_channels_channels(self): + self.assertEqual(self.software_update.mar_channels.channels, set(['expected', 'channels'])) + + def test_mar_channels_set_channels(self): + self.software_update.mar_channels.channels = set(['a', 'b', 'c']) + self.assertEqual(self.software_update.mar_channels.channels, set(['a', 'b', 'c'])) + + def test_mar_channels_add_channels(self): + self.software_update.mar_channels.add_channels(set(['some', 'new', 'channels'])) + self.assertEqual( + self.software_update.mar_channels.channels, + set(['expected', 'channels', 'some', 'new'])) + + def test_mar_channels_remove_channels(self): + self.software_update.mar_channels.remove_channels(set(['expected'])) + self.assertEqual(self.software_update.mar_channels.channels, set(['channels'])) diff --git a/testing/firefox-ui/tests/puppeteer/test_tabbar.py b/testing/firefox-ui/tests/puppeteer/test_tabbar.py new file mode 100644 index 000000000..7da3f7ee7 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_tabbar.py @@ -0,0 +1,191 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.errors import NoCertificateError +from marionette_harness import MarionetteTestCase + + +class TestTabBar(PuppeteerMixin, MarionetteTestCase): + + def tearDown(self): + try: + self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]]) + finally: + super(TestTabBar, self).tearDown() + + def test_basics(self): + tabbar = self.browser.tabbar + + self.assertEqual(tabbar.window, self.browser) + + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + + self.assertEqual(tabbar.newtab_button.get_property('localName'), 'toolbarbutton') + self.assertEqual(tabbar.toolbar.get_property('localName'), 'tabs') + + def test_open_close(self): + tabbar = self.browser.tabbar + + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.selected_index, 0) + + # Open with default trigger, and force closing the tab + tabbar.open_tab() + tabbar.close_tab(force=True) + + # Open a new tab by each trigger method + open_strategies = ('button', + 'menu', + 'shortcut', + lambda tab: tabbar.newtab_button.click() + ) + for trigger in open_strategies: + new_tab = tabbar.open_tab(trigger=trigger) + self.assertEqual(len(tabbar.tabs), 2) + self.assertEqual(new_tab.handle, self.marionette.current_window_handle) + self.assertEqual(new_tab.handle, tabbar.tabs[1].handle) + + tabbar.close_tab() + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + self.assertNotEqual(new_tab.handle, tabbar.tabs[0].handle) + + # Close a tab by each trigger method + close_strategies = ('button', + 'menu', + 'shortcut', + lambda tab: tab.close_button.click()) + for trigger in close_strategies: + new_tab = tabbar.open_tab() + self.assertEqual(len(tabbar.tabs), 2) + self.assertEqual(new_tab.handle, self.marionette.current_window_handle) + self.assertEqual(new_tab.handle, tabbar.tabs[1].handle) + + tabbar.close_tab(trigger=trigger) + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + self.assertNotEqual(new_tab.handle, tabbar.tabs[0].handle) + + def test_close_not_selected_tab(self): + tabbar = self.browser.tabbar + + new_tab = tabbar.open_tab() + tabbar.close_tab(tabbar.tabs[0], trigger="button") + + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(new_tab, tabbar.tabs[0]) + + def test_close_all_tabs_except_first(self): + tabbar = self.browser.tabbar + + orig_tab = tabbar.tabs[0] + + for i in range(0, 3): + tabbar.open_tab() + + tabbar.close_all_tabs([orig_tab]) + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(orig_tab.handle, self.marionette.current_window_handle) + + def test_switch_to(self): + tabbar = self.browser.tabbar + + # Open a new tab in the foreground (will be auto-selected) + new_tab = tabbar.open_tab() + self.assertEqual(new_tab.handle, self.marionette.current_window_handle) + self.assertEqual(tabbar.selected_index, 1) + self.assertEqual(tabbar.selected_tab, new_tab) + + # Switch by index + tabbar.switch_to(0) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + + # Switch by tab + tabbar.switch_to(new_tab) + self.assertEqual(new_tab.handle, self.marionette.current_window_handle) + + # Switch by callback + tabbar.switch_to(lambda tab: tab.window.tabbar.selected_tab != tab) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + + tabbar.close_tab(tabbar.tabs[1]) + + +class TestTab(PuppeteerMixin, MarionetteTestCase): + + def tearDown(self): + try: + self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]]) + finally: + super(TestTab, self).tearDown() + + def test_basic(self): + tab = self.browser.tabbar.tabs[0] + + self.assertEqual(tab.window, self.browser) + + self.assertEqual(tab.tab_element.get_property('localName'), 'tab') + self.assertEqual(tab.close_button.get_property('localName'), 'toolbarbutton') + + def test_certificate(self): + url = self.marionette.absolute_url('layout/mozilla.html') + + with self.marionette.using_context(self.marionette.CONTEXT_CONTENT): + self.marionette.navigate(url) + with self.assertRaises(NoCertificateError): + self.browser.tabbar.tabs[0].certificate + + def test_close(self): + tabbar = self.browser.tabbar + + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.selected_index, 0) + + # Force closing the tab + new_tab = tabbar.open_tab() + new_tab.close(force=True) + + # Close a tab by each trigger method + close_strategies = ('button', + 'menu', + 'shortcut', + lambda tab: tab.close_button.click()) + for trigger in close_strategies: + new_tab = tabbar.open_tab() + self.assertEqual(len(tabbar.tabs), 2) + self.assertEqual(new_tab.handle, self.marionette.current_window_handle) + self.assertEqual(new_tab.handle, tabbar.tabs[1].handle) + + new_tab.close(trigger=trigger) + self.assertEqual(len(tabbar.tabs), 1) + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + self.assertNotEqual(new_tab.handle, tabbar.tabs[0].handle) + + def test_location(self): + url = self.marionette.absolute_url('layout/mozilla.html') + with self.marionette.using_context(self.marionette.CONTEXT_CONTENT): + self.marionette.navigate(url) + self.assertEqual(self.browser.tabbar.tabs[0].location, url) + + def test_switch_to(self): + tabbar = self.browser.tabbar + + new_tab = tabbar.open_tab() + + # Switch to the first tab, which will not select it + tabbar.tabs[0].switch_to() + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + # Bug 1128656: We cannot test as long as switch_to_window() auto-selects the tab + # self.assertEqual(tabbar.selected_index, 1) + # self.assertEqual(tabbar.selected_tab, new_tab) + + # Now select the first tab + tabbar.tabs[0].select() + self.assertEqual(tabbar.tabs[0].handle, self.marionette.current_window_handle) + self.assertTrue(tabbar.tabs[0].selected) + self.assertFalse(tabbar.tabs[1].selected) + + new_tab.close() diff --git a/testing/firefox-ui/tests/puppeteer/test_toolbars.py b/testing/firefox-ui/tests/puppeteer/test_toolbars.py new file mode 100644 index 000000000..8150be7e1 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_toolbars.py @@ -0,0 +1,283 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from marionette_driver import expected, By, Wait +from marionette_driver.errors import NoSuchElementException +from marionette_harness import MarionetteTestCase + + +class TestNavBar(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestNavBar, self).setUp() + + self.navbar = self.browser.navbar + self.url = self.marionette.absolute_url('layout/mozilla.html') + + with self.marionette.using_context('content'): + self.marionette.navigate('about:blank') + + # TODO: check why self.puppeteer.places.remove_all_history() does not work here + self.marionette.execute_script(""" + let count = gBrowser.sessionHistory.count; + gBrowser.sessionHistory.PurgeHistory(count); + """) + + def test_elements(self): + self.assertEqual(self.navbar.back_button.get_property('localName'), 'toolbarbutton') + self.assertEqual(self.navbar.forward_button.get_property('localName'), 'toolbarbutton') + self.assertEqual(self.navbar.home_button.get_property('localName'), 'toolbarbutton') + self.assertEqual(self.navbar.menu_button.get_property('localName'), 'toolbarbutton') + self.assertEqual(self.navbar.toolbar.get_property('localName'), 'toolbar') + + def test_buttons(self): + self.marionette.set_context('content') + + # Load initial web page + self.marionette.navigate(self.url) + Wait(self.marionette).until(expected.element_present(lambda m: + m.find_element(By.ID, 'mozilla_logo'))) + + with self.marionette.using_context('chrome'): + # Both buttons are disabled + self.assertFalse(self.navbar.back_button.is_enabled()) + self.assertFalse(self.navbar.forward_button.is_enabled()) + + # Go to the homepage + self.navbar.home_button.click() + + Wait(self.marionette).until(expected.element_not_present(lambda m: + m.find_element(By.ID, 'mozilla_logo'))) + self.assertEqual(self.marionette.get_url(), self.browser.default_homepage) + + with self.marionette.using_context('chrome'): + # Only back button is enabled + self.assertTrue(self.navbar.back_button.is_enabled()) + self.assertFalse(self.navbar.forward_button.is_enabled()) + + # Navigate back + self.navbar.back_button.click() + + Wait(self.marionette).until(expected.element_present(lambda m: + m.find_element(By.ID, 'mozilla_logo'))) + self.assertEqual(self.marionette.get_url(), self.url) + + with self.marionette.using_context('chrome'): + # Only forward button is enabled + self.assertFalse(self.navbar.back_button.is_enabled()) + self.assertTrue(self.navbar.forward_button.is_enabled()) + + # Navigate forward + self.navbar.forward_button.click() + + Wait(self.marionette).until(expected.element_not_present(lambda m: + m.find_element(By.ID, 'mozilla_logo'))) + self.assertEqual(self.marionette.get_url(), self.browser.default_homepage) + + +class TestLocationBar(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestLocationBar, self).setUp() + + self.locationbar = self.browser.navbar.locationbar + + def test_elements(self): + self.assertEqual(self.locationbar.urlbar.get_property('localName'), 'textbox') + self.assertIn('urlbar-input', self.locationbar.urlbar_input.get_property('className')) + + self.assertEqual(self.locationbar.connection_icon.get_property('localName'), 'image') + self.assertEqual(self.locationbar.identity_box.get_property('localName'), 'box') + self.assertEqual(self.locationbar.identity_country_label.get_property('localName'), + 'label') + self.assertEqual(self.locationbar.identity_organization_label.get_property('localName'), + 'label') + self.assertEqual(self.locationbar.identity_icon.get_property('localName'), 'image') + self.assertEqual(self.locationbar.history_drop_marker.get_property('localName'), + 'dropmarker') + self.assertEqual(self.locationbar.reload_button.get_property('localName'), + 'toolbarbutton') + self.assertEqual(self.locationbar.stop_button.get_property('localName'), + 'toolbarbutton') + + self.assertEqual(self.locationbar.contextmenu.get_property('localName'), 'menupopup') + self.assertEqual(self.locationbar.get_contextmenu_entry('paste').get_attribute('cmd'), + 'cmd_paste') + + def test_reload(self): + event_types = ["shortcut", "shortcut2", "button"] + for event in event_types: + # TODO: Until we have waitForPageLoad, this only tests API + # compatibility. + self.locationbar.reload_url(event, force=True) + self.locationbar.reload_url(event, force=False) + + def test_focus_and_clear(self): + self.locationbar.urlbar.send_keys("zyx") + self.locationbar.clear() + self.assertEqual(self.locationbar.value, '') + + self.locationbar.urlbar.send_keys("zyx") + self.assertEqual(self.locationbar.value, 'zyx') + + self.locationbar.clear() + self.assertEqual(self.locationbar.value, '') + + def test_load_url(self): + data_uri = 'data:text/html,<title>Title</title>' + self.locationbar.load_url(data_uri) + + with self.marionette.using_context('content'): + Wait(self.marionette).until(lambda mn: mn.get_url() == data_uri) + + +class TestAutoCompleteResults(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestAutoCompleteResults, self).setUp() + + self.browser.navbar.locationbar.clear() + + self.autocomplete_results = self.browser.navbar.locationbar.autocomplete_results + + def tearDown(self): + try: + self.autocomplete_results.close(force=True) + except NoSuchElementException: + # TODO: A NoSuchElementException is thrown here when tests accessing the + # autocomplete_results element are skipped. + pass + finally: + super(TestAutoCompleteResults, self).tearDown() + + def test_popup_elements(self): + # TODO: This test is not very robust because it relies on the history + # in the default profile. + self.assertFalse(self.autocomplete_results.is_open) + self.browser.navbar.locationbar.urlbar.send_keys('a') + results = self.autocomplete_results.results + Wait(self.marionette).until(lambda _: self.autocomplete_results.is_complete) + visible_result_count = len(self.autocomplete_results.visible_results) + self.assertTrue(visible_result_count > 0) + self.assertEqual(visible_result_count, + int(results.get_property('itemCount'))) + + def test_close(self): + self.browser.navbar.locationbar.urlbar.send_keys('a') + Wait(self.marionette).until(lambda _: self.autocomplete_results.is_open) + # The Wait in the library implementation will fail this if this doesn't + # end up closing. + self.autocomplete_results.close() + + def test_force_close(self): + self.browser.navbar.locationbar.urlbar.send_keys('a') + Wait(self.marionette).until(lambda _: self.autocomplete_results.is_open) + # The Wait in the library implementation will fail this if this doesn't + # end up closing. + self.autocomplete_results.close(force=True) + + def test_matching_text(self): + # The default profile always has existing bookmarks. So no sites have to + # be visited and bookmarked. + for input_text in ('about', 'zilla'): + self.browser.navbar.locationbar.urlbar.clear() + self.browser.navbar.locationbar.urlbar.send_keys(input_text) + Wait(self.marionette).until(lambda _: self.autocomplete_results.is_open) + Wait(self.marionette).until(lambda _: self.autocomplete_results.is_complete) + visible_results = self.autocomplete_results.visible_results + self.assertTrue(len(visible_results) > 0) + + for result in visible_results: + # check matching text only for results of type bookmark + if result.get_attribute('type') != 'bookmark': + continue + title_matches = self.autocomplete_results.get_matching_text(result, "title") + url_matches = self.autocomplete_results.get_matching_text(result, "url") + all_matches = title_matches + url_matches + self.assertTrue(len(all_matches) > 0) + for match_fragment in all_matches: + self.assertIn(match_fragment.lower(), input_text) + + self.autocomplete_results.close() + + +class TestIdentityPopup(PuppeteerMixin, MarionetteTestCase): + def setUp(self): + super(TestIdentityPopup, self).setUp() + + self.locationbar = self.browser.navbar.locationbar + self.identity_popup = self.locationbar.identity_popup + + self.url = 'https://ssl-ev.mozqa.com' + + with self.marionette.using_context('content'): + self.marionette.navigate(self.url) + + def tearDown(self): + try: + self.identity_popup.close(force=True) + finally: + super(TestIdentityPopup, self).tearDown() + + def test_elements(self): + self.locationbar.open_identity_popup() + + # Test main view elements + main = self.identity_popup.view.main + self.assertEqual(main.element.get_property('localName'), 'panelview') + + self.assertEqual(main.expander.get_property('localName'), 'button') + self.assertEqual(main.host.get_property('localName'), 'label') + self.assertEqual(main.insecure_connection_label.get_property('localName'), + 'description') + self.assertEqual(main.internal_connection_label.get_property('localName'), + 'description') + self.assertEqual(main.secure_connection_label.get_property('localName'), + 'description') + + self.assertEqual(main.permissions.get_property('localName'), 'vbox') + + # Test security view elements + security = self.identity_popup.view.security + self.assertEqual(security.element.get_property('localName'), 'panelview') + + self.assertEqual(security.host.get_property('localName'), 'label') + self.assertEqual(security.insecure_connection_label.get_property('localName'), + 'description') + self.assertEqual(security.secure_connection_label.get_property('localName'), + 'description') + + self.assertEqual(security.owner.get_property('localName'), 'description') + self.assertEqual(security.owner_location.get_property('localName'), 'description') + self.assertEqual(security.verifier.get_property('localName'), 'description') + + self.assertEqual(security.disable_mixed_content_blocking_button.get_property('localName'), + 'button') + self.assertEqual(security.enable_mixed_content_blocking_button.get_property('localName'), + 'button') + + self.assertEqual(security.more_info_button.get_property('localName'), 'button') + + def test_open_close(self): + with self.marionette.using_context('content'): + self.marionette.navigate(self.url) + + self.assertFalse(self.identity_popup.is_open) + + self.locationbar.open_identity_popup() + + self.identity_popup.close() + self.assertFalse(self.identity_popup.is_open) + + def test_force_close(self): + with self.marionette.using_context('content'): + self.marionette.navigate(self.url) + + self.assertFalse(self.identity_popup.is_open) + + self.locationbar.open_identity_popup() + + self.identity_popup.close(force=True) + self.assertFalse(self.identity_popup.is_open) diff --git a/testing/firefox-ui/tests/puppeteer/test_update_wizard.py b/testing/firefox-ui/tests/puppeteer/test_update_wizard.py new file mode 100644 index 000000000..7170ea8e2 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_update_wizard.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/. + +from firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.ui.deck import Panel +from firefox_puppeteer.ui.update_wizard import UpdateWizardDialog +from marionette_harness import MarionetteTestCase + + +class TestUpdateWizard(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestUpdateWizard, self).setUp() + + def opener(win): + self.marionette.execute_script(""" + let updatePrompt = Components.classes["@mozilla.org/updates/update-prompt;1"] + .createInstance(Components.interfaces.nsIUpdatePrompt); + updatePrompt.checkForUpdates(); + """) + + self.dialog = self.browser.open_window(callback=opener, + expected_window_class=UpdateWizardDialog) + self.wizard = self.dialog.wizard + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + super(TestUpdateWizard, self).tearDown() + + def test_basic(self): + self.assertEqual(self.dialog.window_type, 'Update:Wizard') + self.assertNotEqual(self.dialog.dtds, []) + self.assertNotEqual(self.dialog.properties, []) + + def test_elements(self): + """Test correct retrieval of elements.""" + self.assertEqual(self.wizard.element.get_property('localName'), 'wizard') + + buttons = ('cancel_button', 'extra1_button', 'extra2_button', + 'finish_button', 'next_button', 'previous_button', + ) + for button in buttons: + self.assertEqual(getattr(self.wizard, button).get_property('localName'), + 'button') + + panels = ('checking', 'downloading', 'dummy', 'error_patching', 'error', + 'error_extra', 'finished', 'finished_background', + 'manual_update', 'no_updates_found', 'updates_found_basic', + ) + for panel in panels: + self.assertEqual(getattr(self.wizard, panel).element.get_property('localName'), + 'wizardpage') + + # elements of the checking panel + self.assertEqual(self.wizard.checking.progress.get_property('localName'), + 'progressmeter') + + # elements of the downloading panel + self.assertEqual(self.wizard.downloading.progress.get_property('localName'), + 'progressmeter') + + # check wizard attributes + self.assertIsInstance(self.wizard.selected_index, int) + self.assertIsInstance(self.wizard.selected_panel, Panel) diff --git a/testing/firefox-ui/tests/puppeteer/test_utils.py b/testing/firefox-ui/tests/puppeteer/test_utils.py new file mode 100644 index 000000000..664722cce --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_utils.py @@ -0,0 +1,48 @@ +# 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 firefox_puppeteer import PuppeteerMixin +from marionette_harness import MarionetteTestCase + + +class TestSanitize(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + super(TestSanitize, self).setUp() + + # Clear all previous history and cookies. + self.puppeteer.places.remove_all_history() + with self.marionette.using_context('content'): + self.marionette.delete_all_cookies() + + self.urls = [ + 'layout/mozilla_projects.html', + 'layout/mozilla.html', + 'layout/mozilla_mission.html', + 'cookies/cookie_single.html' + ] + self.urls = [self.marionette.absolute_url(url) for url in self.urls] + + # Open the test urls, including the single cookie setting page. + def load_urls(): + with self.marionette.using_context('content'): + for url in self.urls: + self.marionette.navigate(url) + self.puppeteer.places.wait_for_visited(self.urls, load_urls) + + def test_sanitize_history(self): + """ Clears history. """ + self.assertEqual(self.puppeteer.places.get_all_urls_in_history(), self.urls) + self.puppeteer.utils.sanitize(data_type={"history": True}) + self.assertEqual(self.puppeteer.places.get_all_urls_in_history(), []) + + def test_sanitize_cookies(self): + """ Clears cookies. """ + with self.marionette.using_context('content'): + self.assertIsNotNone(self.marionette.get_cookie('litmus_1')) + + self.puppeteer.utils.sanitize(data_type={"cookies": True}) + + with self.marionette.using_context('content'): + self.assertIsNone(self.marionette.get_cookie('litmus_1')) diff --git a/testing/firefox-ui/tests/puppeteer/test_windows.py b/testing/firefox-ui/tests/puppeteer/test_windows.py new file mode 100644 index 000000000..1ba13fa37 --- /dev/null +++ b/testing/firefox-ui/tests/puppeteer/test_windows.py @@ -0,0 +1,259 @@ +# 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 firefox_puppeteer.errors as errors + +from firefox_puppeteer import PuppeteerMixin +from firefox_puppeteer.ui.windows import BaseWindow +from marionette_driver import By, Wait +from marionette_driver.errors import NoSuchWindowException +from marionette_harness import MarionetteTestCase + + +class BaseWindowTestCase(PuppeteerMixin, MarionetteTestCase): + + def setUp(self): + """ + These tests open and close windows pretty rapidly, which + (since bug 1261842) can cause content processes to be + spawned and discarded in large numbers. By default, Firefox + has a 5 second timeout for shutting down content processes, + but we can get into cases where the content process just + doesn't have enough time to get itself all sorted before + the timeout gets hit, which results in the parent killing + the content process manually, which generates a crash report, + which causes these tests to orange. We side-step this by + setting dom.ipc.tabs.shutdownTimeoutSecs to 0, which disables + the shutdown timer. + """ + super(BaseWindowTestCase, self).setUp() + + self.marionette.set_pref('dom.ipc.tabs.shutdownTimeoutSecs', 0) + + def tearDown(self): + try: + self.marionette.clear_pref('dom.ipc.tabs.shutdownTimeoutSecs') + finally: + super(BaseWindowTestCase, self).tearDown() + + +class TestWindows(BaseWindowTestCase): + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + super(TestWindows, self).tearDown() + + def test_switch_to(self): + url = self.marionette.absolute_url('layout/mozilla.html') + + # Open two more windows + for index in range(0, 2): + self.marionette.execute_script(""" window.open(); """) + + windows = self.puppeteer.windows.all + self.assertEquals(len(windows), 3) + + # Switch to the 2nd window + self.puppeteer.windows.switch_to(windows[1].handle) + self.assertEquals(windows[1].handle, self.marionette.current_chrome_window_handle) + + # TODO: Needs updated tabs module for improved navigation + with self.marionette.using_context('content'): + self.marionette.navigate(url) + + # Switch to the last window and find 2nd window by URL + self.puppeteer.windows.switch_to(windows[2].handle) + + # TODO: A window can have multiple tabs, so this may need an update + # when the tabs module gets implemented + def find_by_url(win): + with win.marionette.using_context('content'): + return win.marionette.get_url() == url + + self.puppeteer.windows.switch_to(find_by_url) + self.assertEquals(windows[1].handle, self.marionette.current_chrome_window_handle) + + self.puppeteer.windows.switch_to(find_by_url) + + # Switching to an unknown handles has to fail + self.assertRaises(NoSuchWindowException, + self.puppeteer.windows.switch_to, "humbug") + self.assertRaises(NoSuchWindowException, + self.puppeteer.windows.switch_to, lambda win: False) + + self.puppeteer.windows.close_all([self.browser]) + self.browser.switch_to() + + self.assertEqual(len(self.puppeteer.windows.all), 1) + + def test_switch_to_unknown_window_type(self): + def open_by_js(_): + with self.marionette.using_context('chrome'): + self.marionette.execute_script(""" + window.open('chrome://browser/content/safeMode.xul', '_blank', + 'chrome,centerscreen,resizable=no'); + """) + + win = self.browser.open_window(callback=open_by_js, expected_window_class=BaseWindow) + win.close() + self.browser.switch_to() + + +class TestBaseWindow(BaseWindowTestCase): + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + BaseWindowTestCase.tearDown(self) + + def test_basics(self): + # force BaseWindow instance + win1 = BaseWindow(self.marionette, self.browser.handle) + + self.assertEquals(win1.handle, self.marionette.current_chrome_window_handle) + self.assertEquals(win1.window_element, + self.marionette.find_element(By.CSS_SELECTOR, ':root')) + self.assertEquals(win1.window_element.get_attribute('windowtype'), + self.marionette.get_window_type()) + self.assertFalse(win1.closed) + + # Test invalid parameters for BaseWindow constructor + self.assertRaises(errors.UnknownWindowError, + BaseWindow, self.marionette, 10) + + # Test invalid shortcuts + self.assertRaises(KeyError, + win1.send_shortcut, 'l', acel=True) + + def test_open_close(self): + # force BaseWindow instance + win1 = BaseWindow(self.marionette, self.browser.handle) + + # Open a new window (will be focused), and check states + win2 = win1.open_window() + + # force BaseWindow instance + win2 = BaseWindow(self.marionette, win2.handle) + + self.assertEquals(len(self.marionette.chrome_window_handles), 2) + self.assertNotEquals(win1.handle, win2.handle) + self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle) + + win2.close() + + self.assertTrue(win2.closed) + self.assertEquals(len(self.marionette.chrome_window_handles), 1) + self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle) + Wait(self.marionette).until(lambda _: win1.focused) # catch the no focused window + + win1.focus() + + # Open and close a new window by a custom callback + def opener(window): + window.marionette.execute_script(""" window.open(); """) + + def closer(window): + window.marionette.execute_script(""" window.close(); """) + + win2 = win1.open_window(callback=opener) + + # force BaseWindow instance + win2 = BaseWindow(self.marionette, win2.handle) + + self.assertEquals(len(self.marionette.chrome_window_handles), 2) + win2.close(callback=closer) + + win1.focus() + + # Check for an unexpected window class + self.assertRaises(errors.UnexpectedWindowTypeError, + win1.open_window, expected_window_class=BaseWindow) + self.puppeteer.windows.close_all([win1]) + + def test_switch_to_and_focus(self): + # force BaseWindow instance + win1 = BaseWindow(self.marionette, self.browser.handle) + + # Open a new window (will be focused), and check states + win2 = win1.open_window() + + # force BaseWindow instance + win2 = BaseWindow(self.marionette, win2.handle) + + self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle) + self.assertEquals(win2.handle, self.puppeteer.windows.focused_chrome_window_handle) + self.assertFalse(win1.focused) + self.assertTrue(win2.focused) + + # Switch back to win1 without moving the focus, but focus separately + win1.switch_to() + self.assertEquals(win1.handle, self.marionette.current_chrome_window_handle) + self.assertTrue(win2.focused) + + win1.focus() + self.assertTrue(win1.focused) + + # Switch back to win2 by focusing it directly + win2.focus() + self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle) + self.assertEquals(win2.handle, self.puppeteer.windows.focused_chrome_window_handle) + self.assertTrue(win2.focused) + + # Close win2, and check that it keeps active but looses focus + win2.switch_to() + win2.close() + + win1.switch_to() + + +class TestBrowserWindow(BaseWindowTestCase): + + def tearDown(self): + try: + self.puppeteer.windows.close_all([self.browser]) + finally: + BaseWindowTestCase.tearDown(self) + + def test_basic(self): + self.assertNotEqual(self.browser.dtds, []) + self.assertNotEqual(self.browser.properties, []) + + self.assertFalse(self.browser.is_private) + + self.assertIsNotNone(self.browser.menubar) + self.assertIsNotNone(self.browser.navbar) + self.assertIsNotNone(self.browser.tabbar) + + def test_open_close(self): + # open and close a new browser windows by menu + win2 = self.browser.open_browser(trigger='menu') + self.assertEquals(win2, self.puppeteer.windows.current) + self.assertFalse(self.browser.is_private) + win2.close(trigger='menu') + + # open and close a new browser window by shortcut + win2 = self.browser.open_browser(trigger='shortcut') + self.assertEquals(win2, self.puppeteer.windows.current) + self.assertFalse(self.browser.is_private) + win2.close(trigger='shortcut') + + # open and close a new private browsing window + win2 = self.browser.open_browser(is_private=True) + self.assertEquals(win2, self.puppeteer.windows.current) + self.assertTrue(win2.is_private) + win2.close() + + # open and close a new private browsing window + win2 = self.browser.open_browser(trigger='shortcut', is_private=True) + self.assertEquals(win2, self.puppeteer.windows.current) + self.assertTrue(win2.is_private) + win2.close() + + # force closing a window + win2 = self.browser.open_browser() + self.assertEquals(win2, self.puppeteer.windows.current) + win2.close(force=True) |