Source code for kense.controls

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2018 Jorge Javier Araya Navarro
# This file is under the MIT License
# Complete text of the license is at LICENSE
"""Set of Selenium helpers.
"""

import re
from random import choice

from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

from kense import exceptions, wait

_ISBROWSER = re.compile(
    r'\<class \'selenium\.webdriver\.\w+\.webdriver\.WebDriver\'\>')
WAIT = 60
_MESSAGE_NOTFOUND = "Control %s cannot be found after %d seconds"
ANY = None


def _getwtext(element):
    """Return the text of HTML tag.

    Parameters
    ----------
    element : selenium.webdriver.remote.webelement.WebElement
              The HTML tag to extract the text from.

    Returns
    -------
    str
        The text inside of the HTML tag.
    """
    return element.get_attribute('text') or element.get_attribute(
        "innerText") or element.get_attribute("textContent")


def _findanyoption(browser, id_):
    """Choose an option at random.

    The option is other than the selected before this helper was run. Do not
    use this function directly but instead use `kense.controls.selectdropdown`
    with `kense.controls.ANY` for the value parameter.

    Parameters
    ----------
    browser : selenium.webdriver.remote.webdriver.WebDriver
              The Selenium web driver, the target URL must be loaded
    id_ : str
          The name of the ID of the HTML tag, avoid suffixing it with #.

    Returns
    -------
    str
        The text inside of the HTML tag.
    """
    values = browser.find_elements(By.XPATH, "//ul[@id='%s_listbox']/li" % id_)
    values = [_getwtext(x) for x in values]
    # Find the current selected option
    try:
        option = browser.find_element(By.XPATH,
                                      "//ul[@id='%s_listbox']/li[@id]" % id_)
    except NoSuchElementException:
        raise exceptions.OptionNotFound(
            "Control select#%s have no options to choose from, is empty." %
            id_)
    # Remove the current selected option
    values.remove(_getwtext(option))
    try:
        value = choice(values)
    except IndexError:
        raise exceptions.OptionNotFound(
            "Cannot choose other value than %s: not enough options." %
            _getwtext(option))

    return _findoption(browser, id_, value)


def _findoption(browser, id_, value):
    """Select an specific option.

    Parameters
    ----------
    browser : selenium.webdriver.remote.webdriver.WebDriver
              The Selenium web driver, the target URL must be loaded
    id_ : str
          The name of the ID of the <select> HTML tag, avoid
          suffixing it with #.
    value : str
            The option to select represented by the user-redeable text on it.

    Returns
    -------
    str
        The text inside of the HTML tag.
    """
    # Find the dropdown element in the current page
    parent = WebDriverWait(browser, WAIT).until(
        message=_MESSAGE_NOTFOUND % ("#" + id_, WAIT),
        method=lambda w: w.find_element(By.XPATH, "//*[@id='%s']/.." % id_))

    # Interact with the parent
    parent.click()

    # wait until the animation of the listbox finishes
    wait.waitanimation(browser, "%s_listbox" % id_)

    try:
        setoption = browser.find_element(
            By.XPATH,
            "//ul[@id='%s_listbox']/li[contains(text(), '%s')]" % (id_, value))
    except NoSuchElementException:
        raise exceptions.OptionNotFound(
            ("Option %s was not found for dropdown #%s."
             " Check your data and the casing of the value.") % (value, id_))

    # Select the option by clicking on it
    setoption.click()

    # wait until the animation of the listbox finishes
    wait.waitanimation(browser, "%s_listbox" % id_)

    # Search the new selected option and returns its text content
    option = browser.find_element(By.XPATH,
                                  "//ul[@id='%s_listbox']/li[@id]" % id_)

    return _getwtext(option)


[docs]def selectdropdown(browser, id_, value): """Select option from kendoDropDownList. Parameters ---------- browser : selenium.webdriver.remote.webdriver.WebDriver The Selenium web driver, the target URL must be loaded id_ : str The name of the ID of the <select> HTML tag, avoid suffixing it with #. value : str or kense.controls.ANY The option to select represented by the user-redeable text on it, use `kense.controls.ANY` to choose an option at random. Returns ------- str The text inside of the HTML tag. """ # Check if browser is a valid webdriver browsertype = str(type(browser)) if not _ISBROWSER.match(browsertype): raise ValueError( # pragma: no cover "browser parameter of type %s not valid, expected webdriver." % browsertype) # Check if selector is a valid string if not isinstance(id_, str): raise ValueError( # pragma: no cover "selector parameter of type %s not valid, expected str." % type(id_)) if value == ANY: return _findanyoption(browser, id_) return _findoption(browser, id_, value)