def close_all_browsers(): r"""Close all opened browsers. Examples -------- .. code-block:: robotframework CloseAllBrowsers Related keywords ---------------- \`CloseBrowser\`, \`CloseRemoteBrowser\`, \`OpenBrowser\` """ drivers = browser.get_open_browsers() for driver in drivers: _close_remote_browser_session(driver, close_only=True) driver.quit() # remove everything from our cache so that they will not be there for next case. browser.clear_browser_cache() # Clear browser re-use flag as no session open anymore BuiltIn().set_global_variable('${BROWSER_REUSE}', False) # Set 'Headless' flag as False, since no session open anymore CONFIG.set_value('Headless', False)
def get_config(par=None): """Return value of given configuration parameter. If no parameter is given the GetConfig returns all configurations in a python dictionary of current configuration parameter names and their values. Examples -------- .. code-block:: robotframework ${VAL} GetConfig default timeout # Return default timeout value ${VAL} GetConfig # Return all config parameter names and values Parameters ---------- par : str Setting to be fetched """ if par: if not CONFIG.is_value(par): raise ValueError("Parameter {} doesn't exist".format(par)) # Return single configuration value current_config = CONFIG.get_value(par) else: # return whole configuration dictionary current_config = CONFIG.get_all_values() return current_config
def _set_case_insensitivity(val): check = util.par2bool(val) if check: CONFIG.set_value( "ContainingTextMatch", SearchStrategies.CONTAINING_TEXT_MATCH_CASE_INSENSITIVE) else: CONFIG.set_value("ContainingTextMatch", SearchStrategies.CONTAINING_TEXT_MATCH_CASE_SENSITIVE)
def reset_config(par=None): r"""Reset the value of given parameter to default value. If no parameter is given, reset all parameters configuration parameters to their defaults. Reset also returns the value of the given configuration parameter. If no parameter is given, the ResetConfig returns all configurations in a python dictionary with configuration parameter name and their values. Examples -------- .. code-block:: robotframework ${VAL} ResetConfig default timeout # resets single parameter, and returns value ${VAL} ResetConfig # Resets all parameters, and returns config Related keywords ---------------- \`GetConfig\`, \`SetConfig\` """ if par: if not CONFIG.is_value(par): raise ValueError("Parameter {} doesn't exist".format(par)) CONFIG.reset_value(par) # if case insensitive was reset, reset xpath if par.lower() == "caseinsensitive": CONFIG.reset_value("ContainingTextMatch") # Return single configuration value current_config = CONFIG.get_value(par) else: CONFIG.reset_value() # return whole configuration dictionary current_config = CONFIG.get_all_values() return current_config
def debug_on(mode='draw'): """Start debugger with drawing mode and set default timeout down to 2 sec. Examples -------- .. code-block:: robotframework debugon #Start debugger and set timeout to 2sec. debugon debug #Start debugger with SearchMode debug and set timeout to 2sec. Parameters ---------- mode : str debug(default) = Highlight(blink) element without executing kw draw = Highlight element and execute kw """ dbg = DebugLibrary() global cur_mode # pylint: disable=global-statement global cur_timeout # pylint: disable=global-statement cur_mode = CONFIG.get_value('SearchMode') cur_timeout = CONFIG.get_value('DefaultTimeout') CONFIG.set_value('SearchMode', mode) CONFIG.set_value('DefaultTimeout', 2) CONFIG.set_value('Debug_Run', True) dbg.debug()
def maximize_window(): """Maximizes current browser window. Note: This keyword will not fail if maximizing is prevented for some reason. This can happen for example if window manager is not installed or setup correctly. Examples -------- .. code-block:: robotframework MaximizeWindow Parameters ---------- None """ driver = browser.get_current_browser() if driver is None: raise QWebDriverError("No browser open. Use OpenBrowser keyword" " to open browser first") if CONFIG.get_value('Headless') is True: logger.debug("Maximizing browser in headless mode") screen_width_js = driver.execute_script("return screen.width") screen_height_js = driver.execute_script("return screen.height") driver.set_window_size(screen_width_js, screen_height_js) else: driver.maximize_window() size = driver.get_window_size() logger.debug("Window size set to {}x{}".format(size["width"], size["height"]))
def reset_config(par=None): """Reset the value of given parameter to default value. If no parameter is given, reset all parameters configuration parameters to their defaults. Reset also returns the value of the given configuration parameter. If no parameter is given, the ResetConfig returns all configurations in a python dictionary with configuration parameter name and their values. Examples -------- .. code-block:: robotframework ${VAL} ResetConfig default timeout # resets single parameter, and returns value ${VAL} ResetConfig # Resets all parameters, and returns config """ if par: if not CONFIG.is_value(par): raise ValueError("Parameter {} doesn't exist".format(par)) CONFIG.reset_value(par) # Return single configuration value current_config = CONFIG.get_value(par) else: CONFIG.reset_value() # return whole configuration dictionary current_config = CONFIG.get_all_values() return current_config
def wait_page_loaded(): """Wait for webpage to be loaded. Examples -------- .. code-block:: robotframework WaitPageLoaded Each keyword should have this in the beginning since it is crucial that page has been loaded fully. Monkeypatch this method to have different wait. """ if CONFIG["DefaultDocument"]: driver = browser.get_current_browser() if driver is None: raise QWebDriverError("No browser open. Use OpenBrowser keyword" " to open browser first") try: driver.switch_to.default_content() except InvalidSessionIdException as ie: CONFIG.set_value("OSScreenshots", True) raise QWebBrowserError( "Browser session lost. Did browser crash?") from ie except (NoSuchWindowException, WebDriverException) as e: logger.warn( 'Cannot switch to default context, maybe window is closed. Err: {}' .format(e)) if any(s in str(e) for s in FATAL_MESSAGES): CONFIG.set_value("OSScreenshots", True) raise QWebBrowserError(e) from e driver.switch_to.default_content() timeout = CONFIG['XHRTimeout'] if timeout.lower() == "none": return try: xhr.wait_xhr(timestr_to_secs(timeout)) except (WebDriverException, QWebDriverError) as e: logger.info('Unable to check AJAX requests due error: {}'.format(e))
def click_icon(image, template_res_w=None, browser_res_w=None, timeout=0): # pylint: disable=unused-argument r"""Click the icon on the screen. In case you want to click icons you always have to have reference images. If reference picture are not in default folders (images, files, downloads) then BASE_IMAGE_PATH should be defined in a robot file before using this keyword Examples -------- .. code-block:: robotframework *** Variables *** ${BASE_IMAGE_PATH} ${CURDIR}${/}..${/}resources${/}images BASE_IMAGE_PATH should lead to the folder where all your reference icons are .. code-block:: robotframework ClickIcon plane Related keywords ---------------- \`ClickCell\`, \`ClickCheckbox\`, \`ClickElement\`, \`ClickItem\`, \`ClickList\`, \`ClickText\`, \`ClickUntil\`, \`ClickWhile\`, \`VerifyIcon\` """ if not browser_res_w: browser_res_w = util.get_monitor_width( ) # pyautogui works on whole screen # use current resolution by default if not template_res_w: template_res_w = browser_res_w template_res_w, browser_res_w = int(template_res_w), int(browser_res_w) image_path = icon.get_full_image_path(image) x, y = icon.image_recognition(image_path, template_res_w, browser_res_w, pyautog=True) if x == -1: raise QWebElementNotFoundError( "Couldn't find the icon from the screen") if CONFIG.get_value("RetinaDisplay"): x = x * 0.5 y = y * 0.5 pyautogui.moveTo(x, y) pyautogui.click(x, y)
def debug_off(): """Exit debugger. Set timeout and SearchMode back to default. Examples -------- .. code-block:: robotframework debugoff """ CONFIG.set_value('SearchMode', cur_mode) CONFIG.set_value('DefaultTimeout', cur_timeout) CONFIG.set_value('Debug_Run', False) pyautogui.hotkey('ctrl', 'D')
def _log_matched_image(haystack, needle, scaled_needle, loc, best_scale): """Draw a composite image with the needle image, the haystack image, the scaled needle that matches the best and show where in haystack the best match is. This is best used in debugging, but it could be modified to add the image to the Robot log as well. """ needle = cv2.cvtColor(needle, cv2.COLOR_GRAY2BGR) scaled_needle = cv2.cvtColor(scaled_needle, cv2.COLOR_GRAY2BGR) h1, w1 = needle.shape[:2] hs, ws = scaled_needle.shape[:2] h2, w2 = haystack.shape[:2] max_left_w = max(w1, ws) cv2.rectangle(haystack, (loc[0] - int(w1 / 2 * best_scale), loc[1] - int(h1 / 2 * best_scale)), (loc[0] + int(w1 / 2 * best_scale), loc[1] + int(h1 / 2 * best_scale)), (0, 0, 255), 2) result = np.zeros((max(h2, h1), w2 + max_left_w, 3), np.uint8) result[:h1, :w1, :3] = needle result[h1:h1 + hs, :ws, :3] = scaled_needle result[:h2, max_left_w:max_left_w + w2, :3] = haystack cv2.line(result, (ws, h1), (loc[0] + max_left_w + int(ws / 2), loc[1] - int(hs / 2)), (0, 0, 255), 2) cv2.line(result, (0, h1 + hs), (loc[0] + max_left_w - int(ws / 2), loc[1] + int(hs / 2)), (0, 0, 255), 2) if CONFIG.get_value("LogMatchedIcons"): output = BuiltIn().get_variable_value('${OUTPUT DIR}') filename = "temp_matched_image-{}".format(uuid4()) + ".png" filepath = os.path.join(output, SCREEN_SHOT_DIR_NAME, filename) cv2.imwrite(filepath, result) log_screenshot_file(filepath)
def open_browser(executable_path="chromedriver", chrome_args=None, desired_capabilities=None, **kwargs): """Open Chrome browser instance and cache the driver. Parameters ---------- executable_path : str (Default "chromedriver") path to the executable. If the default is used it assumes the executable is in the $PATH. port : int (Default 0) port you would like the service to run, if left as 0, a free port will be found. desired_capabilities : dict (Default None) Dictionary object with non-browser specific capabilities only, such as "proxy" or "loggingPref". chrome_args : Optional arguments to modify browser settings """ options = Options() logger.debug('opt: {}'.format(options)) # If user wants to re-use existing browser session then # he/she has to set variable BROWSER_REUSE_ENABLED to True. # If enabled, then web driver connection details are written # to an argument file. This file enables re-use of the current # chrome session. # # When variables BROWSER_SESSION_ID and BROWSER_EXECUTOR_URL are # set from argument file, then OpenBrowser will use those # parameters instead of opening new chrome session. # New Remote Web Driver is created in headless mode. chrome_path = kwargs.get( 'chrome_path', None) or BuiltIn().get_variable_value('${CHROME_PATH}') if chrome_path: options.binary_location = chrome_path browser_reuse, session_id, executor_url = check_browser_reuse(**kwargs) logger.debug('browser_reuse: {}, session_id: {}, executor_url: {}'.format( browser_reuse, session_id, executor_url)) if browser_reuse and session_id and executor_url: options.add_argument("headless") # Gets rid of Devtools listening .... printing options.add_experimental_option('excludeSwitches', ['enable-logging']) driver = Remote(command_executor=executor_url, desired_capabilities=options.to_capabilities()) BuiltIn().set_global_variable('${BROWSER_REMOTE_SESSION_ID}', driver.session_id) driver.session_id = session_id else: if user.is_root(): options.add_argument("no-sandbox") if chrome_args: if any('headless' in _.lower() for _ in chrome_args): CONFIG.set_value('Headless', True) for item in chrome_args: options.add_argument(item.lstrip()) # options.add_argument("start-maximized") options.add_argument("--disable-notifications") if 'headless' in kwargs: CONFIG.set_value('Headless', True) options.add_argument("headless") if 'prefs' in kwargs: if isinstance(kwargs.get('prefs'), dict): prefs = kwargs.get('prefs') else: prefs = util.prefs_to_dict(kwargs.get('prefs').strip()) options.add_experimental_option('prefs', prefs) driver = Chrome(BuiltIn().get_variable_value('${CHROMEDRIVER_PATH}') or executable_path, options=options, desired_capabilities=desired_capabilities) browser_reuse_enabled = util.par2bool( BuiltIn().get_variable_value('${BROWSER_REUSE_ENABLED}')) or False if browser_reuse_enabled: # Write WebDriver session info to RF arguments file for re-use write_browser_session_argsfile(driver.session_id, driver.command_executor._url) # pylint: disable=protected-access # Clear possible existing global values BuiltIn().set_global_variable('${BROWSER_SESSION_ID}', None) BuiltIn().set_global_variable('${BROWSER_EXECUTOR_URL}', None) browser.cache_browser(driver) return driver
def set_config(par, val): r"""Set configuration parameter to given value. Return previous value. --- Parameter: LogScreenshot Enables or disables logging screenshots when keyword fails. Default is screenshot (True). False disables screenshots from logs when keyword fails. Examples -------- .. code-block:: robotframework SetConfig LogScreenshot False SetConfig LogScreenshot True --- Parameter: ScreenshotType Defines how screenshot is taken. Default is normal screenshot. "html" saves page as html frame in test log. "all" saves both image and html page. Examples -------- .. code-block:: robotframework SetConfig ScreenshotType html SetConfig ScreenshotType screenshot SetConfig ScreenshotType all --- Parameter: OSScreenshots Defines if screenhots are taken using selenium's or operating system's functionalities. Default is selenium screenshot (False). Examples -------- .. code-block:: robotframework SetConfig OSScreenshots True SetConfig OSScreenshots False --- Parameter: CssSelectors Use CSS selectors for finding elements. CSS selectors is optional way to find elements that are difficult to catch by default selectors. Typically those elements are inputs, checkboxes and dropdowns without placeholder texts. With CSS selectors the detection is tried with: * Placeholder or tooltip * Label with 'for' attribute * DOM traversing to detect sibling element Examples -------- .. code-block:: robotframework SetConfig CssSelectors on TypeText MyLocator Robot SetConfig CssSelectors off --- Parameter: SearchDirection Set search direction for element search. Search direction is "up", "down", "left", "right" and "closest" Examples -------- .. code-block:: robotframework SetConfig SearchDirection right TypeText MyLocator Robot SetConfig SearchDirection closest --- Parameter: LineBreak Set key to be pressed after text is written to input field. By default tab key (\ue004) is pressed Values, that are mapped for selenium keys are: ================ ====== Key Value ================ ====== null \ue000 cancel \ue001 help \ue002 backspace \ue003 tab \ue004 clear \ue005 return \ue006 enter \ue007 shift \ue008 left_shift \ue008 control \ue009 left_control \ue009 alt \ue00A left_alt \ue00A pause \ue00B escape \ue00C space \ue00D page_up \ue00E page_down \ue00F end \ue010 home \ue011 left \ue012 arrow_left \ue012 up \ue013 arrow_up \ue013 right \ue014 arrow_right \ue014 down \ue015 arrow_down \ue015 insert \ue016 delete \ue017 semicolon \ue018 equals \ue019 numpad0 \ue01A numpad1 \ue01B numpad2 \ue01C numpad3 \ue01D numpad4 \ue01E numpad5 \ue01F numpad6 \ue020 numpad7 \ue021 numpad8 \ue022 numpad9 \ue023 multiply \ue024 add \ue025 separator \ue026 subtract \ue027 decimal \ue028 divide \ue029 f1 \ue031 f2 \ue032 f3 \ue033 f4 \ue034 f5 \ue035 f6 \ue036 f7 \ue037 f8 \ue038 f9 \ue039 f10 \ue03A f11 \ue03B f12 \ue03C meta \ue03D right_shift \ue050 right_control \ue051 right_alt \ue052 right_meta \ue053 numpad_page_up \ue054 numpad_page_down \ue055 numpad_end \ue056 numpad_home \ue057 numpad_left \ue058 numpad_up \ue059 numpad_right \ue05A numpad_down \ue05B numpad_insert \ue05C numpad_delete \ue05D ================ ====== Examples -------- .. code-block:: robotframework SetConfig LineBreak \ue004 # Tab key SetConfig LineBreak \ue007 # Enter key SetConfig LineBreak ${EMPTY} # Do not send anything --- Parameter: ClearKey Set key to be pressed before text is written to input field. By default uses webdrivers clear method to clear element. Available values are same as with LineBreak. Some keyboard shortcuts also available. Some examples from link below: https://turbofuture.com/computers/keyboard-shortcut-keys: Examples -------- .. code-block:: robotframework SetConfig ClearKey None # Uses clear method (=default) SetConfig ClearKey {NULL} # Does nothing SetConfig ClearKey {CONTROL + A} # Select all and overwrite # One time use: TypeText username Robot clear_key={CONTROL + A} --- Parameter: CheckInputValue Check that real value matches to preferred value after TypeText. If value is not match we try to re type (three times before fail) This is optional feature. Default = false. Use with caution on elements where webdriver has tendency to lost focus and some part of the preferred text gone missing. Examples -------- .. code-block:: robotframework SetConfig CheckInputValue True SetConfig CheckInputValue False # One time use: TypeText username Robot check=True --- Parameter: DefaultTimeout Set default timeout for QWeb keywords. Timeout can be overridden by entering it manually Examples -------- .. code-block:: robotframework SetConfig DefaultTimeout 10s # One time use: VerifyText Foo 60s --- Parameter: XHRTimeout Set default timeout for XHR (How log we wait page to be loaded). Timeout can be overridden by entering it manually Examples -------- .. code-block:: robotframework SetConfig XHRTimeout 60 --- Parameter: DefaultDocument Switches to default frame automatically. If some other frame is used by previous keyword we switch back to default after keyword is executed so that we are starting to find next locator from html document instead of previously used frame. Default = True Use False only when there is need to use and move between frames and page manually for some reason. Examples -------- .. code-block:: robotframework SetConfig DefaultDocument True SetConfig DefaultDocument False SetConfig DefaultDocument On SetConfig DefaultDocument off --- Parameter: CaseInsensitive Set containing_text_match according to selected case sensitivity. Default = False Note: if containing_text_match has been overwritten manually this will return the default value. Examples -------- .. code-block:: robotframework SetConfig CaseInsensitive True SetConfig CaseInsensitive False --- Parameter: VerifyAppAccuracy Set VerifyApp accuracy. Default is 0.9999. You should not use value of 1 because browser rendering will cause false positives. Examples -------- .. code-block:: robotframework SetConfig VerifyAppAccuracy 0.99999 --- Parameter: WindowSize Set window size. Examples -------- .. code-block:: robotframework SetConfig WindowSize 1920x1080 --- Parameter: InputHandler Set input handler. Default handler is "selenium" which uses Selenium library's methods clear() and send_keys(). These methods assume that the web element is writable (enabled). Inserts tab character at the end of text. Alternative writer "raw" uses pyautogui to input text directly without checking the web element state. This version is intended to be used when the web page doesn't update input element status Selenium compliant way. Examples -------- .. code-block:: robotframework SetConfig InputHandler raw SetConfig InputHandler selenium --- Parameter: OffsetCheck Element with no offset is considered invisible by default. To bypass this check set OffsetCheck to false. Examples -------- .. code-block:: robotframework SetConfig OffsetCheck False #returns also elements that has offset=0 SetConfig OffsetCheck True #offset is needed (default) # One time use: ClickItem Qentinel offset=False --- Parameter: Visibility If set to false no visibility check is made when searching elements. Examples -------- .. code-block:: robotframework SetConfig Visibility False #returns visible and invisible elements SetConfig Visibility True #returns only visible elements(default). # One time use: ClickItem Qentinel visibility=False --- Parameter: InViewport If InViewport is set to true every element outside of current viewport is considered invisible. This helps to narrow searching area when there is lots of similar texts/elements in dom content. This can be also used to prevent searching functions to match any element that is hidden outside of viewport - even if css visibility settings of given element says that it's visible. Examples -------- .. code-block:: robotframework SetConfig InViewport False #returns all matching elements(default) SetConfig InViewport True #element has to be inside of current viewport ClickItem Qentinel viewport=False --- Parameter: SearchMode When SearchMode is used, any found web element is highlighted with blue borders before the actual execution. This setting is useful especially in debug mode when we want to search right kw:s and locators to actual testscript. Examples -------- .. code-block:: robotframework SetConfig SearchMode debug #Highlights element, but won't put action on it SetConfig SearchMode draw #Highlights element and then executes kw --- Parameter: WindowFind When WindowFind is used VerifyText is not looking texts for dom, but simulates ctrl+f like search to find if text exists. Examples -------- .. code-block:: robotframework SetConfig WindowFind True #Searching text from current viewport SetConfig WindowFind False #Searching text from dom(default) --- Parameter: SearchStrategy Values Set search strategy for element search. Strategy type is either "all input elements", or "matching input element". "all input elements" is a plain xpath that is used to find all elements considered as input elements. "matching input element" is an xpath with mandatory placeholder "{}" for search string. Xpath expression is completed by xpath.format(locator) internally and therefore must include placeholder "{}". Used to find elements matching with a custom search string. Placeholder can be positional, such as {0} and repeated in that case. Returns previously used search strategy. Examples -------- .. code-block:: robotframework SetConfig ActiveAreaXpath //input//textarea SetConfig AllInputElements //input//textarea SetConfig MatchingInputElement //*[@placeholder="{}"] SetConfig MatchingInputElement containing input element ${previous}= SetConfig AllInputElements //input SetConfig AllInputElements ${previous} note: in the above case "containing input element" will use an xpath expression such that input elements that contain partial matches are used. Parameters ---------- xpath : str xpath expression with or without "xpath = " Raises ------ ValueError Unknown search strategy --- Parameter: MultipleAnchors Normally QWeb requires anchor to be an unique text. If MultipleAnchors is set to False, QWeb accepts multiple anchors and selects the first one. Examples -------- .. code-block:: robotframework SetConfig MultipleAnchors True # Accept multiple anchors SetConfig MultipleAnchors False # Raise error if anchor is not unique --- Parameter: ClickToFocus Clicks Input element before typing. This is sometimes needed to activate target element. Examples -------- .. code-block:: robotframework SetConfig ClickToFocus True # Clicks element before TypeText SetConfig ClickToFocus False # Handle TypeText without clicks(default) --- Parameter: HandleAlerts Option for handling alerts boxes, on by default. Examples -------- .. code-block:: robotframework SetConfig HandleAlerts False --- Parameter: BlindReturn Return any value (even empty) from input element without waiting. Default = false (Raises QWebValueError if field is empty after timeout). Examples -------- .. code-block:: robotframework SetConfig BlindReturn True ${VALUE} GetInputValue username #Some value must exists inside of given timeout(default): SetConfig BlindReturn False ${VALUE} GetInputValue username # One time use: ${VALUE} GetInputValue username blind=True --- Parameter: Delay Set delay for Paceword. This is meant to be used in demo purposes only and is not recommended way to control execution flow. Default = 0s (No delays before execution). Examples -------- .. code-block:: robotframework # Wait 0.5 seconds before any Paceword is executed: SetConfig Delay 0.5s # One time use - Wait 1s before given Paceword is executed: TypeText username QRobot delay=1s --- Parameter: RetryInterval Set default interval for QWeb retry keywords. Timeout can be overridden by entering it manually Examples -------- .. code-block:: robotframework SetConfig RetryInterval 1s # One time use: ClickUntil Foo button interval=3 """ if not CONFIG.is_value(par): raise ValueError("Parameter {} doesn't exist".format(par)) return CONFIG.set_value(par, val)
def open_browser(executable_path="msedgedriver", edge_args=None, desired_capabilities=None, **kwargs): """Open Edge browser instance and cache the driver. Parameters ---------- executable_path : str (Default "msedgedriver") path to the executable. If the default is used it assumes the executable is in the $PATH. port : int (Default 0) port you would like the service to run, if left as 0, a free port will be found. desired_capabilities : dict (Default None) Dictionary object with non-browser specific capabilities only, such as "proxy" or "loggingPref". chrome_args : Optional arguments to modify browser settings """ options = Options() options.use_chromium = True # Gets rid of Devtools listening .... printing # other non-sensical error messages options.add_experimental_option('excludeSwitches', ['enable-logging']) if platform.system().lower() == "windows": options.set_capability("platform", "WINDOWS") if platform.system().lower() == "linux": options.set_capability("platform", "LINUX") if platform.system().lower() == "darwin": options.set_capability("platform", "MAC") # If user wants to re-use existing browser session then # he/she has to set variable BROWSER_REUSE_ENABLED to True. # If enabled, then web driver connection details are written # to an argument file. This file enables re-use of the current # chrome session. # # When variables BROWSER_SESSION_ID and BROWSER_EXECUTOR_URL are # set from argument file, then OpenBrowser will use those # parameters instead of opening new chrome session. # New Remote Web Driver is created in headless mode. edge_path = kwargs.get( 'edge_path', None) or BuiltIn().get_variable_value('${EDGE_PATH}') if edge_path: options.binary_location = edge_path if user.is_root() or user.is_docker(): options.add_argument("no-sandbox") if edge_args: if any('--headless' in _.lower() for _ in edge_args): CONFIG.set_value('Headless', True) for item in edge_args: options.add_argument(item.lstrip()) options.add_argument("start-maximized") options.add_argument("--disable-notifications") if 'headless' in kwargs: CONFIG.set_value('Headless', True) options.add_argument("--headless") if 'prefs' in kwargs: if isinstance(kwargs.get('prefs'), dict): prefs = kwargs.get('prefs') else: prefs = util.prefs_to_dict(kwargs.get('prefs').strip()) options.add_experimental_option('prefs', prefs) logger.warn("prefs: {}".format(prefs)) driver = Edge(BuiltIn().get_variable_value('${EDGEDRIVER_PATH}') or executable_path, options=options, capabilities=desired_capabilities) browser.cache_browser(driver) return driver
def get_elements_from_dom_content(*args, **kwargs): try: args, kwargs, locator = _equal_sign_handler(args, kwargs, fn) msg = None params = signature(fn).parameters args, kwargs = _args_to_kwargs(params, args, kwargs) timeout = get_timeout(**kwargs) logger.debug('Timeout is {} sec'.format(timeout)) try: if 'go_to' not in str(fn) and 'switch_window' not in str(fn): frame.wait_page_loaded() except UnexpectedAlertPresentException as e: if not CONFIG["HandleAlerts"]: raise QWebUnexpectedAlert(str(e)) logger.debug('Got {}. Trying to retry..'.format(e)) time.sleep(SHORT_DELAY) start = time.time() while time.time() < timeout + start: try: kwargs['timeout'] = float(timeout + start - time.time()) config.set_config('FrameTimeout', float(timeout + start - time.time())) return fn(*args, **kwargs) except (QWebUnexpectedConditionError, QWebTimeoutError) as e: logger.warn('Got {}'.format(e)) except (InvalidSelectorException, NoSuchElementException, QWebElementNotFoundError, UnexpectedAlertPresentException, QWebStalingElementError, StaleElementReferenceException, QWebIconNotFoundError) as e: time.sleep(SHORT_DELAY) logger.debug( 'Got exception: {}. Trying to retry..'.format(e)) except InvalidSessionIdException: CONFIG.set_value("OSScreenshots", True) raise QWebBrowserError( "Browser session lost. Did browser crash?") except (WebDriverException, QWebDriverError) as e: if any(s in str(e) for s in FATAL_MESSAGES): CONFIG.set_value("OSScreenshots", True) raise QWebBrowserError(e) logger.info( 'From timeout decorator: Webdriver exception. Retrying..' ) logger.info(e) time.sleep(SHORT_DELAY) err = QWebDriverError msg = e except QWebValueError as ve: logger.debug( 'Got QWebValueError: {}. Trying to retry..'.format(ve)) err = QWebValueError msg = ve time.sleep(SHORT_DELAY) if msg: raise err(msg) if 'count' in str(fn): return 0 if 'is_text' in str(fn) or 'is_no_text' in str(fn): return False raise QWebElementNotFoundError( 'Unable to find element for locator {} in {} sec'.format( locator, timeout)) except QWebSearchingMode: pass
def open_browser(profile_dir=None, capabilities=None, proxy=None, headless=False, binary=None, executable_path="geckodriver", firefox_args=None, timeout=30, log_path="geckodriver.log", **kwargs): """Open Firefox browser and cache the driver. Parameters ---------- binary : FirefoxBinary or str If string then is needs to be the absolute path to the binary. If undefined, the system default Firefox installation will be used. timeout : int Time to wait for Firefox to launch when using the extension connection. capabilities : dict Dictionary of desired capabilities. executable_path : str (Default geckodriver) Full path to override which geckodriver binary to use for Firefox 47.0.1 and greater, which defaults to picking up the binary from the system path. log_path : str (Default "geckdriver.log") Where to log information from the driver. firefox_args : list Optional arguments to modify browser settings. https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options """ options = Options() if headless: logger.warn('Deprecated.\n' 'Headless mode can be activated just like any other firefox option:\n' '"OpenBrowser https://qentinel.com ${BROWSER} -headless"') options.add_argument('-headless') CONFIG.set_value("Headless", True) if profile_dir: logger.warn('Deprecated.\n' 'Profile directory can be selected like any other firefox option:\n' '"OpenBrowser https://qentinel.com ${BROWSER} -profile /path/to/profile"') options.add_argument('-profile {}'.format(profile_dir)) options.set_preference("browser.helperApps.neverAsk.saveToDisk", browser.MIME_TYPES) options.set_preference("extensions.update.enabled", False) options.set_preference("app.update.enabled", False) options.set_preference("app.update.auto", False) options.set_preference("dom.webnotifications.enabled", False) options.set_preference("privacy.socialtracking.block_cookies.enabled", False) kwargs = {k.lower(): v for k, v in kwargs.items()} # Kwargs keys to lowercase if 'prefs' in kwargs: if isinstance(kwargs.get('prefs'), dict): prefs = kwargs.get('prefs') else: prefs = util.prefs_to_dict(kwargs.get('prefs').strip()) for item in prefs.items(): key, value = item[0], item[1] logger.info('Using prefs: {} = {}'.format(key, value), also_console=True) if not isinstance(value, int) and value.isdigit(): value = int(value) options.set_preference(key, value) if firefox_args: if any('headless' in _.lower() for _ in firefox_args): CONFIG.set_value("Headless", True) for option in firefox_args: option = option.strip() options.add_argument(option) driver = webdriver.Firefox(executable_path=executable_path, proxy=proxy, firefox_binary=binary, desired_capabilities=capabilities, options=options, timeout=timeout, log_path=log_path) if os.name == 'nt': # Maximize window if running on windows, doesn't work on linux driver.maximize_window() browser.cache_browser(driver) return driver
def image_location(self, needle, haystack, tolerance=0.95, draw=1, template_res_w=1440, device_res_w=1080): """Locate an image (needle) within an bigger image (haystack). Tolarance is pixel tolerance, i.e. 1.0 = all pixels are correct, 0.5 = 50% of the pixels are correct. If we know the original resolution, from which the template image is coming, we can supply it as template_res_w. Return value is the central (x,y) of the first image found. Draw function will plot red lines where needle image is found. """ print("*INFO* _image_location Starts") image = cv2.imread(haystack) image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _hay_h, hay_w = image_gray.shape[:2] needle_path = Path(needle) if not needle_path.exists(): raise Exception("Needle file does not exist. Tried: {}".format(needle_path)) template = cv2.imread(str(needle_path.resolve()), 0) if template is None: raise Exception("Cannot read template image. Tried: {}".format(needle)) height, width = template.shape[:2] scale_ratios = self._get_scale_ratios(template_res_w, device_res_w) print("*DEBUG* Scale ratios to be used in order: {}".format(scale_ratios)) best_highest_max_val = 0.0 best_highest_max_val_loc = (-1, -1) best_scale_ratio = None best_matched_image = None print("*DEBUG* Resampling loop Starts") for scale_ratio in scale_ratios: interpolation_method = cv2.INTER_LINEAR if scale_ratio > 1.0 else cv2.INTER_AREA print(("*DEBUG* resize starts: for scale {}".format(scale_ratio))) if math.isclose(scale_ratio, 1.0, rel_tol=0.03): scaled_img_template = template else: scaled_img_template = cv2.resize(template, None, fx=scale_ratio, fy=scale_ratio, interpolation=interpolation_method) print("*DEBUG* matchTemplate Starts:") res = cv2.matchTemplate(image_gray, scaled_img_template, cv2.TM_CCOEFF_NORMED) ratio = device_res_w / hay_w if CONFIG.get_value("RetinaDisplay"): ratio = ratio * 2 elif ratio < 1.1: ratio = 1.0 print("*DEBUG* _extract_points Starts:") _current_points, highest_max_val, highest_max_val_loc = \ self._extract_points(height * scale_ratio, res, tolerance, width * scale_ratio, ratio) if highest_max_val > best_highest_max_val: best_highest_max_val = highest_max_val best_highest_max_val_loc = highest_max_val_loc best_scale_ratio = scale_ratio best_matched_image = scaled_img_template print("*DEBUG* Current best match location: {},\n" "max_value: {},\n" "scale_ratio: {}".format(best_highest_max_val_loc, best_highest_max_val, best_scale_ratio)) if best_highest_max_val > tolerance: if draw == 1: loc = np.where(res >= tolerance) for pt in zip(*loc[::-1]): cv2.rectangle(image, pt, (pt[0] + width, pt[1] + height), (0, 0, 255), 2) cv2.imwrite('temp_matched_area.png', image) break print("*DEBUG* Ready to return points:") print("*DEBUG* Best match location: {}, best correlation value: {}, " "best scale ratio: {}".format(best_highest_max_val_loc, best_highest_max_val, best_scale_ratio)) self._log_matched_image(image, template, best_matched_image, best_highest_max_val_loc, best_scale_ratio) if best_highest_max_val >= tolerance: return best_highest_max_val_loc return -1, -1