def launch_control_center(): profile_path = os.path.join(PathManager.get_working_dir(), "cc_profile") fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error("Can't find local Firefox installation, aborting Iris run.") return False, None args = ["http://127.0.0.1:%s" % get_core_args().port] process_args = {"stream": None} profile = MozProfile(profile=profile_path, preferences=get_fx_prefs()) if OSHelper.is_windows(): process = subprocess.Popen( [ fx_path, "-no-remote", "-new-tab", args, "--wait-for-browser", "-foreground", "-profile", profile.profile, ], shell=False, ) else: fx_runner = FirefoxRunner( binary=fx_path, profile=profile, cmdargs=args, process_args=process_args ) fx_runner.start() logger.debug("Launching web server for directory %s" % PathManager.get_working_dir()) server = LocalWebServer(PathManager.get_working_dir(), get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text="q", modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text="w", modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text="q", modifier=KeyModifier.CTRL) if OSHelper.is_windows(): if process.pid is not None: try: logger.debug("Closing Firefox process ID: %s" % process.pid) process = psutil.Process(process.pid) for proc in process.children(recursive=True): proc.kill() process.kill() except psutil.NoSuchProcess: pass else: try: fx_runner.stop() except Exception as e: logger.debug("Error stopping fx_runner") logger.debug(e) return server.result
def open_directory(directory): if OSHelper.is_windows(): os.startfile(directory) elif OSHelper.is_linux(): os.system('xdg-open "' + directory + '"') else: os.system('open "' + directory + '"')
def stop(self): if OSHelper.is_windows(): quit_firefox() if FXRunner.process.pid is not None: logger.debug('Closing Firefox process ID: %s' % FXRunner.process.pid) try: process = psutil.Process(pid=FXRunner.process.pid) if process.children() is not None: for proc in process.children(recursive=True): proc.kill() if psutil.pid_exists(process.pid): logger.debug('Terminating PID :%s' % process.pid) process.terminate() except psutil.NoSuchProcess: logger.debug('Failed to find and close Firefox PID: %s' % FXRunner.process.pid) # shutdown_process('firefox') else: if self.runner and self.runner.process_handler: quit_firefox() status = self.runner.process_handler.wait( DEFAULT_FIREFOX_TIMEOUT) if status is None: self.runner.stop()
def maximize_window(): """Maximize the browser window to fill the screen. This is NOT Full Screen mode. """ if OSHelper.is_mac(): # There is no keyboard shortcut for this on Mac. We'll do it the old fashioned way. # This image is of the three window control buttons at top left of the window. # We have to resize the window to ensure maximize works properly in all cases. window_controls_pattern = Pattern('window_controls.png') controls_location = find(window_controls_pattern) xcoord = controls_location.x ycoord = controls_location.y width, height = window_controls_pattern.get_size() drag_start = Location(xcoord + 70, ycoord + 5) drag_end = Location(xcoord + 75, ycoord + 5) Mouse().drag_and_drop(drag_start, drag_end, duration=0.1) # Alt key changes maximize button from full screen to maximize window. maximize_button = window_controls_pattern.target_offset(width / 2 - 3, 0) key_down(Key.ALT) click(maximize_button) key_up(Key.ALT) elif OSHelper.is_windows(): type(text=Key.UP, modifier=KeyModifier.WIN) else: type(text=Key.UP, modifier=[KeyModifier.CTRL, KeyModifier.META]) time.sleep(Settings.DEFAULT_UI_DELAY)
def pytest_runtest_teardown(self, item): BaseTarget.pytest_runtest_teardown(self, item) try: if not OSHelper.is_windows(): if item.funcargs['firefox'].runner and item.funcargs[ 'firefox'].runner.process_handler: quit_firefox() status = item.funcargs[ 'firefox'].runner.process_handler.wait(10) if status is None: item.funcargs['firefox'].browser.runner.stop() else: item.funcargs['firefox'].stop() if not target_args.save: profile_instance = item.funcargs['firefox'].profile if os.path.exists(profile_instance.profile): try: shutil.rmtree(profile_instance.profile, ignore_errors=True) except sqlite3.OperationalError: pass else: logger.error('Invalid Path: %s' % profile_instance.profile) except (AttributeError, KeyError): pass
def get_active_modifiers(key): """Gets all the active modifiers depending on the used OS. :param key: Key modifier. :return: Returns an array with all the active modifiers. """ all_modifiers = [Key.SHIFT, Key.CTRL] if OSHelper.is_mac(): all_modifiers.append(Key.CMD) elif OSHelper.is_windows(): all_modifiers.append(Key.WIN) else: all_modifiers.append(Key.META) all_modifiers.append(Key.ALT) active_modifiers = [] for item in all_modifiers: try: for key_value in key: if item == key_value.value: active_modifiers.append(item) except TypeError: if item == key.value: active_modifiers.append(item) return active_modifiers
def __init__(self): self.root = Tk() self.root.overrideredirect(1) s_width = MULTI_MONITOR_AREA["width"] s_height = MULTI_MONITOR_AREA["height"] self.root.wm_attributes("-topmost", True) canvas = Canvas( self.root, width=s_width, height=s_height, borderwidth=0, highlightthickness=0, bg=Color.BLACK.value, ) canvas.grid() Canvas.draw_circle = _draw_circle Canvas.draw_rectangle = _draw_rectangle if OSHelper.is_mac(): self.root.wm_attributes("-fullscreen", 1) self.root.wm_attributes("-transparent", True) self.root.config(bg="systemTransparent") canvas.config(bg="systemTransparent") canvas.pack() if OSHelper.is_windows(): self.root.wm_attributes("-transparentcolor", Color.BLACK.value) if OSHelper.is_linux(): self.root.wait_visibility(self.root) self.root.attributes("-alpha", 0.7) self.canvas = canvas
def start(self, url=None, image=None, maximize=True): if url is not None: self.url = url if not OSHelper.is_windows(): self.runner = self.launch() self.runner.start() else: try: logger.debug("Starting Firefox with custom command.") FXRunner.process = subprocess.Popen( [ self.application.path, "-no-remote", "-new-tab", self.url, "--wait-for-browser", "-foreground", "-profile", self.profile.profile, ], shell=False, ) except subprocess.CalledProcessError: logger.error("Firefox failed to start") exit(1) confirm_firefox_launch(image) if maximize: maximize_window()
def get_local_firefox_path() -> str or None: """Checks if Firefox is installed on your machine.""" paths = { "osx": [ "/Applications/Firefox.app/Contents/MacOS/firefox", "/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox", "/Applications/Firefox Nightly.app/Contents/MacOS/firefox", ], "win": [ "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe", "C:\\Program Files (x86)\\Firefox Developer Edition\\firefox.exe", "C:\\Program Files (x86)\\Nightly\\firefox.exe", "C:\\Program Files\\Mozilla Firefox\\firefox.exe", "C:\\Program Files\\Firefox Developer Edition\\firefox.exe", "C:\\Program Files\\Nightly\\firefox.exe", ], "linux": ["/usr/bin/firefox", "/usr/lib/firefox/firefox"], } if OSHelper.is_windows(): paths["win"].append(PathManager.get_win_environment_path()) for path in paths[OSHelper.get_os().value]: if os.path.exists(path): return path return None
def select_last_tab(): """Select the last tab.""" if OSHelper.is_mac(): type(text='9', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='9', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='9', modifier=KeyModifier.CTRL)
def open_library(): """Open the Library window.""" if OSHelper.is_mac(): type(text='b', modifier=[KeyModifier.CMD, KeyModifier.SHIFT]) elif OSHelper.is_windows(): type(text='b', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='o', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT])
def open_downloads(): """Open the Downloads dialog.""" if OSHelper.is_mac(): type(text='j', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='j', modifier=KeyModifier.CTRL) else: type(text='y', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT])
def minimize_window(): """Minimize the browser window to the application launch bar.""" if OSHelper.is_mac(): type(text='m', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text=Key.DOWN, modifier=KeyModifier.WIN) else: type(text=Key.DOWN, modifier=[KeyModifier.CTRL, KeyModifier.META]) time.sleep(Settings.DEFAULT_UI_DELAY)
def open_library(): """Open the Library window.""" if OSHelper.is_mac(): type(text='b', modifier=[KeyModifier.CMD, KeyModifier.SHIFT]) elif OSHelper.is_windows(): type(text='b', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='o', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) time.sleep(Settings.DEFAULT_UI_DELAY)
def open_firefox_menu(): """ Opens Firefox top menu """ if OSHelper.is_linux(): key_down(Key.ALT) time.sleep(0.5) key_up(Key.ALT) elif OSHelper.is_windows(): type(Key.ALT)
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 select_tab(num): """Select a given tab (only 1-8). param: num is a string 1-8. example: '4'. """ if OSHelper.is_mac(): type(text=str(num), modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text=str(num), modifier=KeyModifier.CTRL) else: type(text=str(num), modifier=KeyModifier.ALT)
def release_often_used_keys(): """ Releases often used keys """ key_up(KeyModifier.SHIFT) key_up(KeyModifier.CTRL) key_up(KeyModifier.ALT) if OSHelper.is_mac(): key_up(KeyModifier.CMD) if OSHelper.is_windows(): key_up(KeyModifier.WIN)
def path_warning(): logger.critical("Problems were encountered finding the project code root.") logger.critical( "If they persist, try setting these environment variables:") if OSHelper.is_windows(): logger.critical("\tset IRIS_CODE_ROOT=%CD%") logger.critical("\tset PYTHONPATH=%CD%") logger.critical( "\nYou must restart your terminal for this to take effect.\n") else: logger.critical("\texport IRIS_CODE_ROOT=$PWD") logger.critical("\texport PYTHONPATH=$PWD")
def path_warning(path): logger.critical("Path not found: %s" % path) logger.critical("This can happen when Iris can't find your code root.") logger.critical("Try setting these environment variables:") if OSHelper.is_windows(): logger.critical("\tset IRIS_CODE_ROOT=%CD%") logger.critical("\tset PYTHONPATH=%CD%") logger.critical( "\nYou must restart your terminal for this to take effect.\n") else: logger.critical("\texport IRIS_CODE_ROOT=$PWD") logger.critical("\texport PYTHONPATH=$PWD")
def open_library_menu(option): """Open a specific option from 'Library' menu with an option as an argument. :param option: Library menu option to be selected. :return: None """ library_menu_pattern = NavBar.LIBRARY_MENU library_option_list = { 'Bookmarks': 1, 'View Pocket List': 2, 'History': 3, 'Downloads': 4, 'Synced Tabs': 5 } if OSHelper.is_windows(): value = 5 else: value = 4 try: wait(library_menu_pattern, 10) region = Region( image_find(library_menu_pattern).x - Screen().width / value, image_find(library_menu_pattern).y, Screen().width / value, Screen().height / value, ) logger.debug("Library menu found.") except FindError: raise APIHelperError( "Can't find the library menu in the page, aborting test.") else: time.sleep(Settings.DEFAULT_UI_DELAY_LONG) click(library_menu_pattern) time.sleep(Settings.DEFAULT_UI_DELAY_SHORT) try: time.sleep(Settings.DEFAULT_UI_DELAY_SHORT) region.wait(LibraryMenu.BOOKMARKS_OPTION, 10) option_number_in_library_list = library_option_list[option] for _ in range(option_number_in_library_list): time.sleep(0.5) type(Key.TAB) time.sleep(1) type(Key.ENTER) except FindError: raise APIHelperError( "Can't find the option in the page, aborting test.")
def quit_firefox(): """Quit the browser.""" # Press the ESC key to exit any modal dialogs that might prevent key capture. type(text=Key.ESC) # Wait before quitting Firefox to avoid concurrency. time.sleep(1) if OSHelper.is_mac(): type(text='q', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='q', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='q', modifier=KeyModifier.CTRL)
def is_lock_on(key): """Determines if a keyboard key(CAPS LOCK, NUM LOCK or SCROLL LOCK) is ON. :param key: Keyboard key(CAPS LOCK, NUM LOCK or SCROLL LOCK). :return: TRUE if keyboard_key state is ON or FALSE if keyboard_key state is OFF. """ if OSHelper.is_windows(): hll_dll = ctypes.WinDLL("User32.dll") keyboard_code = 0 if key == Key.CAPS_LOCK: keyboard_code = 0x14 elif key == Key.NUM_LOCK: keyboard_code = 0x90 elif key == Key.SCROLL_LOCK: keyboard_code = 0x91 try: key_state = hll_dll.GetKeyState(keyboard_code) & 1 except Exception: raise Exception("Unable to run Command.") if key_state == 1: return True return False elif OSHelper.is_linux() or OSHelper.is_mac(): try: cmd = subprocess.run( "xset q", shell=True, stdout=subprocess.PIPE, timeout=20 ) shutdown_process("Xquartz") except subprocess.CalledProcessError as e: logger.error("Command failed: %s" % repr(e.cmd)) raise Exception("Unable to run Command.") else: processed_lock_key = key.value.label if "caps" in processed_lock_key: processed_lock_key = "Caps" elif "num" in processed_lock_key: processed_lock_key = "Num" elif "scroll" in processed_lock_key: processed_lock_key = "Scroll" stdout = cmd.stdout.decode("utf-8").split("\n") for line in stdout: if processed_lock_key in line: values = re.findall(r"\d*\D+", " ".join(line.split())) for val in values: if processed_lock_key in val and "off" in val: return False return True
def get_terminal_encoding(): """Helper function to get current terminal encoding.""" if OSHelper.is_windows(): logger.debug('Running "chcp" shell command') chcp_output = os.popen("chcp").read().strip() logger.debug('chcp output: "%s"' % chcp_output) if chcp_output.startswith("Active code page:"): codepage = chcp_output.split(": ")[1] logger.debug('Active codepage is "%s"' % codepage) return codepage else: logger.warning("There was an error detecting the active codepage") return None else: logger.debug("Platform does not require switching terminal encoding") return None
def shutdown_process(process_name: str): """Checks if the process name exists in the process list and close it .""" if OSHelper.is_windows(): command_str = "taskkill /IM " + process_name + ".exe" try: subprocess.Popen(command_str, shell=True, stdout=subprocess.PIPE) except subprocess.CalledProcessError: logger.error('Command failed: "%s"' % command_str) raise Exception("Unable to run Command.") elif OSHelper.is_mac() or OSHelper.is_linux(): command_str = "pkill " + process_name try: subprocess.Popen(command_str, shell=True, stdout=subprocess.PIPE) except subprocess.CalledProcessError: logger.error('Command failed: "%s"' % command_str) raise Exception("Unable to run Command.")
def open_library_menu(option): """Open the Library menu with an option as argument. :param option: Library menu option. :return: Custom region created for a more efficient and accurate image pattern search. """ library_menu_pattern = NavBar.LIBRARY_MENU if OSHelper.is_windows(): value = 5 else: value = 4 try: wait(library_menu_pattern, 10) region = Region( image_find(library_menu_pattern).x - Screen().width / value, image_find(library_menu_pattern).y, Screen().width / value, Screen().height / value, ) logger.debug("Library menu found.") except FindError: raise APIHelperError( "Can't find the library menu in the page, aborting test.") else: time.sleep(Settings.DEFAULT_UI_DELAY_LONG) click(library_menu_pattern) time.sleep(Settings.DEFAULT_UI_DELAY_SHORT) try: time.sleep(Settings.DEFAULT_UI_DELAY_SHORT) region.wait(option, 10) logger.debug("Option found.") region.click(option) return region except FindError: raise APIHelperError( "Can't find the option in the page, aborting test.")
def init_tesseract_path(): """Initialize Tesseract path.""" which_tesseract = (subprocess.Popen( "which tesseract", stdout=subprocess.PIPE, shell=True).communicate()[0].rstrip().decode("utf-8")) path_not_found = False if OSHelper.is_windows(): win_default_tesseract_path = "C:\\Program Files (x86)\\Tesseract-OCR" if "/c/" in str(which_tesseract): win_which_tesseract_path = ( which_tesseract.replace("/c/", "C:\\").replace("/", "\\") + ".exe") else: win_which_tesseract_path = which_tesseract.replace("\\", "\\\\") if _check_path(win_default_tesseract_path): pytesseract.pytesseract.tesseract_cmd = ( win_default_tesseract_path + "\\tesseract") elif _check_path(win_which_tesseract_path): pytesseract.pytesseract.tesseract_cmd = win_which_tesseract_path else: path_not_found = True elif OSHelper.is_linux() or OSHelper.is_mac(): if _check_path(which_tesseract): pytesseract.pytesseract.tesseract_cmd = which_tesseract else: path_not_found = True else: path_not_found = True if path_not_found: logger.critical("Unable to find Tesseract.") logger.critical("Please consult wiki for complete setup instructions.") return False return True
class ZoomType(object): """Class with zoom type members.""" IN = 300 if OSHelper.is_windows() else 1 OUT = -300 if OSHelper.is_windows() else -1