def close(self, callback=None, force=False): """Closes the current chrome window. If this is the last remaining window, the Marionette session is ended. :param callback: Optional, function to trigger the window to open. It is triggered with the current :class:`BaseWindow` as parameter. Defaults to `window.open()`. :param force: Optional, forces the closing of the window by using the Gecko API. Defaults to `False`. """ self.switch_to() # Bug 1121698 # For more stable tests register an observer topic first prev_win_count = len(self.marionette.chrome_window_handles) if force or callback is None: self._windows.close(self.handle) else: callback(self) # Bug 1121698 # Observer code should let us ditch this wait code wait = Wait(self.marionette) wait.until(lambda m: len(m.chrome_window_handles) == prev_win_count - 1)
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.' 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.')
def attempt_ad_skip(self): """ Attempt to skip ad by clicking on skip-add button. Return True if clicking of ad-skip button occurred. """ # Wait for ad to load and become skippable if self.ad_playing: self.marionette.log('Waiting while ad plays') sleep(10) else: # no ad playing return False if self.ad_skippable: selector = '#movie_player .videoAdUiSkipContainer' wait = Wait(self.marionette, timeout=30) try: with self.marionette.using_context('content'): wait.until(expected.element_displayed(By.CSS_SELECTOR, selector)) ad_button = self.marionette.find_element(By.CSS_SELECTOR, selector) ad_button.click() self.marionette.log('Skipped ad.') return True except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: %s' % selector, level='WARNING') return False
def attempt_ad_skip(self): """ Attempt to skip ad by clicking on skip-add button. :return: True if clicking of ad-skip button occurred. """ if self.ad_playing: self.marionette.log('Waiting while ad plays') sleep(10) else: # no ad playing return False if self.ad_skippable: selector = '.html5-video-player .videoAdUiSkipContainer' wait = Wait(self.marionette, timeout=30) try: with self.marionette.using_context(Marionette.CONTEXT_CONTENT): wait.until( expected.element_displayed(By.CSS_SELECTOR, selector)) ad_button = self.marionette.find_element( By.CSS_SELECTOR, selector) ad_button.click() self.marionette.log('Skipped ad.') return True except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: {}'.format(selector), level='WARNING') return False
def search_ad_duration(self): """ :return: ad duration in seconds, if currently displayed in player """ if not (self.ad_playing or self.player_measure_progress() == 0): return None # If the ad is not Flash... if (self.ad_playing and self.video_src.startswith('mediasource') and self.duration): return self.duration selector = '.html5-media-player .videoAdUiAttribution' wait = Wait(self.marionette, timeout=5) try: with self.marionette.using_context(Marionette.CONTEXT_CONTENT): wait.until(expected.element_present(By.CSS_SELECTOR, selector)) countdown = self.marionette.find_element( By.CSS_SELECTOR, selector) ad_time = self._time_pattern.search(countdown.text) if ad_time: ad_minutes = int(ad_time.group('minute')) ad_seconds = int(ad_time.group('second')) return 60 * ad_minutes + ad_seconds except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: {}'.format(selector), level='WARNING') return None
def deactivate_autoplay(self): """ Attempt to turn off autoplay. Return True if successful. """ element_id = 'autoplay-checkbox' mn = self.marionette wait = Wait(mn, timeout=10) def get_status(el): script = 'return arguments[0].wrappedJSObject.checked' return mn.execute_script(script, script_args=[el]) try: with mn.using_context('content'): # the width, height of the element are 0, so it's not visible wait.until(expected.element_present(By.ID, element_id)) checkbox = mn.find_element(By.ID, element_id) # Note: in some videos, due to late-loading of sidebar ads, the # button is rerendered after sidebar ads appear & the autoplay # pref resets to "on". In other words, if you click too early, # the pref might get reset moments later. sleep(1) if get_status(checkbox): mn.execute_script('return arguments[0].' 'wrappedJSObject.click()', script_args=[checkbox]) self.marionette.log('Toggled autoplay.') autoplay = get_status(checkbox) self.marionette.log('Autoplay is %s' % autoplay) return (autoplay is not None) and (not autoplay) except (NoSuchElementException, TimeoutException): return False
def _search_ad_duration(self): """ Try and determine ad duration. Refreshes state. :return: ad duration in seconds, if currently displayed in player """ self._refresh_state() if not (self._last_seen_player_state.player_ad_playing or self._player_measure_progress() == 0): return None if (self._last_seen_player_state.player_ad_playing and self._last_seen_video_state.duration): return self._last_seen_video_state.duration selector = '.html5-video-player .videoAdUiAttribution' wait = Wait(self.marionette, timeout=5) try: with self.marionette.using_context(Marionette.CONTEXT_CONTENT): wait.until(expected.element_present(By.CSS_SELECTOR, selector)) countdown = self.marionette.find_element( By.CSS_SELECTOR, selector) ad_time = self._time_pattern.search(countdown.text) if ad_time: ad_minutes = int(ad_time.group('minute')) ad_seconds = int(ad_time.group('second')) return 60 * ad_minutes + ad_seconds except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: {}'.format(selector), level='WARNING') return None
def search_ad_duration(self): """ :return: ad duration in seconds, if currently displayed in player """ if not (self.ad_playing or self.player_measure_progress() == 0): return None # If the ad is not Flash... if (self.ad_playing and self.video_src.startswith('mediasource') and self.duration): return self.duration selector = '#movie_player .videoAdUiAttribution' wait = Wait(self.marionette, timeout=5) try: with self.marionette.using_context('content'): wait.until(expected.element_present(By.CSS_SELECTOR, selector)) countdown = self.marionette.find_element(By.CSS_SELECTOR, selector) ad_time = self._time_pattern.search(countdown.text) if ad_time: ad_minutes = int(ad_time.group('minute')) ad_seconds = int(ad_time.group('second')) return 60 * ad_minutes + ad_seconds except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: %s' % selector, level='WARNING') return None
def _search_ad_duration(self): """ Try and determine ad duration. Refreshes state. :return: ad duration in seconds, if currently displayed in player """ self._refresh_state() if not (self._last_seen_player_state.player_ad_playing or self._player_measure_progress() == 0): return None if (self._last_seen_player_state.player_ad_playing and self._last_seen_video_state.duration): return self._last_seen_video_state.duration selector = '.html5-video-player .videoAdUiAttribution' wait = Wait(self.marionette, timeout=5) try: with self.marionette.using_context(Marionette.CONTEXT_CONTENT): wait.until(expected.element_present(By.CSS_SELECTOR, selector)) countdown = self.marionette.find_element(By.CSS_SELECTOR, selector) ad_time = self._time_pattern.search(countdown.text) if ad_time: ad_minutes = int(ad_time.group('minute')) ad_seconds = int(ad_time.group('second')) return 60 * ad_minutes + ad_seconds except (TimeoutException, NoSuchElementException): self.marionette.log('Could not obtain ' 'element: {}'.format(selector), level='WARNING') return None
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.' 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.')
def test_safe_browsing_initial_download(self): wait = Wait(self.marionette, timeout=self.browser.timeout_page_load) for data in self.test_data: if self.platform not in data['platforms']: continue for item in data['files']: wait.until( lambda _: os.path.exists(os.path.join(self.sb_files_path, item)), message='Safe Browsing File: {} not found!'.format(item))
def test_safe_browsing_initial_download(self): wait = Wait(self.marionette, timeout=self.browser.timeout_page_load) for data in self.test_data: if self.platform not in data['platforms']: continue for item in data['files']: wait.until( lambda _: os.path.exists( os.path.join(self.sb_files_path, item)), message='Safe Browsing File: {} not found!'.format(item))
def test_safe_browsing_initial_download(self): wait = Wait(self.marionette, timeout=self.browser.timeout_page_load, ignored_exceptions=[OSError]) for data in self.test_data: if self.platform not in data['platforms']: continue for item in data['files']: wait.until( lambda _: [f for f in os.listdir(self.sb_files_path) if re.search(item, f)], message='Safe Browsing File: {} not found!'.format(item))
def test_safe_browsing_initial_download(self): wait = Wait(self.marionette, timeout=self.browser.timeout_page_load) for data in self.test_data: if self.platform not in data['platforms']: continue for item in data['files']: wait.until( lambda _: [ f for f in os.listdir(self.sb_files_path) if re.search(item, f) ], message='Safe Browsing File: {} not found!'.format(item))
def wait_for_element_tag(self, tagname): """ Wait for element to appear. """ waiter = Wait(self.marionette, timeout=20.0, interval=0.1) element = waiter.until(lambda m: self.find_tag(tagname)) return element
def wait_all_data_received(self): """ Wait for all data to arrive in the dashboard. """ log.info('Waiting for "all-data-received" event') waiter = Wait(self.marionette, timeout=20.0, interval=1.0) def condition(marionette): return self.calljs("grafanaStudio.hasAllData") try: waiter.until(condition) except TimeoutException as ex: log.warning('Timed out waiting for data: %s. Continuing anyway.', ex)
def wait_for_windows(self, expected_windows, message, timeout=5): current_windows = None def check(_): nonlocal current_windows current_windows = self.convert_open_windows_to_set() return current_windows == expected_windows try: wait = Wait(self.marionette, timeout=timeout, interval=0.1) wait.until(check, message=message) except errors.TimeoutException as e: # Update the message to include the most recent list of windows message = ( f"{e.message}. Expected {expected_windows}, got {current_windows}." ) raise errors.TimeoutException(message)
def test_initial_installation(self): m = self.marionette b = self.browser # Navigate to the site and click the install button with m.using_context(m.CONTEXT_CONTENT): m.navigate(SITE_URL) m.find_element(By.CSS_SELECTOR, 'button[data-hook=install]').click() w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element(By.CSS_SELECTOR, 'button[data-hook=install].state-change')) # Click through the blocked notification b.wait_for_notification(AddOnInstallBlockedNotification, timeout=60) # HACK: Things seem to fail intermittently here if we don't wait a tick time.sleep(0.5) b.notification.allow_button.click() # Click through the installation notification b.wait_for_notification(AddOnInstallConfirmationNotification) b.notification.install_button().click() # Wait for and close the completion notification b.wait_for_notification(AddOnInstallCompleteNotification, timeout=60) b.notification.close() # The toolbar button should show up soon after installation with m.using_context(m.CONTEXT_CHROME): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element('id', target=TOOLBAR_BUTTON_ID)) # And the add-on should open up an onboarding tab... Wait(m).until(lambda m: len(b.tabbar.tabs) > 1) next_tab_loc = b.tabbar.tabs[1].location self.assertTrue(next_tab_loc.endswith('/onboarding') or next_tab_loc.endswith('/onboarding/')) b.tabbar.close_tab(b.tabbar.tabs[1]) # The frontend should redirect to /experiments after it contacts the add-on Wait(m).until(lambda m: b.tabbar.tabs[0].location.endswith('/experiments') or b.tabbar.tabs[0].location.endswith('/experiments/')) # Clean up by uninstalling the add-on Addons(m).uninstall('@testpilot-addon')
def test_initial_installation(self): m = self.marionette b = self.browser # Navigate to the site and click the install button with m.using_context(m.CONTEXT_CONTENT): m.navigate(SITE_URL) m.find_element(By.CSS_SELECTOR, 'button[data-hook=install]').click() w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element(By.CSS_SELECTOR, 'button[data-hook=install].state-change')) # Click through the blocked notification b.wait_for_notification(AddOnInstallBlockedNotification) # HACK: Things seem to fail intermittently here if we don't wait a tick time.sleep(0.5) b.notification.allow_button.click() # Click through the installation notification b.wait_for_notification(AddOnInstallConfirmationNotification) b.notification.install_button().click() # Wait for and close the completion notification b.wait_for_notification(AddOnInstallCompleteNotification, timeout=60) b.notification.close() # The toolbar button should show up soon after installation with m.using_context(m.CONTEXT_CHROME): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element('id', target=TOOLBAR_BUTTON_ID)) # And the add-on should open up an onboarding tab... Wait(m).until(lambda m: len(b.tabbar.tabs) > 1) next_tab_loc = b.tabbar.tabs[1].location self.assertTrue(next_tab_loc.endswith('/onboarding') or next_tab_loc.endswith('/onboarding/')) b.tabbar.close_tab(b.tabbar.tabs[1]) # The frontend should redirect to /experiments after it contacts the add-on Wait(m).until(lambda m: b.tabbar.tabs[0].location.endswith('/experiments')) # Clean up by uninstalling the add-on Addons(m).uninstall('@testpilot-addon')
def test_initial_installation(self): m = self.marionette b = self.browser # Navigate to the site and click the install button with m.using_context(m.CONTEXT_CONTENT): m.navigate(SITE_URL) m.find_element(By.CSS_SELECTOR, 'button.install').click() w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element(By.CSS_SELECTOR, 'button.install.state-change')) # HACK: Checking _visibility_ of chrome elements, like notifications, # is known to be buggy. Padding the wait_for_notification call with # sleeps is the current workaround. See https://bugzil.la/1094246#c17 time.sleep(15) # Click through the blocked notification b.wait_for_notification(AddOnInstallBlockedNotification, timeout=60) # HACK: Things seem to fail intermittently here if we don't wait a tick time.sleep(5) b.notification.allow_button.click() # Click through the installation notification b.wait_for_notification(AddOnInstallConfirmationNotification) b.notification.install_button().click() # Wait for and close the completion notification b.wait_for_notification(AddOnInstallCompleteNotification, timeout=60) b.notification.close() # The toolbar button should show up soon after installation with m.using_context(m.CONTEXT_CHROME): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element('id', target=TOOLBAR_BUTTON_ID)) # And the add-on should open up an onboarding tab... Wait(m).until(lambda m: len(b.tabbar.tabs) > 1) next_tab_loc = b.tabbar.tabs[1].location self.assertTrue( next_tab_loc.endswith('/onboarding') or next_tab_loc.endswith('/onboarding/')) b.tabbar.close_tab(b.tabbar.tabs[1]) # The frontend should show a list of experiments after it contacts the add-on with m.using_context(m.CONTEXT_CONTENT): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until( lambda m: m.find_element(By.CSS_SELECTOR, 'div.experiments')) # Clean up by uninstalling the add-on Addons(m).uninstall('@testpilot-addon')
def test_initial_installation(self): m = self.marionette b = self.browser # Navigate to the site and click the install button with m.using_context(m.CONTEXT_CONTENT): m.navigate(SITE_URL) m.find_element(By.CSS_SELECTOR, 'button.install').click() w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element(By.CSS_SELECTOR, 'button.install.state-change')) # HACK: Checking _visibility_ of chrome elements, like notifications, # is known to be buggy. Padding the wait_for_notification call with # sleeps is the current workaround. See https://bugzil.la/1094246#c17 time.sleep(15) # Click through the blocked notification b.wait_for_notification(AddOnInstallBlockedNotification, timeout=60) # HACK: Things seem to fail intermittently here if we don't wait a tick time.sleep(5) b.notification.allow_button.click() # Click through the installation notification b.wait_for_notification(AddOnInstallConfirmationNotification) b.notification.install_button().click() # Wait for and close the completion notification b.wait_for_notification(AddOnInstallCompleteNotification, timeout=60) b.notification.close() # The toolbar button should show up soon after installation with m.using_context(m.CONTEXT_CHROME): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element('id', target=TOOLBAR_BUTTON_ID)) # And the add-on should open up an onboarding tab... Wait(m).until(lambda m: len(b.tabbar.tabs) > 1) next_tab_loc = b.tabbar.tabs[1].location self.assertTrue(next_tab_loc.endswith('/onboarding') or next_tab_loc.endswith('/onboarding/')) b.tabbar.close_tab(b.tabbar.tabs[1]) # The frontend should show a list of experiments after it contacts the add-on with m.using_context(m.CONTEXT_CONTENT): w = Wait(m, ignored_exceptions=NoSuchElementException) w.until(lambda m: m.find_element(By.CSS_SELECTOR, 'div.experiments')) # Clean up by uninstalling the add-on Addons(m).uninstall('@testpilot-addon')
def test_acid3(self): with self.marionette.using_context('content'): self.marionette.navigate(self.test_page_url) wait = Wait(self.marionette, timeout=500, interval=1) wait.until(lambda m: m.find_element('id', 'score').text == '100', message='acid3 not 100')