def generate_region_by_markers(top_left_marker_img=None, bottom_right_marker_img=None): """Generate a region starting from 2 markers. :param top_left_marker_img: Top left pattern used to generate the region. :param bottom_right_marker_img: Bottom right pattern used to generate the region. :return: Screen region generated. """ try: wait(top_left_marker_img, 10) exists(bottom_right_marker_img, 10) except FindError: raise FindError("Unable to find page markers.") top_left_pos = find(top_left_marker_img) bottom_right_pos = find(bottom_right_marker_img) marker_width, marker_height = bottom_right_marker_img.get_size() return Region( top_left_pos.x, top_left_pos.y, (bottom_right_pos.x + marker_width), bottom_right_pos.y - top_left_pos.y + marker_height, )
def download_file( file_to_download, accept_download, max_number_of_attempts=20, expect_accept_download_available=True, ): """ :param file_to_download: Pattern of file to be downloaded. :param accept_download: Accept download pattern. :param max_number_of_attempts: Max number of attempts to locate file_to_download pattern. :param expect_accept_download_available: True if we expect accept_download button, False - if we don't; (in Windows 7 download UI don't have extra accept button in certain cases) :return: None. """ for _ in range(max_number_of_attempts): file_found = exists(file_to_download, FirefoxSettings.FIREFOX_TIMEOUT) if file_found: click(file_to_download) break type(Key.PAGE_DOWN) if exists(DownloadFiles.ABOUT, FirefoxSettings.FIREFOX_TIMEOUT): raise APIHelperError("File to be downloaded not found.") try: wait(DownloadFiles.SAVE_FILE, FirefoxSettings.HEAVY_SITE_LOAD_TIMEOUT) logger.debug("The 'Save file' option is present in the page.") time.sleep( FirefoxSettings.TINY_FIREFOX_TIMEOUT ) # prevent click on inactive button on windows click(DownloadFiles.SAVE_FILE) except FindError: raise APIHelperError( "The 'Save file' option is not present in the page, aborting." ) if expect_accept_download_available: accept_download_button = exists( accept_download, FirefoxSettings.FIREFOX_TIMEOUT ) if accept_download_button: logger.debug("The accept download button found in the page.") click(accept_download) else: raise APIHelperError( "The accept download button was not found in the page." )
def repeat_key_up_until_image_found(image_pattern, num_of_key_up_presses=10, delay_between_presses=1): """ Press the Key Up button until specified image pattern is found. :param image_pattern: Image Pattern to search. :param num_of_key_up_presses: Number of presses of the Key Up button. :param delay_between_presses: Number of seconds to wait between the Key Down presses :return: Boolean. True if image pattern found during the Key Up button pressing, False otherwise """ if not isinstance(image_pattern, Pattern): raise ValueError(INVALID_GENERIC_INPUT) pattern_found = False for _ in range(num_of_key_up_presses): pattern_found = exists(image_pattern) if pattern_found: break type(Key.UP) time.sleep(delay_between_presses) return pattern_found
def find_in_region_from_pattern( outer_pattern: Pattern, inner_pattern: Pattern, outer_pattern_timeout=Settings.auto_wait_timeout, inner_pattern_timeout=Settings.auto_wait_timeout, ): """ Finds pattern in region created from another pattern :param outer_pattern: Pattern for region creation :param inner_pattern: Pattern to find in region :param outer_pattern_timeout: Time to finding outer_pattern :param inner_pattern_timeout: Time to finding inner_pattern, :return: Boolean. True if inner_pattern found in outer_pattern region :raises: ValueError and APIHelperError """ if not isinstance(outer_pattern, Pattern) or not isinstance( inner_pattern, Pattern): raise ValueError(INVALID_GENERIC_INPUT) try: wait(outer_pattern, outer_pattern_timeout) logger.debug("Outer pattern found.") except FindError: raise APIHelperError("Can't find the outer pattern.") width, height = outer_pattern.get_size() region = Region( image_find(outer_pattern).x, image_find(outer_pattern).y, width, height) pattern_found = exists(inner_pattern, inner_pattern_timeout, region=region) return pattern_found
def exists(self, ps=None, timeout=None): """Check if Pattern or image exists. :param ps: Pattern or String. :param timeout: Number as maximum waiting time in seconds. :return: Call the exists() method. """ return exists(ps, timeout, self._area)
def scroll_until_pattern_found( image_pattern: Pattern, scroll_function, scroll_params: tuple = tuple(), num_of_scroll_iterations: int = 10, timeout: float = Settings.auto_wait_timeout, ): """ Scrolls until specified image pattern is found. :param image_pattern: Image Pattern to search. :param scroll_function: Scrolling function or any callable object (e.g. type, scroll, etc.) :param scroll_params: Tuple of params to pass in the scroll_function (e.g. (Key.UP, ) or (Key.UP, KeyModifier.CTRL) for the type function). NOTE: Tuple should contains from 0 (empty tuple) to 2 items. :param num_of_scroll_iterations: Number of scrolling iterations. :param timeout: Number of seconds passed to the 'timeout' param of the 'exist' function. :return: Boolean. True if image pattern found during scrolling, False otherwise """ scroll_arg = None scroll_modifier = None if not isinstance(image_pattern, Pattern): raise ValueError(INVALID_GENERIC_INPUT) if not callable(scroll_function): raise ValueError(INVALID_GENERIC_INPUT) if not isinstance(scroll_params, tuple): raise ValueError(INVALID_GENERIC_INPUT) if len(scroll_params) == 2: scroll_arg, scroll_modifier = scroll_params elif len(scroll_params) == 1: scroll_arg, = scroll_params elif len(scroll_params) == 0: pass else: raise ValueError(INVALID_GENERIC_INPUT) pattern_found = False for _ in range(num_of_scroll_iterations): pattern_found = exists(image_pattern, timeout) if pattern_found: break if scroll_modifier is None and scroll_arg is None: scroll_function() elif scroll_modifier is None: scroll_function(scroll_arg) else: scroll_function(scroll_arg, scroll_modifier) return pattern_found
def select_file_in_folder(directory, filename_pattern, file_option, max_num_of_attempts=3): """ Opens directory, selects file in opened directory, and provides action with it (e.g. copy, cut, delete), and closes opened directory. :param directory: Folder on hard drive to open. :param filename_pattern: File Pattern to select. :param file_option: File processing function. Appropriate methods are: edit_copy, edit_cut, edit_delete. :param max_num_of_attempts: Attempts to find pattern of file name. Default: 3 """ finder_list_view = '2' type_delay = 0.5 if not isinstance(directory, str): raise ValueError(INVALID_GENERIC_INPUT) if not isinstance(filename_pattern, Pattern): raise ValueError(INVALID_GENERIC_INPUT) if not callable(file_option): raise ValueError(INVALID_GENERIC_INPUT) open_directory(directory) try: for attempt in range(1, max_num_of_attempts + 1): file_located = exists(filename_pattern) if file_located: logger.debug('File {} in directory {} is available.'.format(filename_pattern, directory)) break else: if attempt == max_num_of_attempts: logger.debug('File {} is not available after {} attempt(s).'.format(filename_pattern, attempt)) raise Exception time.sleep(Settings.DEFAULT_UI_DELAY_LONG) if OSHelper.is_mac(): type(text=finder_list_view, modifier=KeyModifier.CMD, interval=type_delay) click(filename_pattern) file_option() except Exception: raise APIHelperError('Could not find file {} in folder {}.'.format(filename_pattern, directory)) finally: if OSHelper.is_windows(): type(text='w', modifier=KeyModifier.CTRL) elif OSHelper.is_linux(): type(text='q', modifier=KeyModifier.CTRL) elif OSHelper.is_mac(): type(text='w', modifier=[KeyModifier.CMD, KeyModifier.ALT])
def restore_firefox_focus(): """Restore Firefox focus by clicking the panel near HOME or REFRESH button.""" try: if exists(NavBar.HOME_BUTTON, Settings.DEFAULT_UI_DELAY): target_pattern = NavBar.HOME_BUTTON else: target_pattern = NavBar.RELOAD_BUTTON w, h = target_pattern.get_size() horizontal_offset = w * 1.7 click_area = target_pattern.target_offset(horizontal_offset, 0) click(click_area) except FindError: raise APIHelperError("Could not restore firefox focus.")
def key_to_one_off_search(highlighted_pattern, direction="left"): """Iterate through the one of search engines list until the given one is highlighted. param: highlighted_pattern: The pattern image to search for. param: direction: direction to key to: right or left (default) return: None. """ max_attempts = 7 while max_attempts > 0: if exists(highlighted_pattern, 1): max_attempts = 0 else: if direction == "right": type(Key.RIGHT) else: type(Key.LEFT) max_attempts -= 1
def create_region_from_patterns( top=None, bottom=None, left=None, right=None, padding_top=None, padding_bottom=None, padding_left=None, padding_right=None, ): """Returns a region created from combined area of one or more patterns. Argument names are just for convenience and don't influence outcome. :param top: Top pattern used to generate the region. :param bottom: Bottom pattern used to generate the region. :param left: Left pattern used to generate the region. :param right: Right pattern used to generate the region. :param padding_top: Padding to be added to the pattern's top. :param padding_bottom: Padding to be added to the pattern's bottom. :param padding_left: Padding to be added to the pattern's left. :param padding_right: Padding to be added to the pattern's right. :return: region created from combined area of one or more patterns. """ patterns = [] if top: patterns.append(top) if bottom: patterns.append(bottom) if left: patterns.append(left) if right: patterns.append(right) if len(patterns) == 0: raise ValueError("One or more patterns required.") logger.debug("Creating region from %s pattern(s)." % len(patterns)) a, b = (Screen().width, Screen().height) p1 = Location(a, b) p2 = Location(0, 0) for pattern in patterns: if exists(pattern, 5): current_pattern = find(pattern) if current_pattern.x < p1.x: p1.x = current_pattern.x if current_pattern.y < p1.y: p1.y = current_pattern.y w, h = pattern.get_size() if current_pattern.x + w > p2.x: p2.x = current_pattern.x + w if current_pattern.y + h > p2.y: p2.y = current_pattern.y + h else: raise FindError("Pattern not found: %s " % pattern) found_region = Region(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y) if padding_top or padding_bottom or padding_left or padding_right: logger.debug("Adding padding to region.") if padding_top: found_region.y -= padding_top found_region.height += padding_top if padding_bottom: found_region.height += padding_bottom if padding_left: found_region.x -= padding_left found_region.width += padding_left if padding_right: found_region.width += padding_right return found_region
def open_hamburger_menu(option): """ Opens a specific option from the hamburger menu. If no option is given, just open the menu. In that case, the calling test must close the menu on its own. :param option: Hamburger menu option to be selected. :return: None. """ option_list = [ 'Restore Previous Session', 'Add-ons', 'Customize', 'Print', 'Web Developer', 'Help', 'Exit', 'Quit' ] if not isinstance(option, str) or option not in option_list: raise ValueError(INVALID_GENERIC_INPUT) hamburger_menu_pattern = NavBar.HAMBURGER_MENU region = Screen.UPPER_RIGHT_CORNER sign_in_to_firefox_pattern = Pattern("sign_in_to_firefox.png") try: region.wait(hamburger_menu_pattern, 10) logger.debug("Hamburger menu found.") except FindError: raise APIHelperError( 'Can\'t find the "hamburger menu" in the page, aborting test.') else: try: region.click(hamburger_menu_pattern) region.wait(sign_in_to_firefox_pattern, 10) if option == "Restore Previous Session": restore_option_exists = exists( HamburgerMenu.RESTORE_PREVIOUS_SESSION, FirefoxSettings.FIREFOX_TIMEOUT) assert restore_option_exists, "Restore option exists is hamburger menu." click(HamburgerMenu.RESTORE_PREVIOUS_SESSION) elif option == "Add-ons": add_ons_option_exists = exists(HamburgerMenu.ADDONS, FirefoxSettings.FIREFOX_TIMEOUT) assert add_ons_option_exists, "Add-ons option exists is hamburger menu." click(HamburgerMenu.ADDONS) elif option == "Customize": customize_option_exists = exists( HamburgerMenu.CUSTOMIZE, FirefoxSettings.FIREFOX_TIMEOUT) assert customize_option_exists, "Customize option exists is hamburger menu." click(HamburgerMenu.CUSTOMIZE) elif option == "Print": print_option_exists = exists(HamburgerMenu.PRINT, FirefoxSettings.FIREFOX_TIMEOUT) assert print_option_exists, "Print option exists is hamburger menu." click(HamburgerMenu.PRINT) elif option == "Web Developer": web_dev_option_exists = exists(HamburgerMenu.WEB_DEVELOPER, FirefoxSettings.FIREFOX_TIMEOUT) assert web_dev_option_exists, "Web developer option exists is hamburger menu." click(HamburgerMenu.WEB_DEVELOPER) elif option == "Help": help_option_exists = exists(HamburgerMenu.HELP, FirefoxSettings.FIREFOX_TIMEOUT) assert help_option_exists, "Help option exists is hamburger menu." click(HamburgerMenu.HELP) elif (option == "Exit") or (option == "Quit"): if OSHelper.is_mac(): type(Key.Q, KeyModifier.CMD) else: exit_option_exists = exists( HamburgerMenu.EXIT, FirefoxSettings.FIREFOX_TIMEOUT) assert exit_option_exists, "Exit/Quit option exists is hamburger menu." click(HamburgerMenu.EXIT) except FindError: raise APIHelperError("Can't click the menu button. Aborting test.")
def cancel_in_progress_downloads_from_the_library(private_window=False): # Open the 'Show Downloads' window and cancel all 'in progress' downloads. global cancel_downloads if private_window: steps = show_all_downloads_from_library_menu_private_window() logger.debug('Creating a region for Private Library window.') try: find_back_button = find(NavBar.BACK_BUTTON) except FindError: raise FindError('Could not get the coordinates of the nav bar back button.') try: find_hamburger_menu = find(NavBar.HAMBURGER_MENU) except FindError: raise FindError('Could not get the coordinates of the hamburger menu.') region = Region(find_back_button.x - 10, find_back_button.y, Screen.SCREEN_WIDTH, Screen.SCREEN_HEIGHT) else: steps = open_show_all_downloads_window_from_library_menu() logger.debug('Creating a region for Non-private Library window.') expected = exists(Library.TITLE, 10) assert expected is True, 'Library successfully opened.' try: find_library = find(Library.TITLE) except FindError: raise FindError('Could not get the x-coordinate of the library window title.') try: find_clear_downloads = find(Library.CLEAR_DOWNLOADS) except FindError: raise FindError('Could not get the x-coordinate of the clear_downloads button.') clear_downloads_width, clear_downloads_height = Library.CLEAR_DOWNLOADS.get_size() region = Region(find_library.x - 10, find_library.y, (find_clear_downloads.x + clear_downloads_width + 20) - find_library.x, 500) # Cancel all 'in progress' downloads. expected = region.exists(DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL, 5) expected_highlighted = region.exists(DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL_HIGHLIGHTED) if expected or expected_highlighted: steps.append(Step(expected, 'The Cancel Download button is displayed properly.')) cancel_downloads = True expected_cancel = True else: steps.append(Step(True, 'There are no downloads to be cancelled.')) cancel_downloads = False cancel_pattern = DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL if expected \ else DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL_HIGHLIGHTED if cancel_downloads: while expected_cancel: expected_cancel = region.exists(cancel_pattern, 10) if expected_cancel: click(cancel_pattern) if not private_window: hover(Library.TITLE) steps.append(Step(True, 'All downloads were cancelled.')) if private_window: close_tab() else: click_window_control('close') return steps