mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1270953 - Enhance notification class for Firefox Puppeteer. r=maja_zf
MozReview-Commit-ID: KE117HzhiXM --HG-- extra : rebase_source : eefe2b6c7141784516bddf9e913162f3744e0b7e
This commit is contained in:
parent
b9da89429b
commit
e07a01ca67
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,56 +2,42 @@
|
||||
# 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 marionette_driver import By
|
||||
from marionette_driver.errors import TimeoutException
|
||||
|
||||
from firefox_ui_harness.testcases import FirefoxTestCase
|
||||
from firefox_puppeteer.ui.browser.notifications import (
|
||||
AddOnInstallFailedNotification)
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
AddOnInstallFailedNotification,
|
||||
)
|
||||
|
||||
|
||||
class TestNotifications(FirefoxTestCase):
|
||||
|
||||
def setUp(self):
|
||||
FirefoxTestCase.setUp(self)
|
||||
# setting this pref prevents a notification from being displayed
|
||||
# when e10s is enabled. see http://mzl.la/1TVNAXh
|
||||
self.prefs.set_pref('browser.tabs.remote.force-enable', True)
|
||||
|
||||
self.prefs.set_pref('extensions.install.requireSecureOrigin', False)
|
||||
|
||||
self.addons_url = self.marionette.absolute_url('addons/extensions/')
|
||||
self.utils.permissions.add(self.marionette.baseurl, 'install')
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
if self.browser.notification is not None:
|
||||
self.browser.notification.close()
|
||||
self.utils.permissions.remove(self.addons_url, 'install')
|
||||
|
||||
if self.browser.notification:
|
||||
self.browser.notification.close(force=True)
|
||||
finally:
|
||||
FirefoxTestCase.tearDown(self)
|
||||
|
||||
def test_no_notification(self):
|
||||
"""No initial notifications are shown"""
|
||||
self.assertIsNone(self.browser.notification)
|
||||
|
||||
def test_notification_with_origin(self):
|
||||
"""Trigger a notification with an origin"""
|
||||
self.trigger_add_on_notification('mn-restartless-unsigned.xpi')
|
||||
self.assertIsNotNone(self.browser.notification.origin)
|
||||
self.assertIsNotNone(self.browser.notification.label)
|
||||
|
||||
def test_close_notification(self):
|
||||
def test_open_close_notification(self):
|
||||
"""Trigger and dismiss a notification"""
|
||||
self.trigger_add_on_notification('mn-restartless-unsigned.xpi')
|
||||
self.assertIsNone(self.browser.notification)
|
||||
self.trigger_addon_notification('restartless_addon_unsigned.xpi')
|
||||
self.browser.notification.close()
|
||||
self.assertIsNone(self.browser.notification)
|
||||
|
||||
def test_add_on_failed_notification(self):
|
||||
"""Trigger add-on failed notification using an unsigned add-on"""
|
||||
self.trigger_add_on_notification('mn-restartless-unsigned.xpi')
|
||||
self.assertIsInstance(self.browser.notification,
|
||||
AddOnInstallFailedNotification)
|
||||
|
||||
def test_wait_for_any_notification_timeout(self):
|
||||
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):
|
||||
@ -66,12 +52,29 @@ class TestNotifications(FirefoxTestCase):
|
||||
def test_wait_for_no_notification_timeout(self):
|
||||
"""Wait for no notification when one is shown"""
|
||||
message = 'Unexpected notification shown'
|
||||
self.trigger_add_on_notification('mn-restartless-unsigned.xpi')
|
||||
self.trigger_addon_notification('restartless_addon_unsigned.xpi')
|
||||
with self.assertRaisesRegexp(TimeoutException, message):
|
||||
self.browser.wait_for_notification(None)
|
||||
|
||||
def trigger_add_on_notification(self, add_on):
|
||||
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)
|
||||
self.browser.notification.close()
|
||||
|
||||
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.prefs.set_pref('xpinstall.signatures.required', True)
|
||||
|
||||
self.trigger_addon_notification('restartless_addon_unsigned.xpi')
|
||||
self.assertIsInstance(self.browser.notification,
|
||||
AddOnInstallFailedNotification)
|
||||
self.browser.notification.close()
|
||||
|
||||
def trigger_addon_notification(self, addon):
|
||||
with self.marionette.using_context('content'):
|
||||
self.marionette.navigate('file://{0}'.format(here))
|
||||
self.marionette.find_element(By.LINK_TEXT, add_on).click()
|
||||
self.marionette.navigate(self.addons_url)
|
||||
self.marionette.find_element(By.LINK_TEXT, addon).click()
|
||||
self.browser.wait_for_notification()
|
||||
|
@ -11,11 +11,21 @@ from firefox_puppeteer.ui_base_lib import UIBaseLib
|
||||
|
||||
class BaseNotification(UIBaseLib):
|
||||
"""Abstract base class for any kind of notification."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@property
|
||||
def close_button(self):
|
||||
"""Provide access to the close button.
|
||||
|
||||
:returns: The close button.
|
||||
"""
|
||||
return self.element.find_element(By.ANON_ATTRIBUTE,
|
||||
{'anonid': 'closebutton'})
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
"""Provides access to the notification label.
|
||||
"""Provide access to the notification label.
|
||||
|
||||
:returns: The notification label.
|
||||
"""
|
||||
@ -23,34 +33,47 @@ class BaseNotification(UIBaseLib):
|
||||
|
||||
@property
|
||||
def origin(self):
|
||||
"""Provides access to the notification origin.
|
||||
"""Provide access to the notification origin.
|
||||
|
||||
:returns: The notification origin.
|
||||
"""
|
||||
return self.element.get_attribute('origin')
|
||||
|
||||
def close(self):
|
||||
"""Close the notification."""
|
||||
self.element.find_element(
|
||||
By.ANON_ATTRIBUTE, {'anonid': 'closebutton'}).click()
|
||||
def close(self, force=False):
|
||||
"""Close the notification.
|
||||
|
||||
:param force: Optional, if True force close the notification.
|
||||
Defaults to False.
|
||||
"""
|
||||
if force:
|
||||
self.marionette.execute_script('arguments[0].click()',
|
||||
script_args=[self.close_button])
|
||||
else:
|
||||
self.close_button.click()
|
||||
|
||||
self.window.wait_for_notification(None)
|
||||
|
||||
|
||||
class AddOnInstallBlockedNotification(BaseNotification):
|
||||
"""Add-on install blocked notification."""
|
||||
|
||||
def allow(self):
|
||||
"""Allow the add-on to be installed."""
|
||||
self.element.find_element(
|
||||
@property
|
||||
def allow_button(self):
|
||||
"""Provide access to the allow button.
|
||||
|
||||
:returns: The allow button.
|
||||
"""
|
||||
return self.element.find_element(
|
||||
By.ANON_ATTRIBUTE, {'anonid': 'button'}).find_element(
|
||||
By.ANON_ATTRIBUTE, {'anonid': 'button'}).click()
|
||||
By.ANON_ATTRIBUTE, {'anonid': 'button'})
|
||||
|
||||
|
||||
class AddOnInstallConfirmationNotification(BaseNotification):
|
||||
"""Add-on install confirmation notification."""
|
||||
|
||||
@property
|
||||
def add_on(self):
|
||||
"""Provides access to the add-on name.
|
||||
def addon_name(self):
|
||||
"""Provide access to the add-on name.
|
||||
|
||||
:returns: The add-on name.
|
||||
"""
|
||||
@ -58,27 +81,36 @@ class AddOnInstallConfirmationNotification(BaseNotification):
|
||||
By.CSS_SELECTOR, '#addon-install-confirmation-content label')
|
||||
return label.get_attribute('value')
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel installation of the add-on."""
|
||||
self.element.find_element(
|
||||
By.ID, 'addon-install-confirmation-cancel').click()
|
||||
def cancel_button(self):
|
||||
"""Provide access to the cancel button.
|
||||
|
||||
def install(self):
|
||||
"""Proceed with installation of the add-on."""
|
||||
self.element.find_element(
|
||||
By.ID, 'addon-install-confirmation-accept').click()
|
||||
:returns: The cancel button.
|
||||
"""
|
||||
return self.element.find_element(
|
||||
By.ID, 'addon-install-confirmation-cancel')
|
||||
|
||||
def install_button(self):
|
||||
"""Provide access to the install button.
|
||||
|
||||
:returns: The install button.
|
||||
"""
|
||||
return self.element.find_element(
|
||||
By.ID, 'addon-install-confirmation-accept')
|
||||
|
||||
|
||||
class AddOnInstallCompleteNotification(BaseNotification):
|
||||
"""Add-on install complete notification."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class AddOnInstallFailedNotification(BaseNotification):
|
||||
"""Add-on install failed notification."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class AddOnProgressNotification(BaseNotification):
|
||||
"""Add-on progress notification."""
|
||||
|
||||
pass
|
||||
|
@ -108,24 +108,39 @@ class BrowserWindow(BaseWindow):
|
||||
try:
|
||||
notification = self.window_element.find_element(
|
||||
By.CSS_SELECTOR, '#notification-popup popupnotification')
|
||||
|
||||
notification_id = notification.get_attribute('id')
|
||||
return notifications_map.get(notification_id, BaseNotification)(
|
||||
lambda: self.marionette, self, notification)
|
||||
|
||||
except NoSuchElementException:
|
||||
return None # no notification is displayed
|
||||
notification_id = notification.get_attribute('id')
|
||||
return notifications_map[notification_id](
|
||||
lambda: self.marionette, self, notification)
|
||||
|
||||
def wait_for_notification(self, notification_class=BaseNotification):
|
||||
"""Waits for the specified notification to be displayed."""
|
||||
if notification_class is None:
|
||||
Wait(self.marionette).until(
|
||||
lambda _: self.notification is None,
|
||||
message='Unexpected notification shown.')
|
||||
else:
|
||||
message = '{0} was not shown.'.format(notification_class.__name__)
|
||||
def wait_for_notification(self, notification_class=BaseNotification,
|
||||
timeout=5):
|
||||
"""Waits for the specified notification to be displayed.
|
||||
|
||||
:param notification_class: Optional, the notification class to wait for.
|
||||
If `None` is specified it will wait for any notification to be closed.
|
||||
Defaults to `BaseNotification`.
|
||||
:param timeout: Optional, how long to wait for the expected notification.
|
||||
Defaults to 5 seconds.
|
||||
"""
|
||||
wait = Wait(self.marionette, timeout=timeout)
|
||||
|
||||
if notification_class:
|
||||
if notification_class is BaseNotification:
|
||||
message = 'No notification was shown.'
|
||||
Wait(self.marionette).until(lambda _: isinstance(
|
||||
self.notification, notification_class), message=message)
|
||||
else:
|
||||
message = '{0} was not shown.'.format(notification_class.__name__)
|
||||
wait.until(
|
||||
lambda _: isinstance(self.notification, notification_class),
|
||||
message=message)
|
||||
else:
|
||||
message = 'Unexpected notification shown.'
|
||||
wait.until(
|
||||
lambda _: self.notification is None,
|
||||
message='Unexpected notification shown.')
|
||||
|
||||
@property
|
||||
def tabbar(self):
|
||||
|
Loading…
Reference in New Issue
Block a user