Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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))
Beispiel #8
0
 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
Beispiel #11
0
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
Beispiel #14
0
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)
Beispiel #15
0
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
Beispiel #16
0
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)
Beispiel #19
0
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
Beispiel #20
0
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)
Beispiel #21
0
    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
Beispiel #22
0
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
     )
Beispiel #25
0
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)
Beispiel #28
0
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()
Beispiel #29
0
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()
Beispiel #31
0
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)
Beispiel #32
0
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")
Beispiel #35
0
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)
Beispiel #36
0
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 ''
Beispiel #37
0
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"])
Beispiel #38
0
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)
Beispiel #39
0
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
Beispiel #40
0
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()
Beispiel #41
0
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()
Beispiel #42
0
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)
Beispiel #44
0
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()
Beispiel #45
0
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
Beispiel #46
0
def scroll_to(driver: WebDriver, y: str):
    driver.execute_script("window.scrollTo(0, {});".format(y))
Beispiel #47
0
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)
Beispiel #48
0
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)