diff --git a/foxpuppet/windows/browser/notifications/addons.py b/foxpuppet/windows/browser/notifications/addons.py index 6f422b4..d5aa52a 100644 --- a/foxpuppet/windows/browser/notifications/addons.py +++ b/foxpuppet/windows/browser/notifications/addons.py @@ -102,14 +102,6 @@ def is_downloading(self): with self.selenium.context(self.selenium.CONTEXT_CHROME): return "Downloading and verifying add-on…" in self.find_description().text - def wait_until_complete(self, timeout=None): - """Wait until the progress notification disappears, indicating completion. - - Args: - timeout (int, optional): Maximum time to wait in seconds. - """ - self.window.wait_for_notification(None, timeout=timeout) - # Clean up of these notifications will happen once Firefox ESR is past version 63 # https://github.com/mozilla/FoxPuppet/issues/212 diff --git a/tests/test_notifications.py b/tests/test_notifications.py index 67a9bcb..a39e6e3 100644 --- a/tests/test_notifications.py +++ b/tests/test_notifications.py @@ -5,24 +5,29 @@ import pytest from selenium.common.exceptions import TimeoutException +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.by import By from foxpuppet.windows.browser.notifications import BaseNotification -from selenium.webdriver.common.by import By from foxpuppet.windows.browser.notifications.addons import ( AddOnInstallBlocked, AddOnInstallComplete, AddOnInstallConfirmation, AddOnInstallFailed, + AddOnProgress, ) @pytest.fixture -def firefox_options(firefox_options): +def firefox_options(request, firefox_options): """Fixture for configuring Firefox.""" # Due to https://bugzilla.mozilla.org/show_bug.cgi?id=1329939 we need the # initial browser window to be in the foreground. Without this, the # notifications will not be displayed. firefox_options.add_argument("-foreground") + if getattr(request, "param", {}).get("page_load_strategy_none", False): + firefox_options.set_capability("pageLoadStrategy", "none") return firefox_options @@ -40,18 +45,39 @@ def addon(): class AddOn: def __init__(self): self.name = "WebExtension" - self.paths = { + self._paths = { "default": "webextension.xpi", "corrupt": "corruptwebextension.xpi", + "large": "largewebextension.xpi", } - def get_path(self, size="default"): - """Returns web extension path.""" - return self.paths.get(size, self.paths["default"]) + @property + def path(self): + """Default path.""" + return self._paths["default"] + + def get_path(self, ext_path): + """Returns the web extension path.""" + return self._paths.get(ext_path) return AddOn() +@pytest.fixture +def progress_notification(addon, browser, webserver, selenium): + """Fixture that triggers the download progress notification. + + Returns: + :py:class:AddOnProgress: Firefox notification. + """ + selenium.get(webserver.url) + element = WebDriverWait(selenium, 10).until( + EC.element_to_be_clickable((By.LINK_TEXT, addon.get_path("large"))) + ) + element.click() + return browser.wait_for_notification(AddOnProgress) + + @pytest.fixture def blocked_notification(addon, browser, webserver, selenium): """Fixture causing a blocked notification to appear in Firefox. @@ -60,8 +86,8 @@ def blocked_notification(addon, browser, webserver, selenium): :py:class:`AddOnInstallBlocked`: Firefox notification. """ - selenium.get(webserver.url()) - selenium.find_element(By.LINK_TEXT, addon.get_path()).click() + selenium.get(webserver.url) + selenium.find_element(By.LINK_TEXT, addon.path).click() return browser.wait_for_notification(AddOnInstallBlocked) @@ -96,7 +122,7 @@ def failed_notification(addon, browser, webserver, selenium): Returns: :py:class:`AddOnInstallFailed`: Firefox notification. """ - selenium.get(webserver.url()) + selenium.get(webserver.url) selenium.find_element(By.LINK_TEXT, addon.get_path("corrupt")).click() return browser.wait_for_notification(AddOnInstallFailed) @@ -164,3 +190,12 @@ def test_failed_installation_notification(failed_notification): """Test that a failed installation notification is shown for a corrupt add-on.""" error_text = "The add-on downloaded from this site could not be installed because it appears to be corrupt." assert failed_notification.error_message == error_text + + +@pytest.mark.parametrize( + "firefox_options", [{"page_load_strategy_none": True}], indirect=True +) +def test_progress_notification_downloading(browser, progress_notification): + """Verify downloading status is reported correctly.""" + description = progress_notification.is_downloading + assert description is not None diff --git a/tests/web/largewebextension.xpi b/tests/web/largewebextension.xpi new file mode 100644 index 0000000..824178c Binary files /dev/null and b/tests/web/largewebextension.xpi differ diff --git a/tests/webserver.py b/tests/webserver.py index 2a72cfe..aa1b8af 100644 --- a/tests/webserver.py +++ b/tests/webserver.py @@ -51,6 +51,11 @@ def port(self): """ return self.server.server_address[1] + @property + def url(self): + """Web server URL.""" + return "http://{0.host}:{0.port}/".format(self) + def start(self): """Start web server.""" self.thread.start() @@ -60,18 +65,6 @@ def stop(self): self.server.shutdown() self.thread.join() - def url(self, path="/"): - """Web server URL. - - Args: - path (str, optional): Path to append to the web server URL. - - Returns: - str: URL of web server. - - """ - return "http://{0.host}:{0.port}{1}".format(self, path) - @classmethod def get_free_port(cls): """Find and return a free port on the system."""