def scroll_into_view(driver: WebDriver, element, offset_pixels=0): """Scrolls page to element using JS""" driver.execute_script("return arguments[0].scrollIntoView();", element) # compensate for the header driver.execute_script("window.scrollBy(0, -{});".format(offset_pixels)) return element
def say_hello(driver: RemoteWebDriver, url: str) -> None: """say hello to HR""" js_code = 'window.open("%s")' % url driver.execute_script(js_code) logger.info(driver.current_window_handle) time.sleep(30) driver.close()
def take_screenshot(driver: WebDriver, page_name: str = None): """Will take a screenshot of current page.""" if TAKE_SCREENSHOTS: if BROWSER == "firefox": # Ref: https://stackoverflow.com/a/52572919/ original_size = driver.get_window_size() required_width = driver.execute_script( "return document.body.parentNode.scrollWidth") required_height = driver.execute_script( "return document.body.parentNode.scrollHeight") driver.set_window_size(required_width, required_height) element = driver.find_element_by_tag_name("body") screenshot_png = element.screenshot_as_png screenshot_jpg = convert_png_to_jpg(screenshot_png) elif BROWSER == "chrome": screenshot_jpg = fullpage_screenshot(driver) if page_name: page_name = page_name.lower().replace(" ", "_")[0:200] allure.attach( screenshot_jpg, name=page_name or "screenshot.jpg", attachment_type=allure.attachment_type.JPG, ) if BROWSER == "firefox": driver.set_window_size(original_size["width"], original_size["height"]) else: logging.debug( f"Taking screenshots is disabled. In order to turn it on " f"please set an environment variable TAKE_SCREENSHOTS=true")
def tab_restart_browser(webdriver: WebDriver) -> None: """ kills the current tab and creates a new one to stop traffic """ # note: this technically uses windows, not tabs, due to problems with # chrome-targeted keyboard commands in Selenium 3 (intermittent # nonsense WebDriverExceptions are thrown). windows can be reliably # created, although we do have to detour into JS to do it. close_other_windows(webdriver) if webdriver.current_url.lower() == 'about:blank': return # Create a new window. Note that it is not practical to use # noopener here, as we would then be forced to specify a bunch of # other "features" that we don't know whether they are on or off. # Closing the old window will kill the opener anyway. webdriver.execute_script("window.open('')") # This closes the _old_ window, and does _not_ switch to the new one. webdriver.close() # The only remaining window handle will be for the new window; # switch to it. # assert len(webdriver.window_handles) == 1 webdriver.switch_to.window(webdriver.window_handles[0])
def hide_elements(driver: WebDriver, elements: list) -> None: """ Usage: Hide elements from web page Args: driver : The path of chromedriver elements : The element on web page to be hide Returns: N/A Raises: N/A """ if elements is not None: try: for e in elements: sp_xpath = e.split('=') if 'id=' in e.lower(): driver.execute_script( "document.getElementById('{}').setAttribute('style', 'display:none;');".format( sp_xpath[1])) elif 'class=' in e.lower(): driver.execute_script( "document.getElementsByClassName('{}')[0].setAttribute('style', 'display:none;');".format( sp_xpath[1])) else: print('For Hiding Element works with ID and Class Selector only') except Exception as Error: print('Error : ', str(Error))
class MouseTest(unittest.TestCase): """Mouse command tests for the json webdriver protocol""" def setUp(self): self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) self._driver = WebDriver(self._launcher.GetURL(), DesiredCapabilities.CHROME) def tearDown(self): self._driver.quit() self._launcher.Kill() def testClickElementThatNeedsContainerScrolling(self): self._driver.get(self._launcher.GetURL() + '/test_page.html') self._driver.find_element_by_name('hidden_scroll').click() self.assertTrue(self._driver.execute_script('return window.success')) def testClickElementThatNeedsIframeScrolling(self): self._driver.get(self._launcher.GetURL() + '/test_page.html') self._driver.switch_to_frame('iframe') self._driver.find_element_by_name('hidden_scroll').click() self.assertTrue(self._driver.execute_script('return window.success')) def testClickElementThatNeedsPageScrolling(self): self._driver.get(self._launcher.GetURL() + '/test_page.html') self._driver.find_element_by_name('far_away').click() self.assertTrue(self._driver.execute_script('return window.success')) def testDoNotScrollUnnecessarilyToClick(self): self._driver.get(self._launcher.GetURL() + '/test_page.html') self._driver.find_element_by_name('near_top').click() self.assertTrue(self._driver.execute_script('return window.success')) script = 'return document.body.scrollTop == 0 && ' \ ' document.body.scrollLeft == 0' self.assertTrue(self._driver.execute_script(script))
def select_options(self, driver: WebDriver, timeout: int): driver.execute_script( f"document.getElementById('sg').setAttribute('value', '{self.grid_size_option}')" ) driver.execute_script( f"document.getElementById('sd').setAttribute('value', '{self.difficulty_option}')" )
def try_alternative_click_on_exception(driver: WebDriver, element: WebElement): """Try alternative click methods (JS or ActionChains) if regular way didn't work. JS workaround: Handle situations when clicking on element triggers: selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <input id="id_terms"> is not clickable at point (714, 1235). Other element would receive the click: <label for="id_terms">...</label> See: https://stackoverflow.com/a/44916498 ActionChains workaround: Handles situations when clicking on element triggers: selenium.common.exceptions.ElementNotInteractableException: Message: Element <a href="..."> could not be scrolled into view See: https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains """ try: yield except ElementClickInterceptedException as e: logging.warning( f"Failed click intercepted. Will try JS workaround for: {e.msg}") driver.execute_script("arguments[0].click();", element) except ElementNotInteractableException as e: logging.warning( f"Failed click intercepted. Will try ActionChains workaround for: {e.msg}" ) action_chains = ActionChains(driver) action_chains.move_to_element(element) action_chains.click() action_chains.perform() logging.warning(f"ActionChains click workaround is done")
def scroll_to_element(driver: WebDriver, element: WebElement): """ Scroll until the specified element is in view""" try: driver.execute_script("window.scrollTo(%s, %s);" % (element.location['x'], element.location['y'])) except WebDriverException: pass
def login_driver(driver:WebDriver): driver.get(ROUTER_IP) sleep(1) usernameEle=driver.find_element_by_id(LOGIN_USERNAME_ID) usernameEle.send_keys(USERNAME) pwdEle=driver.find_element_by_name(LOGIN_PWD_NAME) pwdEle.send_keys(PASSWORD) driver.execute_script("login();")
def get_video_watch_time(driver: WebDriver) -> int: watch_time_js = f'return document.querySelector("{PROMO_VIDEO.value}").currentTime' duration_js = f'return document.querySelector("{PROMO_VIDEO.value}").duration' watch_time = driver.execute_script(watch_time_js) duration = driver.execute_script(duration_js) logging.debug(f"Video watch time: {watch_time}") logging.debug(f"Video duration : {duration}") return int(watch_time)
def scroll_to_bottom(driver: WebDriver) -> None: """ Scroll to the bottom of the page. """ try: driver.execute_script( "window.scrollTo(0, document.body.scrollHeight);") except WebDriverException: pass
def play_video(driver: WebDriver, *, play_time: int = 5): # open(driver, group="what's new", element="watch video") video_load_delay = 2 play_js = f'document.querySelector("{PROMO_VIDEO.value}").play()' pause = f'document.querySelector("{PROMO_VIDEO.value}").pause()' driver.execute_script(play_js) if play_time: time.sleep(play_time + video_load_delay) driver.execute_script(pause)
def open_new_tab(web_driver: WebDriver): while True: try: main_window = web_driver.current_window_handle web_driver.execute_script("window.open('','_blank');") new_window = web_driver.window_handles[-1] web_driver.switch_to.window(new_window) return main_window except TimeoutException: continue
def get_video_watch_time(driver: WebDriver) -> int: watch_time_js = 'return document.querySelector("{}").currentTime'.format( PROMO_VIDEO.value) duration_js = 'return document.querySelector("{}").duration'.format( PROMO_VIDEO.value) watch_time = driver.execute_script(watch_time_js) duration = driver.execute_script(duration_js) logging.debug("Video watch time: %d", watch_time) logging.debug("Video duration : %d", duration) return int(watch_time)
def execute_script_with_retry(driver: WebDriver, script): """Execute script, retrying if a WebDriverException is thrown See: https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/7931#issuecomment-192191013 """ try: return driver.execute_script(script) except WebDriverException: return driver.execute_script(script)
def scrollToTarget(self,browser:WebDriver,by='ID', e:str=''): if browser!=None and e != '': if ':' in e : e = e.split(':')[0] e = browser.find_element(eval('By.'+by),e) # browser.execute_script("arguments[0].scrollIntoViewIfNeeded(true);", target) browser.execute_script("arguments[0].scrollIntoView();", e) else: raise ElementNotFoundException(e)
def scroll_to(driver: WebDriver, target: str, timeout: int = 16) -> Union[bool, None]: if wait(driver=driver, target=target, timeout=timeout): element = util.get_element(driver=driver, target=target, timeout=timeout) driver.execute_script('arguments[0].scrollIntoView(true);', element) else: return False
def click(driver: WebDriver, element): """ Used to resolve issues caused while clicking an element. Very often, elements are overlayed in such a way that a click isn't as simple as it should be. This addresses that; simple call it with - `click(driver, element)` """ driver.execute_script('arguments[0].click();', element)
def obtener_carpetas_en_sesion(driver: WebDriver): lista_de_carpetas_localizadas = [] lista_nombres_de_carpetas_formateadas = [] tiempo_de_inicio = Temporizador.obtener_tiempo_timer() tiempo_de_finalizacion = 0 se_encontraron_carpetas = False while tiempo_de_finalizacion < 60: time.sleep(10) if ValidacionesHTML.verificar_elemento_encontrado_por_clase_js( driver, constantes_webdriver_actions.OBTENER_CARPETAS_EN_SESION_CSS_CARPETA_OWA_2016): AccionesHtml.owa_descubierto = 2016 se_encontraron_carpetas = True elif ValidacionesHTML.verificar_elemento_encontrado_por_clase_js( driver, constantes_webdriver_actions.OBTENER_CARPETAS_EN_SESION_CSS_CARPETA_OWA_2013): AccionesHtml.owa_descubierto = 2013 se_encontraron_carpetas = True elif ValidacionesHTML.verificar_elemento_encontrado_por_xpath( driver, constantes_webdriver_actions.OBTENER_CARPETAS_EN_SESION_XPATH_CARPETA_OWA_2010): AccionesHtml.owa_descubierto = 2010 se_encontraron_carpetas = True tiempo_de_finalizacion = Temporizador.obtener_tiempo_timer() - tiempo_de_inicio if tiempo_de_finalizacion % 20 == 0: AccionesHtml.navegar_a_portal_principal_owa(AccionesHtml.url_owa_exchange) driver.refresh() if not se_encontraron_carpetas: tiempo_de_finalizacion = Temporizador.obtener_tiempo_timer() - tiempo_de_inicio else: time.sleep(4) if AccionesHtml.owa_descubierto == 2010: lista_de_carpetas_localizadas = driver.find_elements_by_xpath( constantes_webdriver_actions.OBTENER_CARPETAS_EN_SESION_XPATH_CARPETA_OWA_2010) elif AccionesHtml.owa_descubierto == 2013: lista_de_carpetas_localizadas = driver.execute_script(constantes_webdriver_actions. OBTENER_CARPETAS_EN_SESION_JS_OBTENER_CARPETA_2013) elif AccionesHtml.owa_descubierto == 2016: lista_de_carpetas_localizadas = driver.execute_script(constantes_webdriver_actions. OBTENER_CARPETAS_EN_SESION_JS_OBTENER_CARPETA_2016) for carpeta in lista_de_carpetas_localizadas: if AccionesHtml.owa_descubierto == 2010: nombre_de_carpeta = carpeta.text else: nombre_de_carpeta = FormatUtils.remover_backspaces(carpeta.get_attribute('innerHTML')) lista_nombres_de_carpetas_formateadas.append(nombre_de_carpeta) return lista_nombres_de_carpetas_formateadas
def open_url(url: str, web_driver: WebDriver): try: web_driver.get(url) return except TimeoutException: while True: try: web_driver.execute_script("window.stop();") return except TimeoutException: continue
def play_video(driver: WebDriver, *, play_time: int = 5): video_load_delay = 2 video = driver.find_element(by=PROMO_VIDEO.by, value=PROMO_VIDEO.value) scroll_to(driver, video) video.click() play_js = f'document.querySelector("{PROMO_VIDEO.value}").play()' pause = f'document.querySelector("{PROMO_VIDEO.value}").pause()' driver.execute_script(play_js) if play_time: time.sleep(play_time + video_load_delay) driver.execute_script(pause)
def __call__(self, driver: WebDriver): # inject and expose javascript testing modules via window.test bundle = open("bundle.js") driver.execute_script(bundle.read()) bundle.close() selector = driver.execute_script( "return window.test.getCssSelector(arguments[0])", self.element ) return ( driver.find_element_by_css_selector(selector + ":invalid") == self.element )
def get_json(browser: WebDriver, context: WebElement, url: str) -> object: browser.execute_script('arguments[0].href = arguments[1]', context, url) browser.execute_script('arguments[0].click()', context) browser.switch_to.window(browser.window_handles[1]) pre = WebDriverWait(browser, timeout=5).until( EC.presence_of_element_located((By.TAG_NAME, 'pre'))) text = pre.text obj = json.loads(text) browser.close() browser.switch_to.window(browser.window_handles[0]) return obj
def scroll_down(driver: WebDriver) -> None: """ Scroll down the current page a random amount. """ at_bottom = False while random.random() > .20 and not at_bottom: driver.execute_script("window.scrollBy(0,%d)" % (10 + int(200 * random.random()))) at_bottom = driver.execute_script( "return (((window.scrollY + window.innerHeight ) + 100 " "> document.body.clientHeight ))") time.sleep(0.5 + random.random())
def screenshot_full_page(visit_id, browser_id, driver: WebDriver, manager_params, suffix=''): outdir = os.path.join(manager_params['screenshot_path'], 'parts') if not os.path.isdir(outdir): os.mkdir(outdir) if suffix != '': suffix = '-' + suffix urlhash = md5(driver.current_url.encode('utf-8')).hexdigest() outname = os.path.join( outdir, '%i-%s%s-part-%%i-%%i.png' % (visit_id, urlhash, suffix)) try: part = 0 max_height = execute_script_with_retry( driver, 'return document.body.scrollHeight;') inner_height = execute_script_with_retry(driver, 'return window.innerHeight;') curr_scrollY = execute_script_with_retry(driver, 'return window.scrollY;') prev_scrollY = -1 driver.save_screenshot(outname % (part, curr_scrollY)) while (curr_scrollY + inner_height) < max_height and \ curr_scrollY != prev_scrollY: # Scroll down to bottom of previous viewport try: driver.execute_script('window.scrollBy(0, window.innerHeight)') except WebDriverException: logger.info("BROWSER %i: WebDriverException while scrolling, " "screenshot may be misaligned!" % browser_id) pass # Update control variables part += 1 prev_scrollY = curr_scrollY curr_scrollY = execute_script_with_retry(driver, 'return window.scrollY;') # Save screenshot driver.save_screenshot(outname % (part, curr_scrollY)) except WebDriverException: excp = traceback.format_exception(*sys.exc_info()) logger.error( "BROWSER %i: Exception while taking full page screenshot \n %s" % (browser_id, ''.join(excp))) return _stitch_screenshot_parts(visit_id, browser_id, manager_params)
def wait_for_page_to_reload(browser: WebDriver, wait_time: int = 30): browser.execute_script( 'document.__selenium_placeholder_id = "SELENIUM_PLACEHOLDER_ID"') yield @wait_until( exception_message=f'не перезагрузилась страница {browser.current_url}', wait_time=wait_time) def wait_to_reload() -> bool: sel_id = browser.execute_script( 'return document.__selenium_placeholder_id') return sel_id != 'SELENIUM_PLACEHOLDER_ID' wait_to_reload()
def init_lihkg_context(browser: WebDriver) -> WebElement: ''' We need to open a LIHKG page and then jump to the API URL. This process is wrapped as the LIHKG context. ''' browser.get('https://lihkg.com/thread/2256553/page/1') body = WebDriverWait(browser, timeout=5).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) element_id = random_string() browser.execute_script(f'a = document.createElement("a"); a.id = arguments[1]; a.target = "_blank"; arguments[0].appendChild(a)', body, element_id) context = browser.find_element(By.ID, element_id) return context
def check_selenium_service(command_executor): browser = WebDriver(command_executor=command_executor, desired_capabilities=DesiredCapabilities.FIREFOX) try: browser.get('https://www.youtube.com/watch?v=dfTWTC7UtcQ') browser.execute_script("window.scrollTo(0, document.body.offsetHeight);") WebDriverWait(browser, 5).until( EC.presence_of_element_located((By.CLASS_NAME, "comment-renderer-text-content")) ) assert u'comment-renderer-text-content' in browser.page_source logging.warning("check remote web driver (%s) successful." % command_executor) finally: browser.close() browser.quit()
def resize_to_page_size(driver: WebDriver): """ Resizes the window to the size of the whole web page Details: Copied from https://gist.github.com/elcamino/5f562564ecd2fb86f559 """ width = driver.execute_script( "return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, " "document.documentElement.scrollWidth, document.documentElement.offsetWidth);") height = driver.execute_script( "return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight," " document.documentElement.scrollHeight, document.documentElement.offsetHeight);") driver.set_window_size(width + 100, height + 100)
def hover(driver: WebDriver, target: str, timeout: int = 16) -> Union[bool, None]: if wait(driver, target, timeout): element = util.get_element(driver=driver, target=target, timeout=timeout) driver.execute_script( "var event = new MouseEvent('mouseover', {'view': window, 'bubbles': true, 'cancelable': true});arguments[0].dispatchEvent(event);", element) action = ActionChains(driver) action.move_to_element(element) action.perform() else: return False
def check_selenium_service(command_executor): browser = WebDriver(command_executor=command_executor, desired_capabilities=DesiredCapabilities.FIREFOX) try: browser.get('https://www.youtube.com/watch?v=dfTWTC7UtcQ') browser.execute_script( "window.scrollTo(0, document.body.offsetHeight);") WebDriverWait(browser, 5).until( EC.presence_of_element_located( (By.CLASS_NAME, "comment-renderer-text-content"))) assert u'comment-renderer-text-content' in browser.page_source logging.warning("check remote web driver (%s) successful." % command_executor) finally: browser.close() browser.quit()
def is_loaded(webdriver: WebDriver) -> bool: """ Check if the HTML DOM reports that the page is fully loaded. AJAX or pending script execution could still alter the page however. """ return ( webdriver.execute_script("return document.readyState") == "complete")
def get_gtm_data_layer_properties(driver: WebDriver) -> dict: """ WebDriver returns GTM data layer properties formatted like so: [ { 'event': 'gtm.js', 'gtm.start': 1559324711826 }, { 'businessUnit': 'International', 'loginStatus': 'False', 'siteLanguage': 'en-gb', 'siteSection': 'Topic', 'siteSubsection': 'ListingPage', 'userId': 'None' } ] We're only interested in the seconds item. In order to make the result easier to work with, some extra parsing is done. Only if a value contains string representation of boolean & None type. """ script_result = driver.execute_script("return window.dataLayer;") assert script_result, f"window.dataLayer on {driver.current_url} is empty!" data_layer_raw = { key: value for item in script_result for key, value in item.items() if "businessUnit" in item } return replace_string_representations(data_layer_raw)
def exists(driver: WebDriver) -> str: """ Checks if jQuery exists in the current context. Returns: The version if found, else returns an empty string """ version = driver.execute_script('return jQuery().jquery;') return version if version is not None else ''
class ElementEqualityTest(unittest.TestCase): """Tests that the server properly checks element equality.""" def setUp(self): self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) self._driver = WebDriver(self._launcher.GetURL(), {}) def tearDown(self): self._driver.quit() self._launcher.Kill() def testElementEquality(self): self._driver.get(self._launcher.GetURL() + "/test_page.html") body1 = self._driver.find_element_by_tag_name("body") body2 = self._driver.execute_script("return document.body") # TODO(jleyba): WebDriver's python bindings should expose a proper API # for this. result = body1._execute(Command.ELEMENT_EQUALS, {"other": body2.id}) self.assertTrue(result["value"])
class BaseCase(unittest.TestCase): ''' A base test case that wraps methods for enhanced usage. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None self.page_check_count = 0 self.page_check_failures = [] def open(self, url): self.driver.get(url) if settings.WAIT_FOR_RSC_ON_PAGE_LOADS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def open_url(self, url): """ In case people are mixing up self.open() with open(), use this alternative. """ self.open(url) def click(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH element = page_actions.wait_for_element_visible( self.driver, selector, by, timeout=timeout) self._demo_mode_highlight_if_active(selector, by) pre_action_url = self.driver.current_url element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() if self.demo_mode: if self.driver.current_url != pre_action_url: self._demo_mode_pause_if_active() else: self._demo_mode_pause_if_active(tiny=True) def click_chain(self, selectors_list, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT, spacing=0): """ This method clicks on a list of elements in succession. 'spacing' is the amount of time to wait between clicks. (sec) """ for selector in selectors_list: self.click(selector, by=by, timeout=timeout) if spacing > 0: time.sleep(spacing) def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT): """ This method clicks link text on a page """ # If using phantomjs, might need to extract and open the link directly if self.browser == 'phantomjs': if self.is_link_text_visible(link_text): element = self.wait_for_link_text_visible(link_text) element.click() return source = self.driver.page_source soup = BeautifulSoup(source) html_links = soup.fetch('a') for html_link in html_links: if html_link.text == link_text: for html_attribute in html_link.attrs: if html_attribute[0] == 'href': href = html_attribute[1] if href.startswith('//'): link = "http:" + href elif href.startswith('/'): url = self.driver.current_url domain_url = self.get_domain_url(url) link = domain_url + href else: link = href self.open(link) return raise Exception( 'Could not parse link from link_text [%s]' % link_text) raise Exception("Link text [%s] was not found!" % link_text) # Not using phantomjs element = self.wait_for_link_text_visible(link_text, timeout=timeout) self._demo_mode_highlight_if_active(link_text, by=By.LINK_TEXT) pre_action_url = self.driver.current_url element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() if self.demo_mode: if self.driver.current_url != pre_action_url: self._demo_mode_pause_if_active() else: self._demo_mode_pause_if_active(tiny=True) def get_text(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): element = page_actions.wait_for_element_visible( self.driver, selector, by, timeout) return element.text def get_attribute(self, selector, attribute, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): element = page_actions.wait_for_element_present( self.driver, selector, by, timeout) attribute_value = element.get_attribute(attribute) if attribute_value is not None: return attribute_value else: raise Exception("Element [%s] has no attribute [%s]!" % ( selector, attribute)) def add_text(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ The more-reliable version of driver.send_keys() Similar to update_text(), but won't clear the text field first. """ element = self.wait_for_element_visible( selector, by=by, timeout=timeout) self._demo_mode_highlight_if_active(selector, by) pre_action_url = self.driver.current_url element.send_keys(new_value) if self.demo_mode: if self.driver.current_url != pre_action_url: self._demo_mode_pause_if_active() else: self._demo_mode_pause_if_active(tiny=True) def send_keys(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Same as add_text() -> more reliable, but less name confusion. """ self.add_text(selector, new_value, by=by, timeout=timeout) def update_text_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT, retry=False): """ This method updates an element's text value with a new value. @Params selector - the selector with the value to update new_value - the new value for setting the text field by - the type of selector to search by (Default: CSS) timeout - how long to wait for the selector to be visible retry - if True, use jquery if the selenium text update fails """ element = self.wait_for_element_visible( selector, by=by, timeout=timeout) self._demo_mode_highlight_if_active(selector, by) element.clear() self._demo_mode_pause_if_active(tiny=True) pre_action_url = self.driver.current_url element.send_keys(new_value) if (retry and element.get_attribute('value') != new_value and ( not new_value.endswith('\n'))): logging.debug('update_text_value is falling back to jQuery!') selector = self.jq_format(selector) self.set_value(selector, new_value, by=by) if self.demo_mode: if self.driver.current_url != pre_action_url: self._demo_mode_pause_if_active() else: self._demo_mode_pause_if_active(tiny=True) def update_text(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT, retry=False): """ The shorter version of update_text_value(), which clears existing text and adds new text into the text field. We want to keep the old version for backward compatibility. """ self.update_text_value(selector, new_value, by=by, timeout=timeout, retry=retry) def is_element_present(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_element_visible(self.driver, selector, by) def is_link_text_visible(self, link_text): return page_actions.is_element_visible(self.driver, link_text, by=By.LINK_TEXT) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_text_visible(self.driver, text, selector, by) def find_visible_elements(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.find_visible_elements(self.driver, selector, by) def execute_script(self, script): return self.driver.execute_script(script) def set_window_size(self, width, height): return self.driver.set_window_size(width, height) self._demo_mode_pause_if_active() def maximize_window(self): return self.driver.maximize_window() self._demo_mode_pause_if_active() def activate_jquery(self): """ If "jQuery is not defined", use this method to activate it for use. This happens because jQuery is not always defined on web sites. """ try: # Let's first find out if jQuery is already defined. self.execute_script("jQuery('html')") # Since that command worked, jQuery is defined. Let's return. return except Exception: # jQuery is not currently defined. Let's proceed by defining it. pass self.execute_script( '''var script = document.createElement("script"); ''' '''script.src = "http://code.jquery.com/jquery-2.2.4.min.js"; ''' '''document.getElementsByTagName("head")[0]''' '''.appendChild(script);''') for x in xrange(30): # jQuery needs a small amount of time to activate. (At most 3s) try: self.execute_script("jQuery('html')") return except Exception: time.sleep(0.1) # Since jQuery still isn't activating, give up and raise an exception raise Exception("Exception: WebDriver could not activate jQuery!") def highlight(self, selector, by=By.CSS_SELECTOR, loops=4, scroll=True): """ This method uses fancy javascript to highlight an element. Used during demo_mode. @Params selector - the selector of the element to find by - the type of selector to search by (Default: CSS) loops - # of times to repeat the highlight animation (Default: 4) (4 loops is about 0.70 seconds. Your mileage may vary) scroll - the option to scroll to the element first (Default: True) """ element = self.find_element( selector, by=by, timeout=settings.SMALL_TIMEOUT) if scroll: self._slow_scroll_to_element(element) try: selector = self.convert_to_css_selector(selector, by=by) except Exception: # Don't highlight if can't convert to CSS_SELECTOR for jQuery return # Only get the first match last_syllable = selector.split(' ')[-1] if ':' not in last_syllable: selector += ':first' o_bs = '' # original_box_shadow style = element.get_attribute('style') if style: if 'box-shadow: ' in style: box_start = style.find('box-shadow: ') box_end = style.find(';', box_start) + 1 original_box_shadow = style[box_start:box_end] o_bs = original_box_shadow script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(128, 128, 128, 0.5)');""" % selector try: self.execute_script(script) except Exception: self.activate_jquery() self.execute_script(script) loops = int(loops) for n in xrange(loops): script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(255, 0, 0, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(128, 0, 128, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(0, 0, 255, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(0, 255, 0, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(128, 128, 0, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '0px 0px 6px 6px rgba(128, 0, 128, 1)');""" % selector self.execute_script(script) time.sleep(0.02) script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs) self.execute_script(script) time.sleep(0.065) def scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): ''' Fast scroll to destination ''' element = self.wait_for_element_visible( selector, by=by, timeout=timeout) self._scroll_to_element(element) def slow_scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): ''' Slow motion scroll to destination ''' element = self.wait_for_element_visible( selector, by=by, timeout=timeout) self._slow_scroll_to_element(element) def scroll_click(self, selector, by=By.CSS_SELECTOR): self.scroll_to(selector, by=by) self.click(selector, by=by) def jquery_click(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH selector = self.convert_to_css_selector(selector, by=by) self.wait_for_element_present( selector, by=by, timeout=settings.SMALL_TIMEOUT) if self.is_element_visible(selector, by=by): self._demo_mode_highlight_if_active(selector, by) # Only get the first match last_syllable = selector.split(' ')[-1] if ':' not in last_syllable: selector += ':first' click_script = """jQuery('%s')[0].click()""" % selector try: self.execute_script(click_script) except Exception: # The likely reason this fails is because: "jQuery is not defined" self.activate_jquery() # It's a good thing we can define it here self.execute_script(click_script) self._demo_mode_pause_if_active() def jq_format(self, code): return page_utils.jq_format(code) def get_domain_url(self, url): return page_utils.get_domain_url(url) def download_file(self, file_url, destination_folder=None): """ Downloads the file from the url to the destination folder. If no destination folder is specified, the default one is used. """ if not destination_folder: destination_folder = constants.Files.DOWNLOADS_FOLDER page_utils._download_file_to(file_url, destination_folder) return True def save_file_as(self, file_url, new_file_name, destination_folder=None): """ Similar to self.download_file(), except that you get to rename the file being downloaded to whatever you want. """ if not destination_folder: destination_folder = constants.Files.DOWNLOADS_FOLDER page_utils._download_file_to( file_url, destination_folder, new_file_name) return True def convert_xpath_to_css(self, xpath): return xpath_to_css.convert_xpath_to_css(xpath) def convert_to_css_selector(self, selector, by): """ This method converts a selector to a CSS_SELECTOR. jQuery commands require a CSS_SELECTOR for finding elements. This method should only be used for jQuery actions. """ if by == By.CSS_SELECTOR: return selector elif by == By.ID: return '#%s' % selector elif by == By.CLASS_NAME: return '.%s' % selector elif by == By.NAME: return '[name="%s"]' % selector elif by == By.TAG_NAME: return selector elif by == By.XPATH: return self.convert_xpath_to_css(selector) elif by == By.LINK_TEXT: return 'a:contains("%s")' % selector elif by == By.PARTIAL_LINK_TEXT: return 'a:contains("%s")' % selector else: raise Exception( "Exception: Could not convert [%s](by=%s) to CSS_SELECTOR!" % ( selector, by)) def set_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ This method uses jQuery to update a text field. """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH selector = self.convert_to_css_selector(selector, by=by) self._demo_mode_highlight_if_active(selector, by) self.scroll_to(selector, by=by, timeout=timeout) value = json.dumps(new_value) # Only get the first match last_syllable = selector.split(' ')[-1] if ':' not in last_syllable: selector += ':first' set_value_script = """jQuery('%s').val(%s)""" % (selector, value) try: self.execute_script(set_value_script) except Exception: # The likely reason this fails is because: "jQuery is not defined" self.activate_jquery() # It's a good thing we can define it here self.execute_script(set_value_script) self._demo_mode_pause_if_active() def jquery_update_text_value(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ This method uses jQuery to update a text field. If the new_value string ends with the newline character, WebDriver will finish the call, which simulates pressing {Enter/Return} after the text is entered. """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH element = self.wait_for_element_visible( selector, by=by, timeout=timeout) self._demo_mode_highlight_if_active(selector, by) self.scroll_to(selector, by=by) selector = self.convert_to_css_selector(selector, by=by) # Only get the first match last_syllable = selector.split(' ')[-1] if ':' not in last_syllable: selector += ':first' update_text_script = """jQuery('%s').val('%s')""" % ( selector, self.jq_format(new_value)) try: self.execute_script(update_text_script) except Exception: # The likely reason this fails is because: "jQuery is not defined" self.activate_jquery() # It's a good thing we can define it here self.execute_script(update_text_script) if new_value.endswith('\n'): element.send_keys('\n') self._demo_mode_pause_if_active() def jquery_update_text(self, selector, new_value, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ The shorter version of jquery_update_text_value() (The longer version remains for backwards compatibility.) """ self.jquery_update_text_value( selector, new_value, by=by, timeout=timeout) def hover_on_element(self, selector, by=By.CSS_SELECTOR): self.wait_for_element_visible( selector, by=by, timeout=settings.SMALL_TIMEOUT) self._demo_mode_highlight_if_active(selector, by) self.scroll_to(selector, by=by) time.sleep(0.05) # Settle down from scrolling before hovering return page_actions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, hover_by=By.CSS_SELECTOR, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): if hover_selector.startswith('/') or hover_selector.startswith('./'): hover_by = By.XPATH if click_selector.startswith('/') or click_selector.startswith('./'): click_by = By.XPATH self.wait_for_element_visible( hover_selector, by=hover_by, timeout=timeout) self._demo_mode_highlight_if_active(hover_selector, hover_by) self.scroll_to(hover_selector, by=hover_by) pre_action_url = self.driver.current_url element = page_actions.hover_and_click( self.driver, hover_selector, click_selector, hover_by, click_by, timeout) if self.demo_mode: if self.driver.current_url != pre_action_url: self._demo_mode_pause_if_active() else: self._demo_mode_pause_if_active(tiny=True) return element ############ def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Waits for an element to appear in the HTML of a page. The element does not need be visible (it may be hidden). """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_present( self.driver, selector, by, timeout) def assert_element_present(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_element_present(), but returns nothing. Waits for an element to appear in the HTML of a page. The element does not need be visible (it may be hidden). Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_element_present(selector, by=by, timeout=timeout) return True # For backwards compatibility, earlier method names of the next # four methods have remained even though they do the same thing, # with the exception of assert_*, which won't return the element, # but like the others, will raise an exception if the call fails. def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Waits for an element to appear in the HTML of a page. The element must be visible (it cannot be hidden). """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_visible( self.driver, selector, by, timeout) def wait_for_element(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_element_visible() """ return self.wait_for_element_visible(selector, by=by, timeout=timeout) def find_element(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Same as wait_for_element_visible() - returns the element """ return self.wait_for_element_visible(selector, by=by, timeout=timeout) def assert_element(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_element_visible(), but returns nothing. As above, will raise an exception if nothing can be found. Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_element_visible(selector, by=by, timeout=timeout) return True # For backwards compatibility, earlier method names of the next # four methods have remained even though they do the same thing, # with the exception of assert_*, which won't return the element, # but like the others, will raise an exception if the call fails. def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_text_visible( self.driver, text, selector, by, timeout) def wait_for_text(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_text_visible() """ return self.wait_for_text_visible( text, selector, by=by, timeout=timeout) def find_text(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Same as wait_for_text_visible() - returns the element """ return self.wait_for_text_visible( text, selector, by=by, timeout=timeout) def assert_text(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_text_visible(), but returns nothing. As above, will raise an exception if nothing can be found. Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_text_visible(text, selector, by=by, timeout=timeout) return True # For backwards compatibility, earlier method names of the next # four methods have remained even though they do the same thing, # with the exception of assert_*, which won't return the element, # but like the others, will raise an exception if the call fails. def wait_for_link_text_visible(self, link_text, timeout=settings.LARGE_TIMEOUT): return self.wait_for_element_visible( link_text, by=By.LINK_TEXT, timeout=timeout) def wait_for_link_text(self, link_text, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_link_text_visible() """ return self.wait_for_link_text_visible(link_text, timeout=timeout) def find_link_text(self, link_text, timeout=settings.LARGE_TIMEOUT): """ Same as wait_for_link_text_visible() - returns the element """ return self.wait_for_link_text_visible(link_text, timeout=timeout) def assert_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_link_text_visible(), but returns nothing. As above, will raise an exception if nothing can be found. Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_link_text_visible(link_text, timeout=timeout) return True ############ def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Waits for an element to no longer appear in the HTML of a page. A hidden element still counts as appearing in the page HTML. If an element with "hidden" status is acceptable, use wait_for_element_not_visible() instead. """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_absent( self.driver, selector, by, timeout) def assert_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_element_absent() - returns nothing. As above, will raise an exception if the element stays present. Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_element_absent(selector, by=by, timeout=timeout) return True ############ def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ Waits for an element to no longer be visible on a page. The element can be non-existant in the HTML or hidden on the page to qualify as not visible. """ if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_not_visible( self.driver, selector, by, timeout) def assert_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): """ Similar to wait_for_element_not_visible() - returns nothing. As above, will raise an exception if the element stays visible. Returns True if successful. Default timeout = SMALL_TIMEOUT. """ self.wait_for_element_not_visible(selector, by=by, timeout=timeout) return True ############ def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT): return page_actions.wait_for_ready_state_complete(self.driver, timeout) def wait_for_and_accept_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_accept_alert(self.driver, timeout) def wait_for_and_dismiss_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_dismiss_alert(self.driver, timeout) def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_switch_to_alert(self.driver, timeout) def save_screenshot(self, name, folder=None): return page_actions.save_screenshot(self.driver, name, folder) ############ def _get_exception_message(self): """ This method extracts the message from an exception if there was an exception that occurred during the test, assuming that the exception was in a try/except block and not thrown. """ exception_info = sys.exc_info()[1] if hasattr(exception_info, 'msg'): exc_message = exception_info.msg elif hasattr(exception_info, 'message'): exc_message = exception_info.message else: exc_message = '(Unknown Exception)' return exc_message def _package_check(self): current_url = self.driver.current_url message = self._get_exception_message() self.page_check_failures.append( "CHECK #%s: (%s)\n %s" % ( self.page_check_count, current_url, message)) def check_assert_element(self, selector, by=By.CSS_SELECTOR, timeout=settings.MINI_TIMEOUT): """ A non-terminating assertion for an element on a page. Any and all exceptions will be saved until the process_checks() method is called from inside a test, likely at the end of it. """ self.page_check_count += 1 try: self.wait_for_element_visible(selector, by=by, timeout=timeout) return True except Exception: self._package_check() return False def check_assert_text(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.MINI_TIMEOUT): """ A non-terminating assertion for text from an element on a page. Any and all exceptions will be saved until the process_checks() method is called from inside a test, likely at the end of it. """ self.page_check_count += 1 try: self.wait_for_text_visible(text, selector, by=by, timeout=timeout) return True except Exception: self._package_check() return False def process_checks(self): """ To be used at the end of any test that uses checks, which are non-terminating verifications that will only raise an exception after this method is called. Useful for pages with multiple elements to be checked when you want to find as many failures as possible on a page before making fixes. Might be more useful if this method is called after processing all the checks for a single html page, otherwise the screenshot in the logs file won't match the location of the checks. """ if self.page_check_failures: exception_output = '' exception_output += "\n*** FAILED CHECKS FOR: %s\n" % self.id() all_failing_checks = self.page_check_failures self.page_check_failures = [] for tb in all_failing_checks: exception_output += "%s\n" % tb raise Exception(exception_output) ############ def _demo_mode_pause_if_active(self, tiny=False): if self.demo_mode: if self.demo_sleep: wait_time = float(self.demo_sleep) else: wait_time = settings.DEFAULT_DEMO_MODE_TIMEOUT if not tiny: time.sleep(wait_time) else: time.sleep(wait_time/3.4) def _demo_mode_scroll_if_active(self, selector, by): if self.demo_mode: self.slow_scroll_to(selector, by=by) def _demo_mode_highlight_if_active(self, selector, by): if self.demo_mode: # Includes self.slow_scroll_to(selector, by=by) by default self.highlight(selector, by=by) def _scroll_to_element(self, element): element_location = element.location['y'] element_location = element_location - 130 if element_location < 0: element_location = 0 scroll_script = "window.scrollTo(0, %s);" % element_location # The old jQuery scroll_script required by=By.CSS_SELECTOR # scroll_script = "jQuery('%s')[0].scrollIntoView()" % selector self.execute_script(scroll_script) self._demo_mode_pause_if_active(tiny=True) def _slow_scroll_to_element(self, element): scroll_position = self.execute_script("return window.scrollY;") element_location = element.location['y'] element_location = element_location - 130 if element_location < 0: element_location = 0 distance = element_location - scroll_position if distance != 0: total_steps = int(abs(distance) / 50.0) + 2.0 step_value = float(distance) / total_steps new_position = scroll_position for y in xrange(int(total_steps)): time.sleep(0.0114) new_position += step_value scroll_script = "window.scrollTo(0, %s);" % new_position self.execute_script(scroll_script) time.sleep(0.01) scroll_script = "window.scrollTo(0, %s);" % element_location self.execute_script(scroll_script) time.sleep(0.01) if distance > 430 or distance < -300: # Add small recovery time for long-distance slow-scrolling time.sleep(0.162) # PyTest-Specific Code # def setUp(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass setUp() method: super(SubClassOfBaseCase, self).setUp() """ self.is_pytest = None try: # This raises an exception if the test is not coming from pytest self.is_pytest = pytest.config.option.is_pytest except Exception: # Not using pytest (probably nosetests) self.is_pytest = False if self.is_pytest: test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) self.with_selenium = pytest.config.option.with_selenium self.headless = pytest.config.option.headless self.headless_active = False self.with_testing_base = pytest.config.option.with_testing_base self.with_db_reporting = pytest.config.option.with_db_reporting self.with_s3_logging = pytest.config.option.with_s3_logging self.with_screen_shots = pytest.config.option.with_screen_shots self.with_basic_test_info = ( pytest.config.option.with_basic_test_info) self.with_page_source = pytest.config.option.with_page_source self.database_env = pytest.config.option.database_env self.log_path = pytest.config.option.log_path self.browser = pytest.config.option.browser self.data = pytest.config.option.data self.demo_mode = pytest.config.option.demo_mode self.demo_sleep = pytest.config.option.demo_sleep if self.with_db_reporting: self.execution_guid = str(uuid.uuid4()) self.testcase_guid = None self.execution_start_time = 0 self.case_start_time = 0 self.application = None self.testcase_manager = None self.error_handled = False self.testcase_manager = TestcaseManager(self.database_env) # exec_payload = ExecutionQueryPayload() exec_payload.execution_start_time = int(time.time() * 1000) self.execution_start_time = exec_payload.execution_start_time exec_payload.guid = self.execution_guid exec_payload.username = getpass.getuser() self.testcase_manager.insert_execution_data(exec_payload) # data_payload = TestcaseDataPayload() self.testcase_guid = str(uuid.uuid4()) data_payload.guid = self.testcase_guid data_payload.execution_guid = self.execution_guid if self.with_selenium: data_payload.browser = self.browser else: data_payload.browser = "N/A" data_payload.testcaseAddress = test_id application = ApplicationManager.generate_application_string( self._testMethodName) data_payload.env = application.split('.')[0] data_payload.start_time = application.split('.')[1] data_payload.state = constants.State.NOTRUN self.testcase_manager.insert_testcase_data(data_payload) self.case_start_time = int(time.time() * 1000) if self.headless: self.display = Display(visible=0, size=(1200, 800)) self.display.start() self.headless_active = True if self.with_selenium: self.driver = browser_launcher.get_driver(self.browser) def __insert_test_result(self, state, err): data_payload = TestcaseDataPayload() data_payload.runtime = int(time.time() * 1000) - self.case_start_time data_payload.guid = self.testcase_guid data_payload.execution_guid = self.execution_guid data_payload.state = state if err: tb_string = traceback.format_exc() if "Message: " in tb_string: data_payload.message = "Message: " + tb_string.split( "Message: ")[-1] elif "Exception: " in tb_string: data_payload.message = tb_string.split("Exception: ")[-1] elif "Error: " in tb_string: data_payload.message = tb_string.split("Error: ")[-1] else: data_payload.message = "Unknown Error: See Stacktrace" self.testcase_manager.update_testcase_data(data_payload) def tearDown(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass's tearDown(): super(SubClassOfBaseCase, self).tearDown() """ if self.page_check_failures: # self.process_checks() was not called after checks were made. # We will log those now here, but without raising an exception. exception_output = '' exception_output += "\n*** FAILED CHECKS FOR: %s\n" % self.id() for tb in self.page_check_failures: exception_output += "%s\n" % tb logging.exception(exception_output) if self.is_pytest: test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) if self.with_selenium: # Save a screenshot if logging is on when an exception occurs if self.with_testing_base and (sys.exc_info()[1] is not None): test_logpath = self.log_path + "/" + test_id if not os.path.exists(test_logpath): os.makedirs(test_logpath) if ((not self.with_screen_shots) and (not self.with_basic_test_info) and (not self.with_page_source)): # Log everything if nothing specified (if testing_base) log_helper.log_screenshot(test_logpath, self.driver) log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) log_helper.log_page_source(test_logpath, self.driver) else: if self.with_screen_shots: log_helper.log_screenshot( test_logpath, self.driver) if self.with_basic_test_info: log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) if self.with_page_source: log_helper.log_page_source( test_logpath, self.driver) # Finally close the browser self.driver.quit() if self.headless: if self.headless_active: self.display.stop() if self.with_db_reporting: if sys.exc_info()[1] is not None: self.__insert_test_result(constants.State.ERROR, True) else: self.__insert_test_result(constants.State.PASS, False) runtime = int(time.time() * 1000) - self.execution_start_time self.testcase_manager.update_execution_data( self.execution_guid, runtime) if self.with_s3_logging and (sys.exc_info()[1] is not None): """ After each testcase, upload logs to the S3 bucket. """ s3_bucket = S3LoggingBucket() guid = str(uuid.uuid4().hex) path = "%s/%s" % (self.log_path, test_id) uploaded_files = [] for logfile in os.listdir(path): logfile_name = "%s/%s/%s" % (guid, test_id, logfile.split(path)[-1]) s3_bucket.upload_file(logfile_name, "%s/%s" % (path, logfile)) uploaded_files.append(logfile_name) s3_bucket.save_uploaded_file_names(uploaded_files) index_file = s3_bucket.upload_index_file(test_id, guid) print("\n\n*** Log files uploaded: ***\n%s\n" % index_file) logging.error( "\n\n*** Log files uploaded: ***\n%s\n" % index_file) if self.with_db_reporting: self.testcase_manager = TestcaseManager(self.database_env) data_payload = TestcaseDataPayload() data_payload.guid = self.testcase_guid data_payload.logURL = index_file self.testcase_manager.update_testcase_log_url(data_payload)
class Browser: name = None capname = None supports_alert = True def __init__(self): self.driver = None self.profiledir = None self.initialized = False def initialSetup(self): pass def start(self): if self.driver: raise RuntimeError('%s is already running' % self.name) caps = {} caps.update(getattr(DesiredCapabilities, self.capname)) self.prepare_caps(caps) self.driver = WebDriver( 'http://%s:%d/wd/hub' % (self.args.server_host, self.args.server_port), desired_capabilities = caps ) self.driver.implicitly_wait(2) time.sleep(3) for h in self.driver.window_handles[1:]: self.driver.switch_to.window(h) self.driver.close() self.driver.switch_to.window(self.driver.window_handles[0]) self.driver.switch_to_default_content() if not self.initialized: self.initialSetup() self.initialized = True def quit(self): try: if self.driver: self.driver.quit() self.driver = None except http_client.BadStatusLine: pass def create_profile(self): self.profiledir = os.path.join(self.testdir, 'profile', self.name) if os.path.exists(self.profiledir): shutil.rmtree(self.profiledir) os.makedirs(self.profiledir) return self.profiledir def set_window_size(self, width, height): self.driver.set_window_size(width, height) @property def url(self): return self.driver.current_url def wait_page_load(self): time.sleep(1) self.wait_until(lambda d: self.js('return !!(window.document&&window.document.readyState==="complete")')) def open(self, url): self.driver.get(url) self.wait_page_load() def reload(self): self.open(self.url) def wait_until(self, callback): wait = WebDriverWait(self.driver, 20) return wait.until(callback) def ac(self): return ActionChains(self.driver) def q(self, selector, context = None): if context is None: return self.driver.find_element_by_css_selector(selector) return context.find_element_by_css_selector(selector) def qa(self, selector, context = None): if context is None: return self.driver.find_elements_by_css_selector(selector) return context.find_elements_by_css_selector(selector) def x(self, xpath): return self.driver.find_element_by_xpath(xpath) def xa(self, xpath): return self.driver.find_elements_by_xpath(xpath) def alert_accept(self): if self.supports_alert: Alert(self.driver).accept() else: raise RuntimeError('%s not supports alert handling' % self.name) def js(self, script, *args): return self.driver.execute_script(script, *args) def geom(self, element): return self.geom2(element)[:4] def geom2(self, element): return tuple(map(round, self.js(''' var elem = arguments[0]; var rect = elem.getBoundingClientRect(); return [rect.left, rect.top, rect.width, rect.height, rect.left + rect.width, rect.top + rect.height]; ''', element))) def screen_size(self): sw, sh = self.js(''' return [document.documentElement.clientWidth, document.documentElement.clientHeight]; ''') return sw, sh def set_cookie(self, name, value, domain, path): expires = '' if value is None: value = '' expires = '; expires=Thu, 01 Jan 1970 00:00:00 GMT' cookie = '%s=%s; domain=%s; path=%s%s' % (name, value, domain, path, expires) self.js('document.cookie=%s' % json.dumps(cookie)) def screenshot(self, elem = None): ss = self.driver.get_screenshot_as_png() io = util.BytesIO(ss) img = Image.open(io) if elem is not None: x, y, w, h = tuple(map(int, self.geom(elem))) img = img.crop((x, y, x + w, y + h)) return img.convert('RGB') def download(self, url, filename): dlpath = os.path.join(self.browserdir, filename) if not os.path.exists(dlpath) or os.stat(dlpath).st_mtime < time.time() - 60 * 60 * 24: util.download(url, dlpath) return dlpath def read_file_as_base64(self, filename): fp = open(filename, 'rb') try: data = fp.read() finally: fp.close() data = base64.b64encode(data) try: data = str(data, 'ascii') except TypeError: pass return data
class BaseCase(unittest.TestCase): ''' A base test case that wraps methods for enhanced usage. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None def open(self, url): self.driver.get(url) if settings.WAIT_FOR_RSC_ON_PAGE_LOADS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def open_url(self, url): """ In case people are mixing up self.open() with open(), use this alternative. """ self.open(url) def click(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): element = page_actions.wait_for_element_visible( self.driver, selector, by, timeout=timeout) self._demo_mode_scroll_if_active(selector, by) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def click_chain(self, selectors_list, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT, spacing=0): """ This method clicks on a list of elements in succession. 'spacing' is the amount of time to wait between clicks. (sec) """ for selector in selectors_list: self.click(selector, by=by, timeout=timeout) if spacing > 0: time.sleep(spacing) def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_link_text_visible(link_text, timeout=timeout) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def add_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): """ The more-reliable version of driver.send_keys() Similar to update_text(), but won't clear the text field first. """ element = self.wait_for_element_visible(selector, timeout=timeout) element.send_keys(new_value) self._demo_mode_pause_if_active() def send_keys(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): """ Same as add_text() -> more reliable, but less name confusion. """ self.add_text(selector, new_value, timeout=timeout) def update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT, retry=False): """ This method updates an element's text value with a new value. @Params selector - the selector with the value to update new_value - the new value for setting the text field timeout - how long to wait for the selector to be visible retry - if True, use jquery if the selenium text update fails """ element = self.wait_for_element_visible(selector, timeout=timeout) element.clear() self._demo_mode_pause_if_active(tiny=True) element.send_keys(new_value) if (retry and element.get_attribute('value') != new_value and ( not new_value.endswith('\n'))): logging.debug('update_text_value is falling back to jQuery!') selector = self.jq_format(selector) self.set_value(selector, new_value) self._demo_mode_pause_if_active() def update_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT, retry=False): """ The shorter version of update_text_value(), which clears existing text and adds new text into the text field. We want to keep the old version for backward compatibility. """ self.update_text_value(selector, new_value, timeout=timeout, retry=retry) def is_element_present(self, selector, by=By.CSS_SELECTOR): return page_actions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): return page_actions.is_element_visible(self.driver, selector, by) def is_link_text_visible(self, link_text): return page_actions.is_element_visible(self.driver, link_text, by=By.LINK_TEXT) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): return page_actions.is_text_visible(self.driver, text, selector, by) def find_visible_elements(self, selector, by=By.CSS_SELECTOR): return page_actions.find_visible_elements(self.driver, selector, by) def execute_script(self, script): return self.driver.execute_script(script) def set_window_size(self, width, height): return self.driver.set_window_size(width, height) self._demo_mode_pause_if_active() def maximize_window(self): return self.driver.maximize_window() self._demo_mode_pause_if_active() def activate_jquery(self): """ If "jQuery is not defined", use this method to activate it for use. This happens because jQuery is not always defined on web sites. """ try: # Let's first find out if jQuery is already defined. self.driver.execute_script("jQuery('html')") # Since that command worked, jQuery is defined. Let's return. return except Exception: # jQuery is not currently defined. Let's proceed by defining it. pass self.driver.execute_script( '''var script = document.createElement("script"); ''' '''script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1/''' '''jquery.min.js"; document.getElementsByTagName("head")[0]''' '''.appendChild(script);''') for x in xrange(30): # jQuery needs a small amount of time to activate. (At most 3s) try: self.driver.execute_script("jQuery('html')") return except Exception: time.sleep(0.1) # Since jQuery still isn't activating, give up and raise an exception raise Exception("Exception: WebDriver could not activate jQuery!") def scroll_to(self, selector): self.wait_for_element_visible(selector, timeout=settings.SMALL_TIMEOUT) scroll_script = "jQuery('%s')[0].scrollIntoView()" % selector try: self.driver.execute_script(scroll_script) except Exception: # The likely reason this fails is because: "jQuery is not defined" self.activate_jquery() # It's a good thing we can define it here self.driver.execute_script(scroll_script) self._demo_mode_pause_if_active(tiny=True) def scroll_click(self, selector): self.scroll_to(selector) self.click(selector) def jquery_click(self, selector): self.scroll_to(selector) self.driver.execute_script("jQuery('%s').click()" % selector) self._demo_mode_pause_if_active() def jq_format(self, code): return page_utils.jq_format(code) def set_value(self, selector, value): self.scroll_to(selector) val = json.dumps(value) self.driver.execute_script("jQuery('%s').val(%s)" % (selector, val)) self._demo_mode_pause_if_active() def jquery_update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_element_visible(selector, timeout=timeout) self.scroll_to(selector) self.driver.execute_script("""jQuery('%s').val('%s')""" % (selector, self.jq_format(new_value))) if new_value.endswith('\n'): element.send_keys('\n') self._demo_mode_pause_if_active() def jquery_update_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): self.jquery_update_text_value(selector, new_value, timeout=timeout) def hover_on_element(self, selector): self.wait_for_element_visible(selector, timeout=settings.SMALL_TIMEOUT) self.scroll_to(selector) time.sleep(0.05) # Settle down from scrolling before hovering return page_actions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): self.wait_for_element_visible(hover_selector, timeout=timeout) self.scroll_to(hover_selector) # Settle down from the scrolling before hovering element = page_actions.hover_and_click( self.driver, hover_selector, click_selector, click_by, timeout) self._demo_mode_pause_if_active() return element def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_present( self.driver, selector, by, timeout) def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_visible( self.driver, selector, by, timeout) def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_text_visible( self.driver, text, selector, by, timeout) def wait_for_link_text_visible(self, link_text, timeout=settings.LARGE_TIMEOUT): return self.wait_for_element_visible( link_text, by=By.LINK_TEXT, timeout=timeout) def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_absent( self.driver, selector, by, timeout) def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_not_visible( self.driver, selector, by, timeout) def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT): return page_actions.wait_for_ready_state_complete(self.driver, timeout) def wait_for_and_accept_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_accept_alert(self.driver, timeout) def wait_for_and_dismiss_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_dismiss_alert(self.driver, timeout) def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_switch_to_alert(self.driver, timeout) def save_screenshot(self, name, folder=None): return page_actions.save_screenshot(self.driver, name, folder) def _demo_mode_pause_if_active(self, tiny=False): if self.demo_mode: if self.demo_sleep: wait_time = float(self.demo_sleep) else: wait_time = settings.DEFAULT_DEMO_MODE_TIMEOUT if not tiny: time.sleep(wait_time) else: time.sleep(wait_time/3.0) def _demo_mode_scroll_if_active(self, selector, by): if self.demo_mode: if by == By.CSS_SELECTOR: self.scroll_to(selector) # PyTest-Specific Code # def setUp(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass setUp() method: super(SubClassOfBaseCase, self).setUp() """ self.is_pytest = None try: # This raises an exception if the test is not coming from pytest self.is_pytest = pytest.config.option.is_pytest except Exception: # Not using pytest (probably nosetests) self.is_pytest = False if self.is_pytest: self.with_selenium = pytest.config.option.with_selenium self.headless = pytest.config.option.headless self.headless_active = False self.with_testing_base = pytest.config.option.with_testing_base self.log_path = pytest.config.option.log_path self.browser = pytest.config.option.browser self.data = pytest.config.option.data self.demo_mode = pytest.config.option.demo_mode self.demo_sleep = pytest.config.option.demo_sleep if self.headless: self.display = Display(visible=0, size=(1200, 800)) self.display.start() self.headless_active = True if self.with_selenium: self.driver = browser_launcher.get_driver(self.browser) def tearDown(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass's tearDown(): super(SubClassOfBaseCase, self).tearDown() """ if self.is_pytest: if self.with_selenium: # Save a screenshot if logging is on when an exception occurs if self.with_testing_base and (sys.exc_info()[1] is not None): test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) test_logpath = self.log_path + "/" + test_id if not os.path.exists(test_logpath): os.makedirs(test_logpath) # Handle screenshot logging log_helper.log_screenshot(test_logpath, self.driver) # Handle basic test info logging log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) # Handle page source logging log_helper.log_page_source(test_logpath, self.driver) # Finally close the browser self.driver.quit() if self.headless: if self.headless_active: self.display.stop()
class WebAPP(common.APP): def __init__(self, app_config=None, app_name=None, apk_pkg_name=None, apk_activity_name=None): self.driver = None self.app_type = common.APP_TYPE_WEB self.app_name = app_name self.app_id = "" self.cur_path = os.getcwd() self.config_file = "data.conf" self.device_platform = "" self.test_type = "" self.read_config() self.test_url = app_config["test-url"] self.baseline_path = self.test_url + "/../../data/" + self.device_platform self.text_value = {} self.picture_list = [] self.color_dict = { "rgb(255, 0, 0)": "red", "rgb(0, 255, 0)": "green", "rgb(0, 0, 255)": "blue", "rgb(255, 255, 0)": "yellow", "rgb(0, 0, 0)": "black", "rgb(0, 128, 0)": "green", "rgb(255, 255, 255)": "white", "rgba(0, 0, 0, 0)": "white"} apk_activity_name = apk_activity_name apk_pkg_name = apk_pkg_name if "platform" in app_config and "name" in app_config["platform"]: if app_config["platform"]["name"].upper().find('ANDROID') >= 0: if apk_activity_name == apk_pkg_name is None: if "app_launcher" in app_config and app_config[ "app_launcher"] == "XWalkLauncher": self.app_name = self.app_name.replace("-", "_") apk_name_update = self.app_name.capitalize() apk_activity_name = ".%sActivity" % apk_name_update apk_pkg_name = "org.xwalk.%s" % self.app_name if "app_launcher" in app_config and app_config[ "app_launcher"] == "CordovaLauncher": self.app_name = self.app_name.replace("-", "_") apk_activity_name = ".%s" % self.app_name apk_pkg_name = "org.xwalk.%s" % self.app_name self.app_config_str = json.dumps(app_config).replace( "TEST_APP_NAME", self.app_name).replace( "TEST_APP_ID", self.app_id).replace( "TEST_PKG_NAME", apk_pkg_name).replace( "TEST_ACTIVITY_NAME", apk_activity_name) if app_config["platform"]["name"].upper().find('DEEPIN') >= 0: app_config.update({"desired-capabilities": {"loggingPrefs":{},"xwalkOptions": {"binary": "/usr/bin/TEST_BINARY", "debugPort": "12450"}}}) self.app_config_str = json.dumps(app_config).replace("TEST_BINARY", self.app_name) if app_config["platform"]["name"].upper().find('WINDOWS') >= 0: self.app_config_str = json.dumps(app_config).replace("TEST_BINARY", self.app_name) self.app_config = json.loads(self.app_config_str) if "url-prefix" in app_config: self.url_prefix = app_config["url-prefix"] else: self.url_prefix = "" def read_config(self): try: config = ConfigParser.ConfigParser() with open(self.config_file, "r") as cfgfile: config.readfp(cfgfile) self.device_platform = config.get('info', 'platform') self.test_type = config.get('info', 'test_type') except Exception as e: print "Parser config data.config failed: %s" % e def __get_element_by_xpath(self, xpath, display=True): try: element = self.driver.find_element_by_xpath(xpath) if display: try: if element.is_displayed(): return element except StaleElementReferenceException: pass else: return element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_key_attr(self, key, attr, display=True): xpath = "//*[@%s='%s']" % (attr, key) try: element = self.driver.find_element_by_xpath(xpath) if display: try: if element.is_displayed(): return element except StaleElementReferenceException: pass else: return element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_tag(self, key, display=True): try: element = self.driver.find_element_by_tag(key) return element except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_key(self, key, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( "//*[@id='%(key)s']|" "//*[@name='%(key)s']|" "//*[@value='%(key)s']|" "//*[contains(@class, '%(key)s')]|" "//div[contains(text(), '%(key)s')]|" "//button[contains(text(), '%(key)s')]|" "//input[contains(text(), '%(key)s')]|" "//textarea[contains(text(), '%(key)s')]|" "//a[contains(text(), '%(key)s')]") % {'key': key}): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_keys(self, key_p, key_c, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( "//*[@id='%(key)s']|" "//*[@name='%(key)s']|" "//*[@value='%(key)s']|" "//*[contains(@class, '%(key)s')]|" "//div[contains(text(), '%(key)s')]|" "//button[contains(text(), '%(key)s')]|" "//input[contains(text(), '%(key)s')]|" "//textarea[contains(text(), '%(key)s')]|" "//a[contains(text(), '%(key)s')]") % {'key': key_p}): get_element = False if display: try: if i_element.is_displayed(): get_element = True except StaleElementReferenceException: pass else: get_element = True if get_element: print "%s ++ %s" % (i_element.get_attribute("id"), i_element.get_attribute("class")) for ii_element in i_element.find_elements_by_xpath(str( "./*[@id='%(key)s']|" "./*[@name='%(key)s']|" "./*[@value='%(key)s']|" "./*[contains(@class, '%(key)s')]|" "./div[contains(text(), '%(key)s')]|" "./button[contains(text(), '%(key)s')]|" "./input[contains(text(), '%(key)s')]|" "./textarea[contains(text(), '%(key)s')]|" "./a[contains(text(), '%(key)s')]") % {'key': key_c}): if display: try: if ii_element.is_displayed(): return ii_element except StaleElementReferenceException: pass else: return ii_element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __check_normal_text(self, text, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element except Exception as e: print "Failed to get element: %s" % e return None def check_normal_text_element_not_exist(self, text, key, display=True): element = self.__get_element_by_key(key, display) if element: try: e_list = element.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))) for i_element in e_list: if i_element.text == text: return False return True except Exception as e: print "Failed to get element: %s" % e return False def __check_normal_text_element(self, text, key, display=True): element = self.__get_element_by_key(key, display) if element: try: for i_element in element.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element except Exception as e: print "Failed to get element: %s" % e return None def compare_two_values(self, first=None, second=None): try: if first.isdigit(): if eval(first) < eval(self.text_value[second]): return True else: return False else: if eval(self.text_value[first]) < eval(self.text_value[second]): return True else: return False except Exception as e: print "Failed to compare these two param: %s" % e return False def judge_saved_value(self, value=None, result=None): try: if self.text_value[value] == result: return True else: return False except Exception as e: print "Failed to judge saved vaule: %s" % e return False def compare_two_values_range(self, first=None, second=None, value=None): try: result = eval(self.text_value[second]) - eval(self.text_value[first]) if result >= eval(value) : return True else: return False except Exception as e: print "Failed to compare these two param with value: %s" % e return False def judge_value_range(self, value=None, first=None, second=None): try: result = eval(self.text_value[value]) if (eval(second) >= result) and (eval(first) <= result) : return True elif (eval(second) <= result) and (eval(first) >= result) : return True else: return False except Exception as e: print "Failed to judge value range: %s" % e return False def save_content(self, p_name=None, key=None): try: js_script = 'var style=document.getElementById(\"' + \ key + '\").innerHTML; return style' style = self.driver.execute_script(js_script) self.text_value[p_name] = style return True except Exception as e: print "Failed to get element: %s" % e return False def launch_app(self): try: desired_capabilities = self.app_config["desired-capabilities"] if self.app_config["platform"]["name"] == "android": self.driver = WebDriver( str(self.app_config["driver-url"]), desired_capabilities) elif self.app_config["platform"]["name"] in ("deepin", "windows"): self.driver = WebDriver( str(self.app_config["driver-url"]), desired_capabilities, keep_alive=True) except Exception as e: print "Failed to launch %s: %s" % (self.app_name, e) return False return True def switch_url(self, url, with_prefix=True): if with_prefix: url = urljoin(self.url_prefix, url) try: self.driver.get(url) except Exception as e: print "Failed to visit %s: %s" % (url, e) return False return True def title(self): try: return self.driver.title except Exception as e: print "Failed to get title: %s" % e return None def current_url(self): try: if isinstance(self.driver.current_url, dict): return self.driver.current_url['CurrentUrl'] else: return self.driver.current_url except Exception as e: print "Failed to get current url: %s" % e return None def reload(self): self.driver.refresh() return True def back(self): self.driver.back() return True def forward(self): self.driver.forward() return True def check_normal_text_timeout(self, text=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text(text, display): return True time.sleep(0.2) return False def check_normal_title_timeout(self, text=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.title() == text: return True time.sleep(0.2) return False def check_normal_text_element_timeout( self, text=None, key=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text_element(text, key, display): return True time.sleep(0.2) return False def check_normal_text_element_timeout_with_color( self, text=None, key=None, color=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text_element(text, key, display): if self.check_text_color(key, color): return True time.sleep(0.2) return False def check_normal_element_timeout_with_color( self, key=None, color=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.check_background_color(key, color): return True time.sleep(0.2) return False def check_background_color(self, key=None, color=None, display=True): try: js_script = 'var bg_color=document.getElementById(\"' + \ key + '\").style.backgroundColor; return bg_color' bg_color = self.driver.execute_script(js_script) if not bg_color: js_script = 'var element=document.getElementById(\"' + key + '\");' \ ' if(element.currentStyle) {return element.currentStyle.backgroundColor;} ' \ ' else { return document.defaultView.getComputedStyle(element,null).backgroundColor; } ' bg_color = self.driver.execute_script(js_script) if not bg_color: bg_color = "white" number = re.match(r'[A-Za-z]+$', bg_color) if not number: bg_color = self.color_dict[bg_color] if bg_color.strip() == color: return True except Exception as e: print "Failed to get element color: %s" % e return False def check_text_color(self, key=None, color=None, display=True): try: js_script = 'var text_color=document.getElementById(\"' + \ key + '\").style.color; return text_color' text_color = self.driver.execute_script(js_script) if not text_color: js_script = 'var element=document.getElementById(\"' + key + '\");' \ ' if(element.currentStyle) {return element.currentStyle.color;} ' \ ' else { return document.defaultView.getComputedStyle(element,null).color; } ' text_color = self.driver.execute_script(js_script) if not text_color: text_color = "black" is_rgb = re.match(r'[A-Za-z]+$', text_color) if not is_rgb: text_color = self.color_dict[text_color] if text_color.strip() == color: return True except Exception as e: print "Failed to get element: %s" % e return False def check_content_type(self, key=None, display=True): try: js_script = 'var text=document.getElementById(\"' + \ key + '\").innerText; return text' text = self.driver.execute_script(js_script) if text.strip() == '': return 'none' number = re.match(r'(-?\d+)(\.\d+)?', text) if number: if "." in text: return "float" else: return "int" else: if text.upper() == "TRUE" or text.upper() == "FALSE": return "boolean" else: return "string" except Exception as e: print "Failed to get element text: %s" % e def should_see_text_startswith(self, text=None, key=None): try: js_script = 'var text=document.getElementById(\"' + \ key + '\").innerHTML; return text' content = self.driver.execute_script(js_script) if content.strip().startswith(text): return True else: return False except Exception as e: print "Failed to find text startswith %s" % text return False def should_see_text_endswith(self, text=None, key=None): try: js_script = 'var text=document.getElementById(\"' + \ key + '\").innerHTML; return text' content = self.driver.execute_script(js_script) if content.strip().endswith(text): return True else: return False except Exception as e: print "Failed to find text endswith %s" % text return False def press_element_by_key(self, key, display=True): element = self.__get_element_by_key(key, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def press_element_by_keys(self, key_p, key_c, display=True): element = self.__get_element_by_keys(key_p, key_c, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def press_element_by_key_attr(self, key, attr, display=True): element = self.__get_element_by_key_attr(key, attr, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def click_element_by_keys(self, key_p, key_c, display=True): element = self.__get_element_by_keys(key_p, key_c, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: ActionChains(self.driver).click(element).perform() return True return False def click_element_by_key(self, key, display=True): element = self.__get_element_by_key(key, display) if element: print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if self.app_config["platform"]["name"].upper() == "WINDOWS": element.click() else: ActionChains(self.driver).click(element).perform() return True return False # * The method click_element_by_key will fail when VKB shelter the button, and js can avoid this issue. def click_element_by_id_with_js(self, key, display=True): element = self.__get_element_by_key_attr(key, "id", display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: js_script = 'document.getElementById(\"' + key + '\").click()' self.driver.execute_script(js_script) return True return False def click_element_coords(self, x, y, key, display=True): element = self.__get_element_by_key(key, display) if element: ActionChains(self.driver).move_to_element_with_offset( element, x, y).click().perform() return True return False def execute_js_code(self, js_code): try: return self.driver.execute_script(js_code) except Exception as e: print "Execute js code failed: %s" % e return 0 # Calculate the location params of element def calculate_element_location(self, key, width=0, height=0): try: if width: width = string.atoi(width) if height: height = string.atoi(height) js_script = 'var top=document.getElementById(\"' + \ key + '\").getBoundingClientRect().top; return top' top = self.execute_js_code(js_script) js_script = 'var left=document.getElementById(\"' + \ key + '\").getBoundingClientRect().left; return left' left = self.execute_js_code(js_script) if not width: js_script = 'var width=document.getElementById(\"' + \ key + '\").getBoundingClientRect().width; return width' width = self.execute_js_code(js_script) if not height: js_script = 'var height=document.getElementById(\"' + \ key + '\").getBoundingClientRect().height; return height' height = self.execute_js_code(js_script) return (left, top, left + width, top + height) except Exception as e: print "Get element location failed: %s" % e return 0 def calculate_resolution_ratio(self, pic_name): try: js_script = 'var width=window.screen.availWidth; return width' body_width = self.execute_js_code(js_script) js_script = 'var height=window.screen.availHeight; return height' body_height = self.execute_js_code(js_script) im = Image.open(pic_name) w, h = im.size ratio_w = w / body_width ratio_h = h / body_height ration = 0 if ratio_w > ratio_h: ratio = ratio_w else: ratio = ratio_h return w / ratio, h / ratio except Exception as e: print "Calculate page picture resolution failed: %s" % e return 0 # Save the specified element as a single picture def save_div_as_picture(self, key, element_pic, width=0, height=0): try: page_pic = "page.png" self.driver.get_screenshot_as_file(page_pic) self.picture_list.append(page_pic) ratio = self.calculate_resolution_ratio(page_pic) self.convert_pic(page_pic, ratio) box = self.calculate_element_location(key, width, height) self.crop_pic(page_pic, element_pic, box) self.picture_list.append(element_pic) return True except Exception as e: print "Save element picture failed: %s" % e return False # Remove these temporary pictures def remove_picture(self): try: picture_list = list(set(self.picture_list)) for element in picture_list: os.remove(element) self.picture_list = [] return True except Exception as e: print "Remove the tmp pictures fail: %s" % e return False # Check if 2 files content are the same def check_md5_file_same(self, file_name): try: if self.test_type == "result": result_path = self.baseline_path + "/" + file_name + ".md5" fp_result = open(result_path, "r") str_result = fp_result.read() fp_result.close() baseline_path = self.baseline_path + \ "/" + file_name + "_baseline.md5" fp_baseline = open(baseline_path, "r") str_baseline = fp_baseline.read() fp_baseline.close() index = cmp(str_result, str_baseline) if not index: return True else: return False elif self.test_type == "baseline": return True except Exception as e: print "Check md5 file failed: %s" % e return False # Save pic as base64 data's md5 def save_base64_md5_pic(self, pic_name): try: md5file_path = "" if self.test_type == "result": md5file_path = self.baseline_path + "/" + pic_name + ".md5" elif self.test_type == "baseline": md5file_path = self.baseline_path + \ "/" + pic_name + "_baseline.md5" pic_base64 = self.driver.get_screenshot_as_base64() pic_md5 = self.get_string_md5(pic_base64) fp = open(md5file_path, "w") fp.write(pic_md5) fp.close() return True except Exception as e: print "Save pic as base64 failed: %s" % e return False # Save page as pictures def save_page_per_conf(self, pic_name): try: if not os.path.exists(self.baseline_path): os.makedirs(self.baseline_path) if self.test_type == "result": picname_result = self.baseline_path + "/" + pic_name + ".png" self.driver.get_screenshot_as_file(picname_result) return True elif self.test_type == "baseline": picname_baseline = self.baseline_path + \ "/" + pic_name + "_baseline.png" self.driver.get_screenshot_as_file(picname_baseline) return True else: print "Test_type is wrong. It should be baseline or result. Please check the data.config file." return False except Exception as e: print "Save baseline pictures fail: %s" % e return False def check_base_result_similarity(self, pic_name, similarity): resu_pic = self.baseline_path + "/" + pic_name + ".png" base_pic = self.baseline_path + "/" + pic_name + "_baseline.png" if not os.path.exists(resu_pic): print "The result picture %s is not existed! Case fail" % pic_name return False if not os.path.exists(base_pic): print "The baseline picture %s is not existed! Case fail" % base_pic return False return self.check_pic_same(base_pic, resu_pic, similarity) def fill_element_by_key(self, key, text, display=True): element = self.__get_element_by_key(key, display) if element: element.send_keys(text) return True return False def fill_element_by_key_attr(self, key, attr, text, display=True): element = self.__get_element_by_key_attr(key, attr, display) if element: element.send_keys(text) return True return False def check_checkbox_by_key(self, key, display=True): element = self.__get_element_by_xpath(str( "//input[@id='%(key)s'][@type='checkbox']|" "//input[@name='%(key)s'][@type='checkbox']") % {'key': key}, display) if element: if not element.is_selected(): element.click() return True return False def uncheck_checkbox_by_key(self, key, display=True): element = self.__get_element_by_xpath(str( "//input[@id='%(key)s'][@type='checkbox']|" "//input[@name='%(key)s'][@type='checkbox']") % {'key': key}, display) if element: if element.is_selected(): element.click() return True return False def get_alert_text(self): try: alert_element = self.driver.switch_to_alert() if alert_element: return alert_element.text except Exception as e: print "Failed to get alert text: %s" % e return None def check_alert_existing(self): try: self.driver.switch_to_alert().text except NoAlertPresentException: return False return True def accept_alert(self): try: alert_element = self.driver.switch_to_alert() alert_element.accept() return True except Exception as e: print "Failed to accept alert: %s" % e return False def quit(self): if self.driver: self.driver.quit()
def get_user_agent(driver: WebDriver): return driver.execute_script("return navigator.userAgent")
class BaseCase(unittest.TestCase): ''' A base test case that wraps a bunch of methods from tools for easier access. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None def setUp(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass setUp() method: super(SubClassOfBaseCase, self).setUp() """ self.is_pytest = None try: # This raises an exception if the test is not coming from pytest self.is_pytest = pytest.config.option.is_pytest except Exception: # Not using pytest (probably nosetests) self.is_pytest = False if self.is_pytest: self.with_selenium = pytest.config.option.with_selenium self.with_testing_base = pytest.config.option.with_testing_base self.log_path = pytest.config.option.log_path self.browser = pytest.config.option.browser self.data = pytest.config.option.data if self.with_selenium: self.driver = browser_launcher.get_driver(self.browser) def tearDown(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass's tearDown(): super(SubClassOfBaseCase, self).tearDown() """ if self.is_pytest: if self.with_selenium: # Save a screenshot if logging is on when an exception occurs if self.with_testing_base and (sys.exc_info()[1] is not None): test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) test_logpath = self.log_path + "/" + test_id if not os.path.exists(test_logpath): os.makedirs(test_logpath) # Handle screenshot logging log_helper.log_screenshot(test_logpath, self.driver) # Handle basic test info logging log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) # Handle page source logging log_helper.log_page_source(test_logpath, self.driver) # Finally close the browser self.driver.quit() def open(self, url): self.driver.get(url) if settings.WAIT_FOR_RSC_ON_PAGE_LOADS: self.wait_for_ready_state_complete() def open_url(self, url): """ In case people are mixing up self.open() with open(), use this alternative. """ self.open(url) def click(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): element = page_actions.wait_for_element_visible( self.driver, selector, by, timeout=timeout) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_link_text_visible(link_text, timeout=timeout) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() def update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT, retry=False): """ This method updates a selector's text value with a new value @Params selector - the selector with the value to update new_value - the new value for setting the text field timeout - how long to wait for the selector to be visible retry - if True, use jquery if the selenium text update fails """ element = self.wait_for_element_visible(selector, timeout=timeout) element.clear() element.send_keys(new_value) if (retry and element.get_attribute('value') != new_value and not new_value.endswith('\n')): logging.debug('update_text_value is falling back to jQuery!') selector = self.jq_format(selector) self.set_value(selector, new_value) def is_element_present(self, selector, by=By.CSS_SELECTOR): return page_actions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): return page_actions.is_element_visible(self.driver, selector, by) def is_link_text_visible(self, link_text): return page_actions.is_element_visible(self.driver, link_text, by=By.LINK_TEXT) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): return page_actions.is_text_visible(self.driver, text, selector, by) def find_visible_elements(self, selector, by=By.CSS_SELECTOR): return page_actions.find_visible_elements(self.driver, selector, by) def execute_script(self, script): return self.driver.execute_script(script) def set_window_size(self, width, height): return self.driver.set_window_size(width, height) def maximize_window(self): return self.driver.maximize_window() def activate_jquery(self): """ (It's not on by default on all website pages.) """ self.driver.execute_script( '''var script = document.createElement("script"); ''' '''script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1/''' '''jquery.min.js"; document.getElementsByTagName("head")[0]''' '''.appendChild(script);''') def scroll_to(self, selector): self.wait_for_element_visible(selector, timeout=settings.SMALL_TIMEOUT) self.driver.execute_script( "jQuery('%s')[0].scrollIntoView()" % selector) def scroll_click(self, selector): self.scroll_to(selector) self.click(selector) def jquery_click(self, selector): self.driver.execute_script("jQuery('%s').click()" % selector) def jq_format(self, code): return page_utils.jq_format(code) def set_value(self, selector, value): val = json.dumps(value) self.driver.execute_script("jQuery('%s').val(%s)" % (selector, val)) def jquery_update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_element_visible(selector, timeout=timeout) self.driver.execute_script("""jQuery('%s').val('%s')""" % (selector, self.jq_format(new_value))) if new_value.endswith('\n'): element.send_keys('\n') def hover_on_element(self, selector): return page_actions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): return page_actions.hover_and_click(self.driver, hover_selector, click_selector, click_by, timeout) def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_present( self.driver, selector, by, timeout) def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_visible( self.driver, selector, by, timeout) def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_text_visible( self.driver, text, selector, by, timeout) def wait_for_link_text_visible(self, link_text, timeout=settings.LARGE_TIMEOUT): return self.wait_for_element_visible( link_text, by=By.LINK_TEXT, timeout=timeout) def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_absent( self.driver, selector, by, timeout) def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_element_not_visible( self.driver, selector, by, timeout) def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT): return page_actions.wait_for_ready_state_complete(self.driver, timeout) def wait_for_and_accept_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_accept_alert(self.driver, timeout) def wait_for_and_dismiss_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_dismiss_alert(self.driver, timeout) def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_switch_to_alert(self.driver, timeout)
class WebAPP(common.APP): def __init__(self, app_config=None, app_name=None, apk_pkg_name=None, apk_activity_name=None): self.driver = None self.app_type = common.APP_TYPE_WEB self.app_name = app_name self.app_id = "" self.text_value = {} self.color_dict = {"rgb(255, 0, 0)": "red","rgb(0, 255, 0)": "green","rgb(0, 0, 255)": "blue","rgb(255, 255, 0)": "yellow","rgb(0, 0, 0)": "black","rgb(0, 128, 0)": "green","rgb(255, 255, 255)": "white","rgba(0, 0, 0, 0)": "white"} apk_activity_name = apk_activity_name apk_pkg_name = apk_pkg_name if "platform" in app_config and "name" in app_config["platform"]: if app_config["platform"]["name"].upper().find('TIZEN') >= 0: self.app_id = tizen.get_appid_by_name( self.app_name, app_config["platform"], app_config["tizen_user"]) if app_config["platform"]["name"].upper().find('ANDROID') >= 0: if apk_activity_name == apk_pkg_name == None: if "app_launcher" in app_config and app_config["app_launcher"] == "XWalkLauncher": self.app_name = self.app_name.replace("-", "_") apk_name_update = "".join( [i.capitalize() for i in self.app_name.split("_") if i]) apk_activity_name = ".%sActivity" % apk_name_update apk_pkg_name = "org.xwalk.%s" % self.app_name if "app_launcher" in app_config and app_config["app_launcher"] == "CordovaLauncher": self.app_name = self.app_name.replace("-", "_") apk_activity_name = ".%s" % self.app_name apk_pkg_name = "org.xwalk.%s" % self.app_name app_config_str = json.dumps(app_config).replace( "TEST_APP_NAME", self.app_name).replace( "TEST_APP_ID", self.app_id).replace( "TEST_PKG_NAME", apk_pkg_name).replace( "TEST_ACTIVITY_NAME", apk_activity_name) self.app_config = json.loads(app_config_str) if "url-prefix" in app_config: self.url_prefix = app_config["url-prefix"] else: self.url_prefix = "" def __get_element_by_xpath(self, xpath, display=True): try: element = self.driver.find_element_by_xpath(xpath) if display: try: if element.is_displayed(): return element except StaleElementReferenceException: pass else: return element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_key_attr(self, key, attr, display=True): xpath = "//*[@%s='%s']" % (attr, key) try: element = self.driver.find_element_by_xpath(xpath) if display: try: if element.is_displayed(): return element except StaleElementReferenceException: pass else: return element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_tag(self, key, display=True): try: element = self.driver.find_element_by_tag(key) return element except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_key(self, key, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( "//*[@id='%(key)s']|" "//*[@name='%(key)s']|" "//*[@value='%(key)s']|" "//*[contains(@class, '%(key)s')]|" "//div[contains(text(), '%(key)s')]|" "//button[contains(text(), '%(key)s')]|" "//input[contains(text(), '%(key)s')]|" "//textarea[contains(text(), '%(key)s')]|" "//a[contains(text(), '%(key)s')]") % {'key': key}): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __get_element_by_keys(self, key_p, key_c, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( "//*[@id='%(key)s']|" "//*[@name='%(key)s']|" "//*[@value='%(key)s']|" "//*[contains(@class, '%(key)s')]|" "//div[contains(text(), '%(key)s')]|" "//button[contains(text(), '%(key)s')]|" "//input[contains(text(), '%(key)s')]|" "//textarea[contains(text(), '%(key)s')]|" "//a[contains(text(), '%(key)s')]") % {'key': key_p}): get_element = False if display: try: if i_element.is_displayed(): get_element = True except StaleElementReferenceException: pass else: get_element = True if get_element: print "%s ++ %s" % (i_element.get_attribute("id"), i_element.get_attribute("class")) for ii_element in i_element.find_elements_by_xpath(str( "./*[@id='%(key)s']|" "./*[@name='%(key)s']|" "./*[@value='%(key)s']|" "./*[contains(@class, '%(key)s')]|" "./div[contains(text(), '%(key)s')]|" "./button[contains(text(), '%(key)s')]|" "./input[contains(text(), '%(key)s')]|" "./textarea[contains(text(), '%(key)s')]|" "./a[contains(text(), '%(key)s')]") % {'key': key_c}): if display: try: if ii_element.is_displayed(): return ii_element except StaleElementReferenceException: pass else: return ii_element print "Failed to get element" except Exception as e: print "Failed to get element: %s" % e return None def __check_normal_text(self, text, display=True): try: for i_element in self.driver.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element except Exception as e: print "Failed to get element: %s" % e return None def check_normal_text_element_not_exist(self, text, key, display=True): element = self.__get_element_by_key(key, display) if element: try: e_list = element.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))) for i_element in e_list: if i_element.text == text: return False return True except Exception as e: print "Failed to get element: %s" % e return False def __check_normal_text_element(self, text, key, display=True): element = self.__get_element_by_key(key, display) if element: try: for i_element in element.find_elements_by_xpath(str( '//*[@value="{text}"]|' '//*[contains(normalize-space(.),"{text}") ' 'and not(./*[contains(normalize-space(.),"{text}")])]' .format(text=text))): if display: try: if i_element.is_displayed(): return i_element except StaleElementReferenceException: pass else: return i_element except Exception as e: print "Failed to get element: %s" % e return None def compare_two_values(self, first=None, second=None): try: if eval(self.text_value[first]) < eval(self.text_value[second]): return True else: return False except Exception as e: print "Failed to compare these two param: %s" % e return False def save_content(self, p_name=None, key=None): try: js_script = 'var style=document.getElementById(\"' + key + '\").innerHTML; return style' style = self.driver.execute_script(js_script) self.text_value[p_name] = style return True except Exception as e: print "Failed to get element: %s" % e return False def launch_app(self): try: desired_capabilities = self.app_config["desired-capabilities"] self.driver = WebDriver( str(self.app_config["driver-url"]), desired_capabilities) except Exception as e: print "Failed to launch %s: %s" % (self.app_name, e) return False return True def switch_url(self, url, with_prefix=True): if with_prefix: url = urljoin(self.url_prefix, url) try: self.driver.get(url) except Exception as e: print "Failed to visit %s: %s" % (url, e) return False return True def title(self): try: return self.driver.title except Exception as e: print "Failed to get title: %s" % e return None def current_url(self): try: return self.driver.current_url except Exception as e: print "Failed to get current url: %s" % e return None def reload(self): self.driver.refresh() return True def back(self): self.driver.back() return True def forward(self): self.driver.forward() return True def check_normal_text_timeout(self, text=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text(text, display): return True time.sleep(0.2) return False def check_normal_text_element_timeout( self, text=None, key=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text_element(text, key, display): return True time.sleep(0.2) return False def check_normal_text_element_timeout_with_color( self, text=None, key=None, color=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.__check_normal_text_element(text, key, display): if self.check_text_color(key, color): return True time.sleep(0.2) return False def check_normal_element_timeout_with_color( self, key=None, color=None, display=True, timeout=2): end_time = time.time() + timeout while time.time() < end_time: if self.check_background_color(key, color): return True time.sleep(0.2) return False def check_background_color(self, key=None, color=None, display=True): try: js_script = 'var bg_color=document.getElementById(\"' + key + '\").style.backgroundColor; return bg_color' bg_color = self.driver.execute_script(js_script) if not bg_color: js_script = 'var element=document.getElementById(\"' + key + '\");' \ ' if(element.currentStyle) {return element.currentStyle.backgroundColor;} ' \ ' else { return document.defaultView.getComputedStyle(element,null).backgroundColor; } ' bg_color = self.driver.execute_script(js_script) if not bg_color: bg_color = "white" number = re.match(r'[A-Za-z]+$',bg_color) if not number: bg_color = self.color_dict[bg_color] if bg_color.strip() == color: return True except Exception as e: print "Failed to get element color: %s" % e return False def check_text_color(self, key=None, color=None, display=True): try: js_script = 'var text_color=document.getElementById(\"' + key + '\").style.color; return text_color' text_color = self.driver.execute_script(js_script) if not text_color: js_script = 'var element=document.getElementById(\"' + key + '\");' \ ' if(element.currentStyle) {return element.currentStyle.color;} ' \ ' else { return document.defaultView.getComputedStyle(element,null).color; } ' text_color = self.driver.execute_script(js_script) if not text_color: text_color = "black" is_rgb = re.match(r'[A-Za-z]+$',text_color) if not is_rgb: text_color = self.color_dict[text_color] if text_color.strip() == color: return True except Exception as e: print "Failed to get element: %s" % e return False def check_content_type(self, key=None, display=True): try: js_script = 'var text=document.getElementById(\"' + key + '\").innerText; return text' text = self.driver.execute_script(js_script) if text.strip() == '': return 'none' number = re.match(r'(-?\d+)(\.\d+)?',text) if number: if "." in text: return "float" else: return "int" else: if text.upper() == "TRUE" or text.upper() == "FALSE": return "boolean" else: return "string" except Exception as e: print "Failed to get element text: %s" % e def press_element_by_key(self, key, display=True): element = self.__get_element_by_key(key, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def press_element_by_keys(self, key_p, key_c, display=True): element = self.__get_element_by_keys(key_p, key_c, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def press_element_by_key_attr(self, key, attr, display=True): element = self.__get_element_by_key_attr(key, attr, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: element.click() return True return False def click_element_by_keys(self, key_p, key_c, display=True): element = self.__get_element_by_keys(key_p, key_c, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: ActionChains(self.driver).click(element).perform() return True return False def click_element_by_key(self, key, display=True): element = self.__get_element_by_key(key, display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: ActionChains(self.driver).click(element).perform() return True return False # * The method click_element_by_key will fail when VKB shelter the button, and js can avoid this issue. def click_element_by_id_with_js(self, key, display=True): element = self.__get_element_by_key_attr(key, "id", display) print "%s == %s" % (element.get_attribute("id"), element.get_attribute("class")) if element: js_script = 'document.getElementById(\"' + key + '\").click()' self.driver.execute_script(js_script) return True return False def click_element_coords(self, x, y, key, display=True): element = self.__get_element_by_key(key, display) if element: ActionChains(self.driver).move_to_element_with_offset( element, x, y).click().perform() return True return False def fill_element_by_key(self, key, text, display=True): element = self.__get_element_by_key(key, display) if element: element.send_keys(text) return True return False def fill_element_by_key_attr(self, key, attr, text, display=True): element = self.__get_element_by_key_attr(key, attr, display) if element: element.send_keys(text) return True return False def check_checkbox_by_key(self, key, display=True): element = self.__get_element_by_xpath(str( "//input[@id='%(key)s'][@type='checkbox']|" "//input[@name='%(key)s'][@type='checkbox']") % {'key': key}, display) if element: if not element.is_selected(): element.click() return True return False def uncheck_checkbox_by_key(self, key, display=True): element = self.__get_element_by_xpath(str( "//input[@id='%(key)s'][@type='checkbox']|" "//input[@name='%(key)s'][@type='checkbox']") % {'key': key}, display) if element: if element.is_selected(): element.click() return True return False def get_alert_text(self): try: alert_element = self.driver.switch_to_alert() if alert_element: return alert_element.text except Exception as e: print "Failed to get alert text: %s" % e return None def check_alert_existing(self): try: self.driver.switch_to_alert().text except NoAlertPresentException: return False return True def accept_alert(self): try: alert_element = self.driver.switch_to_alert() alert_element.accept() return True except Exception as e: print "Failed to accept alert: %s" % e return False def quit(self): if self.driver: self.driver.quit()
def scroll(driver: WebDriver, seconds: int = 1): prev_height = driver.execute_script('return document.body.scrollHeight') driver.execute_script('window.scrollTo(0, document.body.scrollHeight)') time.sleep(seconds) curr_height = driver.execute_script('return document.body.scrollHeight') return prev_height, curr_height
def scroll_to(driver: WebDriver, y: str): driver.execute_script("window.scrollTo(0, {});".format(y))
class BaseCase(unittest.TestCase): ''' A base test case that wraps a bunch of methods from tools for easier access. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None def find_visible_elements(self, selector, by=By.CSS_SELECTOR): return page_interactions.find_visible_elements(self.driver, selector, by) def hover_on_element(self, selector): return page_interactions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, click_by=By.CSS_SELECTOR, timeout=5): return page_interactions.hover_and_click(self.driver, hover_selector, click_selector, click_by, timeout) def is_element_present(self, selector, by=By.CSS_SELECTOR): return page_interactions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): return page_interactions.is_element_visible(self.driver, selector, by) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): return page_interactions.is_text_visible(self.driver, text, selector, by) def jquery_click(self, selector): return self.driver.execute_script("jQuery('%s').click()" % selector) def click(self, selector): ele = self.driver.find_element(by=By.CSS_SELECTOR, value=selector) return ele.click() def scroll_to(self, selector): self.driver.execute_script("jQuery('%s')[0].scrollIntoView()" % selector) def scroll_click(self, selector): self.scroll_to(selector) time.sleep(0.1) self.click(selector) def jq_format(self, code): """ Use before throwing raw code such as 'div[tab="advanced"]' into jQuery. Similar to "json.dumps(value)". The first replace should take care of everything. Now see what else there is. """ code = code.replace('\\','\\\\').replace('\t',' ').replace('\n', '\\n').replace('\"','\\\"').replace('\'','\\\'').replace('\r', '\\r').replace('\v', '\\v').replace('\a', '\\a').replace('\f', '\\f').replace('\b', '\\b').replace('\u', '\\u') return code def set_value(self, selector, value): val = json.dumps(value) return self.driver.execute_script("jQuery('%s').val(%s)" % (selector, val)) def update_text_value(self, selector, new_value, timeout=5, retry=False): """ This method updates a selector's text value with a new value @Params selector - the selector with the value to change new_value - the new value for the text field where the selector points to timeout - how long to want for the selector to be visible before timing out retry - if text update fails, try the jQuery version (Warning: don't use this if update_text_value() takes you to a new page, or if it resets the value (such as using [backslash n] for the enter key) """ element = self.wait_for_element_visible(selector, timeout=timeout) element.clear() element.send_keys(new_value) if retry: if element.get_attribute('value') != new_value: logging.debug('update_text_value is falling back to jQuery!') # Since selectors with quotes inside of quotes such as 'div[data-tab-name="advanced"]' break jQuery, format them first selector = self.jq_format(selector) self.set_value(selector, new_value) time.sleep(0.5) def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_present(self.driver, selector, by, timeout) def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_visible(self.driver, selector, by, timeout) def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_text_visible(self.driver, text, selector, by, timeout) def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_absent(self.driver, selector, by, timeout) def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_not_visible(self.driver, selector, by, timeout) def wait_for_and_switch_to_alert(self, timeout=30): return page_loads.wait_for_and_switch_to_alert(self.driver, timeout)
class BaseCase(unittest.TestCase): ''' A base test case that wraps methods for enhanced usage. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None def open(self, url): self.driver.get(url) if settings.WAIT_FOR_RSC_ON_PAGE_LOADS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def open_url(self, url): """ In case people are mixing up self.open() with open(), use this alternative. """ self.open(url) def click(self, selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH element = page_actions.wait_for_element_visible( self.driver, selector, by, timeout=timeout) self._demo_mode_scroll_if_active(selector, by) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def click_chain(self, selectors_list, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT, spacing=0): """ This method clicks on a list of elements in succession. 'spacing' is the amount of time to wait between clicks. (sec) """ for selector in selectors_list: self.click(selector, by=by, timeout=timeout) if spacing > 0: time.sleep(spacing) def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_link_text_visible(link_text, timeout=timeout) element.click() if settings.WAIT_FOR_RSC_ON_CLICKS: self.wait_for_ready_state_complete() self._demo_mode_pause_if_active() def add_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): """ The more-reliable version of driver.send_keys() Similar to update_text(), but won't clear the text field first. """ element = self.wait_for_element_visible(selector, timeout=timeout) element.send_keys(new_value) self._demo_mode_pause_if_active() def send_keys(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): """ Same as add_text() -> more reliable, but less name confusion. """ self.add_text(selector, new_value, timeout=timeout) def update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT, retry=False): """ This method updates an element's text value with a new value. @Params selector - the selector with the value to update new_value - the new value for setting the text field timeout - how long to wait for the selector to be visible retry - if True, use jquery if the selenium text update fails """ element = self.wait_for_element_visible(selector, timeout=timeout) element.clear() self._demo_mode_pause_if_active(tiny=True) element.send_keys(new_value) if (retry and element.get_attribute('value') != new_value and ( not new_value.endswith('\n'))): logging.debug('update_text_value is falling back to jQuery!') selector = self.jq_format(selector) self.set_value(selector, new_value) self._demo_mode_pause_if_active() def update_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT, retry=False): """ The shorter version of update_text_value(), which clears existing text and adds new text into the text field. We want to keep the old version for backward compatibility. """ self.update_text_value(selector, new_value, timeout=timeout, retry=retry) def is_element_present(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_element_visible(self.driver, selector, by) def is_link_text_visible(self, link_text): return page_actions.is_element_visible(self.driver, link_text, by=By.LINK_TEXT) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.is_text_visible(self.driver, text, selector, by) def find_visible_elements(self, selector, by=By.CSS_SELECTOR): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.find_visible_elements(self.driver, selector, by) def execute_script(self, script): return self.driver.execute_script(script) def set_window_size(self, width, height): return self.driver.set_window_size(width, height) self._demo_mode_pause_if_active() def maximize_window(self): return self.driver.maximize_window() self._demo_mode_pause_if_active() def activate_jquery(self): """ If "jQuery is not defined", use this method to activate it for use. This happens because jQuery is not always defined on web sites. """ try: # Let's first find out if jQuery is already defined. self.driver.execute_script("jQuery('html')") # Since that command worked, jQuery is defined. Let's return. return except Exception: # jQuery is not currently defined. Let's proceed by defining it. pass self.driver.execute_script( '''var script = document.createElement("script"); ''' '''script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1/''' '''jquery.min.js"; document.getElementsByTagName("head")[0]''' '''.appendChild(script);''') for x in xrange(30): # jQuery needs a small amount of time to activate. (At most 3s) try: self.driver.execute_script("jQuery('html')") return except Exception: time.sleep(0.1) # Since jQuery still isn't activating, give up and raise an exception raise Exception("Exception: WebDriver could not activate jQuery!") def scroll_to(self, selector, wait=True): if wait: # Fail here if element isn't visible after SMALL_TIMEOUT seconds self.wait_for_element_visible( selector, timeout=settings.SMALL_TIMEOUT) else: # Might be a jQuery action to interact with an invisible element if not self.is_element_visible: time.sleep(0.05) # Last chance to load before scrolling there scroll_script = "jQuery('%s')[0].scrollIntoView()" % selector try: self.driver.execute_script(scroll_script) except Exception: # The likely reason this fails is because: "jQuery is not defined" self.activate_jquery() # It's a good thing we can define it here self.driver.execute_script(scroll_script) self._demo_mode_pause_if_active(tiny=True) def scroll_click(self, selector): self.scroll_to(selector) self.click(selector) def jquery_click(self, selector, wait=False): self.scroll_to(selector, wait=wait) self.driver.execute_script("jQuery('%s').click()" % selector) self._demo_mode_pause_if_active() def jq_format(self, code): return page_utils.jq_format(code) def set_value(self, selector, value, wait=False): self.scroll_to(selector, wait=wait) val = json.dumps(value) self.driver.execute_script("jQuery('%s').val(%s)" % (selector, val)) self._demo_mode_pause_if_active() def jquery_update_text_value(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): element = self.wait_for_element_visible(selector, timeout=timeout) self.scroll_to(selector) self.driver.execute_script("""jQuery('%s').val('%s')""" % (selector, self.jq_format(new_value))) if new_value.endswith('\n'): element.send_keys('\n') self._demo_mode_pause_if_active() def jquery_update_text(self, selector, new_value, timeout=settings.SMALL_TIMEOUT): self.jquery_update_text_value(selector, new_value, timeout=timeout) def hover_on_element(self, selector): self.wait_for_element_visible(selector, timeout=settings.SMALL_TIMEOUT) self.scroll_to(selector) time.sleep(0.05) # Settle down from scrolling before hovering return page_actions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, click_by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT): if click_selector.startswith('/'): click_by = By.XPATH self.wait_for_element_visible(hover_selector, timeout=timeout) self.scroll_to(hover_selector) # Settle down from the scrolling before hovering element = page_actions.hover_and_click( self.driver, hover_selector, click_selector, click_by, timeout) self._demo_mode_pause_if_active() return element def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_present( self.driver, selector, by, timeout) def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_visible( self.driver, selector, by, timeout) def wait_for_element(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_element_visible() """ return self.wait_for_element_visible(selector, by=by, timeout=timeout) def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_text_visible( self.driver, text, selector, by, timeout) def wait_for_text(self, text, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_text_visible() """ return self.wait_for_text_visible( text, selector, by=by, timeout=timeout) def wait_for_link_text_visible(self, link_text, timeout=settings.LARGE_TIMEOUT): return self.wait_for_element_visible( link_text, by=By.LINK_TEXT, timeout=timeout) def wait_for_link_text(self, link_text, timeout=settings.LARGE_TIMEOUT): """ The shorter version of wait_for_link_text_visible() """ return self.wait_for_link_text_visible(link_text, timeout=timeout) def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_absent( self.driver, selector, by, timeout) def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT): if selector.startswith('/') or selector.startswith('./'): by = By.XPATH return page_actions.wait_for_element_not_visible( self.driver, selector, by, timeout) def wait_for_ready_state_complete(self, timeout=settings.EXTREME_TIMEOUT): return page_actions.wait_for_ready_state_complete(self.driver, timeout) def wait_for_and_accept_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_accept_alert(self.driver, timeout) def wait_for_and_dismiss_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_dismiss_alert(self.driver, timeout) def wait_for_and_switch_to_alert(self, timeout=settings.LARGE_TIMEOUT): return page_actions.wait_for_and_switch_to_alert(self.driver, timeout) def save_screenshot(self, name, folder=None): return page_actions.save_screenshot(self.driver, name, folder) def _demo_mode_pause_if_active(self, tiny=False): if self.demo_mode: if self.demo_sleep: wait_time = float(self.demo_sleep) else: wait_time = settings.DEFAULT_DEMO_MODE_TIMEOUT if not tiny: time.sleep(wait_time) else: time.sleep(wait_time/3.0) def _demo_mode_scroll_if_active(self, selector, by): if self.demo_mode: if by == By.CSS_SELECTOR: self.scroll_to(selector) # PyTest-Specific Code # def setUp(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass setUp() method: super(SubClassOfBaseCase, self).setUp() """ self.is_pytest = None try: # This raises an exception if the test is not coming from pytest self.is_pytest = pytest.config.option.is_pytest except Exception: # Not using pytest (probably nosetests) self.is_pytest = False if self.is_pytest: test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) self.with_selenium = pytest.config.option.with_selenium self.headless = pytest.config.option.headless self.headless_active = False self.with_testing_base = pytest.config.option.with_testing_base self.with_db_reporting = pytest.config.option.with_db_reporting self.with_s3_logging = pytest.config.option.with_s3_logging self.with_screen_shots = pytest.config.option.with_screen_shots self.with_basic_test_info = ( pytest.config.option.with_basic_test_info) self.with_page_source = pytest.config.option.with_page_source self.database_env = pytest.config.option.database_env self.log_path = pytest.config.option.log_path self.browser = pytest.config.option.browser self.data = pytest.config.option.data self.demo_mode = pytest.config.option.demo_mode self.demo_sleep = pytest.config.option.demo_sleep if self.with_db_reporting: self.execution_guid = str(uuid.uuid4()) self.testcase_guid = None self.execution_start_time = 0 self.case_start_time = 0 self.application = None self.testcase_manager = None self.error_handled = False self.testcase_manager = TestcaseManager(self.database_env) # exec_payload = ExecutionQueryPayload() exec_payload.execution_start_time = int(time.time() * 1000) self.execution_start_time = exec_payload.execution_start_time exec_payload.guid = self.execution_guid exec_payload.username = getpass.getuser() self.testcase_manager.insert_execution_data(exec_payload) # data_payload = TestcaseDataPayload() self.testcase_guid = str(uuid.uuid4()) data_payload.guid = self.testcase_guid data_payload.execution_guid = self.execution_guid if self.with_selenium: data_payload.browser = self.browser else: data_payload.browser = "N/A" data_payload.testcaseAddress = test_id application = ApplicationManager.generate_application_string( self._testMethodName) data_payload.env = application.split('.')[0] data_payload.start_time = application.split('.')[1] data_payload.state = constants.State.NOTRUN self.testcase_manager.insert_testcase_data(data_payload) self.case_start_time = int(time.time() * 1000) if self.headless: self.display = Display(visible=0, size=(1200, 800)) self.display.start() self.headless_active = True if self.with_selenium: self.driver = browser_launcher.get_driver(self.browser) def __insert_test_result(self, state, err): data_payload = TestcaseDataPayload() data_payload.runtime = int(time.time() * 1000) - self.case_start_time data_payload.guid = self.testcase_guid data_payload.execution_guid = self.execution_guid data_payload.state = state if err: tb_string = traceback.format_exc() if "Message: " in tb_string: data_payload.message = "Message: " + tb_string.split( "Message: ")[-1] elif "Exception: " in tb_string: data_payload.message = tb_string.split("Exception: ")[-1] elif "Error: " in tb_string: data_payload.message = tb_string.split("Error: ")[-1] else: data_payload.message = "Unknown Error: See Stacktrace" self.testcase_manager.update_testcase_data(data_payload) def tearDown(self): """ pytest-specific code Be careful if a subclass of BaseCase overrides setUp() You'll need to add the following line to the subclass's tearDown(): super(SubClassOfBaseCase, self).tearDown() """ if self.is_pytest: test_id = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) if self.with_selenium: # Save a screenshot if logging is on when an exception occurs if self.with_testing_base and (sys.exc_info()[1] is not None): test_logpath = self.log_path + "/" + test_id if not os.path.exists(test_logpath): os.makedirs(test_logpath) if ((not self.with_screen_shots) and (not self.with_basic_test_info) and (not self.with_page_source)): # Log everything if nothing specified (if testing_base) log_helper.log_screenshot(test_logpath, self.driver) log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) log_helper.log_page_source(test_logpath, self.driver) else: if self.with_screen_shots: log_helper.log_screenshot( test_logpath, self.driver) if self.with_basic_test_info: log_helper.log_test_failure_data( test_logpath, self.driver, self.browser) if self.with_page_source: log_helper.log_page_source( test_logpath, self.driver) # Finally close the browser self.driver.quit() if self.headless: if self.headless_active: self.display.stop() if self.with_db_reporting: if sys.exc_info()[1] is not None: self.__insert_test_result(constants.State.ERROR, True) else: self.__insert_test_result(constants.State.PASS, False) runtime = int(time.time() * 1000) - self.execution_start_time self.testcase_manager.update_execution_data( self.execution_guid, runtime) if self.with_s3_logging and (sys.exc_info()[1] is not None): """ After each testcase, upload logs to the S3 bucket. """ s3_bucket = S3LoggingBucket() guid = str(uuid.uuid4().hex) path = "%s/%s" % (self.log_path, test_id) uploaded_files = [] for logfile in os.listdir(path): logfile_name = "%s/%s/%s" % (guid, test_id, logfile.split(path)[-1]) s3_bucket.upload_file(logfile_name, "%s/%s" % (path, logfile)) uploaded_files.append(logfile_name) s3_bucket.save_uploaded_file_names(uploaded_files) index_file = s3_bucket.upload_index_file(test_id, guid) print "\n\n*** Log files uploaded: ***\n%s\n" % index_file logging.error( "\n\n*** Log files uploaded: ***\n%s\n" % index_file) if self.with_db_reporting: self.testcase_manager = TestcaseManager(self.database_env) data_payload = TestcaseDataPayload() data_payload.guid = self.testcase_guid data_payload.logURL = index_file self.testcase_manager.update_testcase_log_url(data_payload)