def test_browserHelper_log(logType): BrowserHelperFunction.browserHelper_log(logType, "Log Text", MagicMock(), MagicMock, extra="test") assert 1 == 1
def goToUrl(self, url): self.statistics.update_teststep() helper.browserHelper_log(logging.INFO, f'GoToUrl:{url}', self.browserData) try: if self.browserName == GC.BROWSER_FIREFOX: self.browserData.driver.set_context("content") self.browserData.driver.get(url) self.setZoomFactor() except WebDriverException as e: # Use noScreenshot-Parameter as otherwise we'll try on a dead browser to create a screenshot helper.browserHelper_log( logging.ERROR, f"Webpage {url} not reached. Error was: {e}", self.browserData, cbTakeScreenshot=self.takeScreenshot) helper.browserHelper_setProxyError(self.randomProxy) raise Exceptions.baangtTestStepException except Exception as e: # Use noScreenshot-Parameter as otherwise we'll try on a dead browser to create a screenshot helper.browserHelper_log(logging.ERROR, f"Webpage {url} throws error {e}", self.browserData, cbTakeScreenshot=self.takeScreenshot) helper.browserHelper_setProxyError(self.randomProxy) raise Exceptions.baangtTestStepException(url, e)
def goBack(self): """ Method to go 1 step back in current tab's browse history @return: """ self.statistics.update_teststep() try: self.javaScript("window.history.go(-1)") except Exception as e: helper.browserHelper_log( logging.WARNING, f"Tried to go back in history, didn't work with error {e}", self.browserData)
def findWaitNotVisible(self, css=None, xpath=None, id=None, timeout=90, optional=False): """ You'd use this method when you wait for an element to disappear, for instance Angular Spinner or a popup to disapear before you continue with your script in the main screen. """ self.statistics.update_teststep() logger.debug( f"Waiting for Element to disappear: XPATH:{xpath}, timeout: {timeout}" ) time.sleep(0.5) stillHere = True elapsed = 0 begin = time.time() while stillHere and elapsed < timeout: try: if xpath: self.element = self.browserData.driver.find_element_by_xpath( xpath) elif id: self.element = self.browserData.driver.find_element_by_id( id) elif css: self.element = self.browserData.driver.find_element_by_css_selector( css) time.sleep(0.2) elapsed = time.time() - begin except Exception as e: # Element gone - exit stillHere = False helper.browserHelper_log( logging.DEBUG, f"Element was gone after {format(elapsed, '.2f')} seconds", self.browserData) if not stillHere: raise Exceptions.baangtTestStepException( f"Element still here after {timeout} seconds. Locator: xpath={xpath}, id={id}" ) return stillHere
def findByAndSetTextValidated(self, id=None, css=None, xpath=None, class_name=None, value=None, iframe=None, timeout=60, retries=5): """ This is a method not recommended to be used regularly. Sometimes (especially with Angular Frontends) it gets pretty hard to set a value into a field. Chrome, but also FF will show the value, but the DOM will not have it. Ths Method should be your last ressort. Here we try <retries> time to set a value. Then we read the element again and compare value to what we'd expect. If value is different and we're less than <retries>-Times, we'll try again. """ tries = 0 self.element, self.html = self.findBy(id=id, css=css, xpath=xpath, class_name=class_name, iframe=iframe, timeout=timeout) while self.element.text != value and self.element.get_property( "value") != value and tries < retries: helper.browserHelper_log( logging.DEBUG, f"Verified trying of SetText - iteration {tries} of {retries}", self.browserData) self.findByAndForceText(id=id, css=css, xpath=xpath, class_name=class_name, iframe=iframe, value=value, timeout=timeout) self.element, self.html = self.findBy(id=id, css=css, xpath=xpath, class_name=class_name, iframe=iframe, timeout=timeout) tries += 1
def _browserFirefoxRun(self, browserName, lCurPath, browserProxy, randomProxy, desiredCapabilities): executable = helper.browserHelper_getBrowserExecutable(browserName) self._downloadDriverCheck(executable, lCurPath, browserName) profile = webDrv.webdriver_setFirefoxProfile(browserProxy, randomProxy) self.downloadFolder = webDrv.getDownloadFolderFromProfile(profile) logger.debug(f"Firefox Profile as follows:{profile.userPrefs}") return webDrv.BROWSER_DRIVERS[browserName]( options=webDrv.webdriver_createBrowserOptions( browserName=browserName, desiredCapabilities=desiredCapabilities), executable_path=helper.browserHelper_findBrowserDriverPaths( executable), firefox_profile=profile, service_log_path=os.path.join(self.managedPaths.getLogfilePath(), 'geckodriver.log'))
def _browserChromeRun(self, browserName, lCurPath, browserProxy, randomProxy, desiredCapabilities): executable = helper.browserHelper_getBrowserExecutable(browserName) self._downloadDriverCheck(executable, lCurPath, browserName) lOptions = webDrv.webdriver_createBrowserOptions( browserName=browserName, desiredCapabilities=desiredCapabilities, browserMobProxy=browserProxy, randomProxy=randomProxy) self.downloadFolder = webDrv.getDownloadFolderFromChromeOptions( options=lOptions) return webDrv.BROWSER_DRIVERS[browserName]( chrome_options=lOptions, executable_path=helper.browserHelper_findBrowserDriverPaths( executable), service_log_path=os.path.join(self.managedPaths.getLogfilePath(), 'chromedriver.log'))
def takeScreenshot(self, screenShotPath=None): driver = self.browserData.driver # Filename must have ".png" inside lFile = str(uuid.uuid4()) + ".png" if screenShotPath: lFile = Path(screenShotPath).joinpath(lFile) else: lFile = Path(self.screenshotPath).joinpath(lFile) try: lFile = str(lFile) driver.save_screenshot(lFile) helper.browserHelper_log(logging.DEBUG, f"Stored Screenshot: {lFile}", self.browserData) except Exception as e: helper.browserHelper_log(logging.INFO, f"Screenshot not possible. Error: {e}", self.browserData) lFile = None return lFile
def downloadDriver(browserName): managedPaths = ManagedPaths() path = Path(managedPaths.getOrSetDriverPath()) logger.debug( f"Trying to download browserDriver for {browserName} into {path}") path.mkdir(parents=True, exist_ok=True) if browserName == GC.BROWSER_FIREFOX: url, isTarFile = helper.browserHelper_getFirefoxFileUrl() if isTarFile: helper.browserHelper_extractTarDriverFile( url, path, GC.GECKO_DRIVER) else: helper.browserHelper_unzipDriverFile(url, path, GC.GECKO_DRIVER) elif browserName == GC.BROWSER_CHROME: url = helper.browserHelper_getChromeFileUrl() helper.browserHelper_unzipDriverFile(url, path, GC.CHROME_DRIVER) else: logger.critical( f"Please download driver for {browserName} manually into folder /browserDrivers" )
def handleIframe(self, iframe=None): """ Give an IFRAME and it will try to go into. If you're inside an iframe it will go out of the iframe """ self.statistics.update_teststep() if iframe: self.browserData.locatorType = "XPATH" self.browserData.locator = iframe helper.browserHelper_log(logging.DEBUG, "Going into Iframe: ", self.browserData, **{"iframe": iframe}) # frame_to_be_availble_and_switch_to_it doesn't work. mustEnd = time.time() + 30 while time.time() < mustEnd: try: self.browserData.driver.switch_to.default_content() self.iFrame = self.browserData.driver.switch_to.frame( iframe) break except WebDriverException as e: helper.browserHelper_log( logging.DEBUG, f"IFrame {iframe} not there yet - waiting 1 second", self.browserData) time.sleep(1) if time.time() > mustEnd: raise TimeoutError elif self.iFrame: helper.browserHelper_log(logging.DEBUG, f"Leaving Iframe: {self.iFrame}", self.browserData) self.browserData.driver.switch_to.default_content() self.iFrame = None else: # TODO add exception, this code should never be reached pass
def webdriver_createBrowserOptions(browserName, desiredCapabilities, browserMobProxy=None, randomProxy=None): """ Translates desired capabilities from the Testrun (or globals) into specific BrowserOptions for the currently active browser @param browserName: any of the GC.BROWSER* @param desiredCapabilities: Settings from TestRun or globals @param browserMobProxy: Proxy-Server IP+Port of internal BrowserMobProxy. @param randomProxy: Proxy-Server IP+Port of random external Proxy @return: the proper BrowserOptions for the currently active browser. """ # Default Download Directory for Attachment downloads if browserName == GC.BROWSER_CHROME: lOptions = ChromeOptions() prefs = { "plugins.plugins_disabled": ["Chrome PDF Viewer"], "plugins.always_open_pdf_externally": True, "profile.default_content_settings.popups": 0, "download.default_directory": helper.browserHelper_setBrowserDownloadDirRandom( ), # IMPORTANT - ENDING SLASH V IMPORTANT "directory_upgrade": True } lOptions.add_experimental_option("prefs", prefs) # Set Proxy for Chrome. First RandomProxy (External), if set. If not, then internal Browsermob if randomProxy: lOptions.add_argument( f"--proxy-server={randomProxy['ip']}:{randomProxy['port']}" ) elif browserMobProxy: lOptions.add_argument('--proxy-server={0}'.format( browserMobProxy.proxy)) elif browserName == GC.BROWSER_FIREFOX: lOptions = ffOptions() else: lOptions = None if desiredCapabilities and lOptions: # sometimes instead of DICT comes a string with DICT-Format if isinstance( desiredCapabilities, str ) and "{" in desiredCapabilities and "}" in desiredCapabilities: desiredCapabilities = json.loads( desiredCapabilities.replace("'", '"')) if isinstance(desiredCapabilities, dict): if desiredCapabilities.get(GC.BROWSER_MODE_HEADLESS): logger.debug("Starting in Headless mode") lOptions.headless = True else: # statement not matched pass else: # statement not matched pass else: # statement not matched pass return lOptions
def createNewBrowser(self, mobileType=None, mobileApp=None, desired_app=None, mobile_app_setting=None, browserName=GC.BROWSER_FIREFOX, desiredCapabilities={}, randomProxy=None, **kwargs): """ Will find the specified executables of the desired browser and start it with the given capabilities. @param browserName: one of GC_BROWSER_*-Browsernames, e.g. GC_BROWSER_FIREFOX @param desiredCapabilities: DICT of desiredCapabilities for this browser @param kwargs: Currently (Jan2020) not used """ self.takeTime("Browser Start") self.randomProxy = randomProxy self.browserName = browserName self.browserProcessID = [] lCurPath = Path(self.managedPaths.getOrSetDriverPath()) if browserName in webDrv.BROWSER_DRIVERS: browserProxy = kwargs.get('browserProxy') browserInstance = kwargs.get('browserInstance', 'unknown') if utils.anything2Boolean(mobileType): self.browserData.driver = self._mobileConnectAppium( browserName, desired_app, mobileApp, mobile_app_setting) elif GC.BROWSER_FIREFOX == browserName: self.browserData.driver = self._browserFirefoxRun( browserName, lCurPath, browserProxy, randomProxy, desiredCapabilities) helper.browserHelper_startBrowsermobProxy( browserName=browserName, browserInstance=browserInstance, browserProxy=browserProxy) self.browserProcessID.append( self.browserData.driver.capabilities.get("moz:processID")) elif GC.BROWSER_CHROME == browserName: self.browserData.driver = self._browserChromeRun( browserName, lCurPath, browserProxy, randomProxy, desiredCapabilities) helper.browserHelper_startBrowsermobProxy( browserName=browserName, browserInstance=browserInstance, browserProxy=browserProxy) try: port = self.browserData.driver.capabilities[ 'goog:chromeOptions']["debuggerAddress"].split(":")[1] fp = os.popen(f"lsof -nP -iTCP:{port} | grep LISTEN") self.browserProcessID.append( int(fp.readlines()[-1].split()[1])) except Exception as ex: logger.info(ex) elif GC.BROWSER_EDGE == browserName: self.browserData.driver = webDrv.BROWSER_DRIVERS[browserName]( executable_path=helper. browserHelper_findBrowserDriverPaths(GC.EDGE_DRIVER)) elif GC.BROWSER_SAFARI == browserName: # SAFARI doesn't provide any options, but desired_capabilities. # Executable_path = the standard safaridriver path. if len(desiredCapabilities) == 0: desiredCapabilities = {} self.browserData.driver = webDrv.BROWSER_DRIVERS[browserName]( desired_capabilities=desiredCapabilities) elif GC.BROWSER_REMOTE == browserName: self.browserData.driver = webDrv.BROWSER_DRIVERS[browserName]( options=webDrv.webdriver_createBrowserOptions( browserName=browserName, desiredCapabilities=desiredCapabilities), command_executor=GC.REMOTE_EXECUTE_URL, desired_capabilities=desiredCapabilities) else: logger.critical( f"Browsername not found: {browserName}. Cancelling test run" ) raise SystemError( f"Browsername not found: {browserName}. Cancelling test run" ) elif GC.BROWSER_REMOTE_V4 == browserName: desired_capabilities, seleniumGridIp, seleniumGridPort = helper.browserHelper_setSettingsRemoteV4( desiredCapabilities) if desired_capabilities['browserName'] == 'firefox': browserExecutable = helper.browserHelper_getBrowserExecutable( GC.BROWSER_FIREFOX) self._downloadDriverCheck(browserExecutable, lCurPath, GC.BROWSER_FIREFOX) elif desired_capabilities['browserName'] == 'chrome': browserExecutable = helper.browserHelper_getBrowserExecutable( GC.BROWSER_CHROME) self._downloadDriverCheck(browserExecutable, lCurPath, GC.BROWSER_CHROME) serverUrl = 'http://' + seleniumGridIp + ':' + seleniumGridPort self.browserData.driver = webDrv.BROWSER_DRIVERS[ GC.BROWSER_REMOTE](command_executor=serverUrl, desired_capabilities=desiredCapabilities) else: raise SystemExit("Browsername unknown") if self.downloadFolder: self.downloadFolderMonitoring = DownloadFolderMonitoring( self.downloadFolder) self.takeTime("Browser Start")
def webdriver_tryAndRetry(browserData, timeout=20, optional=False): """ In: Locator Out: Boolean whether the element was found or not. Also sets the self.element for further use by other Methods (for instance to setText or read existing value) The method is resistant to common timing problems (can't work 100% of the time but will remove at least 80% of your pain compared to directly calling Selenium Methods). """ REQUEST_TIMEOUT_MINIMUM = 1.5 REQUEST_POLL_FREQUENCY = 0.5 element = None html = None begin = time.time() elapsed = 0 if timeout < REQUEST_TIMEOUT_MINIMUM: pollFrequency = timeout / 3 else: pollFrequency = REQUEST_POLL_FREQUENCY internalTimeout = timeout / 5 lLoopCount = 0 try: html = WebdriverFunctions.webdriver_getCurrentHTMLReference( browserData.driver) except BaseException as e: raise Exceptions.baangtTestStepException( f"__getCurrentHTMLReference was not successful: {e}") while not element and elapsed < timeout: lLoopCount += 1 try: driverWait = WebDriverWait(browserData.driver, timeout=internalTimeout, poll_frequency=pollFrequency) if By.ID == browserData.locatorType or By.CSS_SELECTOR == browserData.locatorType: element = driverWait.until( ec.visibility_of_element_located( (browserData.locatorType, browserData.locator))) elif By.CLASS_NAME == browserData.locatorType: element = browserData.driver.find_element_by_class_name( browserData.locator) elif By.XPATH == browserData.locatorType: # visibility of element sometimes not true, but still clickable. If we tried already # 2 times with visibility, let's give it one more try with Presence of element if lLoopCount > 1: logger.debug( f"Tried 2 times to find visible element, now trying presence " f"of element instead, XPATH = {browserData.locator}" ) element = driverWait.until( ec.presence_of_element_located( (browserData.locatorType, browserData.locator))) else: element = driverWait.until( ec.visibility_of_element_located( (browserData.locatorType, browserData.locator))) except StaleElementReferenceException as e: logger.debug("Stale Element Exception - retrying " + str(e)) time.sleep(pollFrequency) except ElementClickInterceptedException as e: logger.debug("ElementClickIntercepted - retrying " + str(e)) time.sleep(pollFrequency) except TimeoutException as e: logger.debug("TimoutException - retrying " + str(e)) time.sleep(pollFrequency) except NoSuchElementException as e: logger.debug("Retrying Webdriver Exception: " + str(e)) time.sleep(pollFrequency) except InvalidSessionIdException as e: logger.debug("WebDriver Exception - terminating testrun: " + str(e)) raise Exceptions.baangtTestStepException except NoSuchWindowException as e: helper.browserHelper_log( logging.CRITICAL, "WebDriver Exception - terminating testrun: " + str(e), browserData) raise Exceptions.baangtTestStepException except ElementNotInteractableException as e: logger.debug("Most probably timeout exception - retrying: " + str(e)) time.sleep(pollFrequency) except WebDriverException as e: helper.browserHelper_log( logging.ERROR, "Retrying WebDriver Exception: " + str(e), browserData) time.sleep(2) elapsed = time.time() - begin return element, html
def webdriver_doSomething(command, element, value=None, timeout=20, optional=False, browserData=None): """ Will interact in an element (that was found before by findBy-Method and stored in self.element) as defined by ``command``. Command can be "SETTEXT" (GC.CMD_SETTEXT), "CLICK" (GC.CMD_CLICK), "FORCETEXT" (GC.CMD_FORCETEXT). Similarly to __try_and_retry the method is pretty robust when it comes to error handling of timing issues. """ NUMBER_OF_SEND_KEY_BACKSPACE = 10 COUNTER_LIMIT_RETRY = 2 COUNTER_LIMIT_ELEMENT_REF = 4 COUNTER_LIMIT_ELEMENT_NOT_INTERACT = 5 didWork = False elapsed = 0 counter = 0 begin = time.time() while not didWork and elapsed < timeout: counter += 1 logger.debug(f"__doSomething {command} with {value}") try: if command.upper() == GC.CMD_SETTEXT: if not value: value = "" element.send_keys(value) elif command.upper() == GC.CMD_CLICK: element.click() elif command.upper() == GC.CMD_FORCETEXT: element.clear() element.click() # element.send_keys(keys.Keys.CONTROL+"A") # for i in range(0, NUMBER_OF_SEND_KEY_BACKSPACE): # element.send_keys(keys.Keys.BACKSPACE) element.send_keys(value) element.send_keys(keys.Keys.TAB) didWork = True except ElementClickInterceptedException as e: logger.debug("doSomething: Element intercepted - retry") time.sleep(0.2) except StaleElementReferenceException as e: logger.debug( f"doSomething: Element stale - retry {browserData.locatorType} {browserData.locator}" ) # If the element is stale after 2 times, try to re-locate the element if counter < COUNTER_LIMIT_RETRY: time.sleep(0.2) elif counter < COUNTER_LIMIT_ELEMENT_REF: begin, element = WebdriverFunctions.webdriver_refindElementAfterError( browserData, timeout, optional=optional) else: raise Exceptions.baangtTestStepException(e) except NoSuchElementException as e: logger.debug("doSomething: Element not there yet - retry") time.sleep(0.5) except InvalidSessionIdException as e: helper.browserHelper_log( logging.ERROR, f"Invalid Session ID Exception caught - aborting... {e} ", browserData) raise Exceptions.baangtTestStepException(e) except ElementNotInteractableException as e: if counter < COUNTER_LIMIT_RETRY: logger.debug( f"Element not interactable {browserData.locatorType} {browserData.locator}, retrying" ) time.sleep(0.2) elif counter < COUNTER_LIMIT_ELEMENT_NOT_INTERACT: logger.debug( f"Element not interactable {browserData.locatorType} {browserData.locator}, re-finding element" ) begin, element = WebdriverFunctions.webdriver_refindElementAfterError( browserData, timeout, optional=optional) else: helper.browserHelper_log(logging.ERROR, f"Element not interactable {e}", browserData) raise Exceptions.baangtTestStepException(e) except NoSuchWindowException as e: raise Exceptions.baangtTestStepException(e) elapsed = time.time() - begin if not didWork: if optional: logger.debug( f"Action not possible after {timeout} s, Locator: {browserData.locatorType}: {browserData.locator}, but flag 'optional' is set" ) else: raise Exceptions.baangtTestStepException( f"Action not possible after {timeout} s, Locator: {browserData.locatorType}: {browserData.locator}" ) else: # Function successful pass return didWork
def test_browserHelper_setProxyError(): BrowserHelperFunction.browserHelper_setProxyError({ "ip": "127.0.0.1", "port": "4444" }) assert 1 == 1
def webdriver_setFirefoxProfile(browserProxy, randomProxy=None): profile = webdriver.FirefoxProfile() if browserProxy: profile.set_proxy(browserProxy.selenium_proxy()) if randomProxy: """ from selenium import webdriver return webdriver.Proxy({ "httpProxy": self.proxy, "sslProxy": self.proxy, }) """ # We shall use a random Proxy from the list: PROXY = f"{randomProxy['ip']}:{randomProxy['port']}" logger.info(f"Using Proxy-Server: {PROXY}") ffProxy = webdriver.Proxy({ "httpProxy": PROXY, "ftpProxy": PROXY, "sslProxy": PROXY, "noProxy": None, "proxy_type": "MANUAL", "proxyType": "MANUAL", "class": "org.openqa.selenium.Proxy", "autodetect": False }) profile.set_proxy(ffProxy) profile.set_preference("browser.download.folderList", 2) profile.set_preference("browser.helperApps.alwaysAsk.force", False) profile.set_preference("browser.download.manager.showWhenStarting", False) profile.set_preference("browser.download.manager.showAlertOnComplete", False) profile.set_preference( 'browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream,application/pdf,application/x-pdf,application/vnd.pdf,application/zip,application/octet-stream,application/x-zip-compressed,multipart/x-zip,application/x-rar-compressed, application/octet-stream,application/msword,application/vnd.ms-word.document.macroEnabled.12,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/rtf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.ms-word.document.macroEnabled.12,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/xls,application/msword,text/csv,application/vnd.ms-excel.sheet.binary.macroEnabled.12,text/plain,text/csv/xls/xlsb,application/csv,application/download,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/octet-stream' ) profile.set_preference( 'browser.helperApps.neverAsk.openFile', 'application/octet-stream,application/pdf,application/x-pdf,application/vnd.pdf,application/zip,application/octet-stream,application/x-zip-compressed,multipart/x-zip,application/x-rar-compressed, application/octet-stream,application/msword,application/vnd.ms-word.document.macroEnabled.12,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/rtf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.ms-word.document.macroEnabled.12,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/xls,application/msword,text/csv,application/vnd.ms-excel.sheet.binary.macroEnabled.12,text/plain,text/csv/xls/xlsb,application/csv,application/download,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/octet-stream' ) profile.set_preference( "browser.download.dir", helper.browserHelper_setBrowserDownloadDirRandom()) profile.set_preference("browser.download.manager.useWindow", False) profile.set_preference("browser.download.manager.focusWhenStarting", False) profile.set_preference("browser.download.manager.showAlertOnComplete", False) profile.set_preference("browser.download.manager.closeWhenDone", True) profile.set_preference("pdfjs.enabledCache.state", False) profile.set_preference( "pdfjs.disabled", True) # This is nowhere on the Internet! But that did the trick! # Set volume to 0 profile.set_preference("media.volume_scale", "0.0") return profile
def test_browserHelper_setSettingsRemoteV4(desiredCapabilities): result = BrowserHelperFunction.browserHelper_setSettingsRemoteV4( desiredCapabilities) assert len(result) == 3