Skip to content

Webelement addon

webelement_addon

module with webelement class extensions

Webelement extensions include: - more convenient access as select object - various scrolling - retrieval of XPATH of an element

script_get_tag_idx = '\n function get_tag_idx(element) {\n var ix = 0;\n var siblings = element.parentElement.children;\n for (var i = 0; i < siblings.length; i++) {\n var sibling = siblings[i];\n if (sibling === element)\n return (ix+1);\n if (sibling.tagName === element.tagName)\n ix++;\n }\n }\n return get_tag_idx(arguments[0]);\n' module-attribute

as_select(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp.Select

as_select - provide direct access to select object to a SELECT-tag (alternative caller to asselect)

Source code in src/utils_seleniumxp/webelement_addon.py
def as_select(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp.Select:
    """
    as_select - provide direct access to select object to a SELECT-tag (alternative caller to asselect)
    """
    return asselect(webelement)

asselect(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp.Select

asselect - provide direct access to select object to a SELECT-tag

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required

Returns:

Type Description
Select

utils_seleniumxp.Select: Selenium select object

Source code in src/utils_seleniumxp/webelement_addon.py
def asselect(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp.Select:
    """
    asselect - provide direct access to select object to a SELECT-tag

    Args:
        webelement (utils_seleniumxp._WebElement): webelement

    Returns:
        utils_seleniumxp.Select: Selenium select object
    """

    if webelement.tag_name.upper() == "SELECT":
        return utils_seleniumxp.Select(webelement)
    else:
        err_msg = "WebElement is not a SELECT element."
        raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)

clear_and_send_keys(webelement: utils_seleniumxp._WebElement, value: str) -> None

clear_and_send_keys - clear element and send keys to it (combine simple calls)

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
value str

value for send_keys

required
Source code in src/utils_seleniumxp/webelement_addon.py
def clear_and_send_keys(webelement: utils_seleniumxp._WebElement, value: str) -> None:
    """
    clear_and_send_keys - clear element and send keys to it (combine simple calls)

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        value (str): value for send_keys
    """

    webelement.clear()
    webelement.send_keys(value)

get_css_selector(webelement: utils_seleniumxp._WebElement) -> str

get_css_selector - get CSS selector for webelement

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required

Returns:

Name Type Description
str str

CSS selector to webelement

Source code in src/utils_seleniumxp/webelement_addon.py
def get_css_selector(webelement: utils_seleniumxp._WebElement) -> str:
    """
    get_css_selector - get CSS selector for webelement

    Args:
        webelement (utils_seleniumxp._WebElement): webelement

    Returns:
        str: CSS selector to webelement
    """

    css_selector: list[str] = []
    element = webelement

    while element.tag_name.lower() != 'html':

        tag = element.tag_name.lower()
        parent = element.find_element(utils_seleniumxp.By.XPATH, "..")
        siblings = parent.find_elements(utils_seleniumxp.By.XPATH, f"./{tag}")

        if len(siblings) == 1:
            css_selector.insert(0, tag)
        else:
            index = None
            for i, sibling in enumerate(siblings, start=1):
                if sibling._id == element._id:
                    index = i
                    break
            css_selector.insert(0, f"{tag}:nth-of-type({index})")

        element = parent

    css_selector.insert(0, "html")
    return " > ".join(css_selector)

get_css_selector_from_xpath(webelement: utils_seleniumxp._WebElement, use_id: bool = False) -> str

get_css_selector_from_xpath - get CSS selector for webelement by transforming XPATH

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
use_id bool

flag if ID attribute should be used. Defaults to False.

False

Returns:

Name Type Description
str str

CSS selector to webelement

Source code in src/utils_seleniumxp/webelement_addon.py
def get_css_selector_from_xpath(webelement: utils_seleniumxp._WebElement, use_id: bool = False) -> str:
    """
    get_css_selector_from_xpath - get CSS selector for webelement by transforming XPATH

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        use_id (bool, optional): flag if ID attribute should be used. Defaults to False.

    Returns:
        str: CSS selector to webelement
    """

    xpath = webelement.get_xpath(use_id)
    return cssify.cssify(xpath)

get_overlapping_element(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp._WebElement

get_overlapping_element - get overlapping element

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required

Return

utils_seleniumxp._WebElement: overlapping webelement

Source code in src/utils_seleniumxp/webelement_addon.py
def get_overlapping_element(webelement: utils_seleniumxp._WebElement) -> utils_seleniumxp._WebElement:
    """
    get_overlapping_element - get overlapping element

    Args:
        webelement (utils_seleniumxp._WebElement): webelement

    Return:
        utils_seleniumxp._WebElement: overlapping webelement
    """

    rect = webelement.rect
    result = webelement.parent.execute_script("return document.elementFromPoint(arguments[0], arguments[1]);", rect['x'] + rect['width'] // 2, rect['y'] + rect['height'] // 2)
    if result == webelement:
        result = None
    return result

get_xpath(webelement: utils_seleniumxp._WebElement, use_id: bool = True) -> str

get_xpath - get XPATH for webelement

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
use_id bool

flag if ID attribute should be used. Defaults to True.

True

Returns:

Name Type Description
str str

XPATH to webelement

Source code in src/utils_seleniumxp/webelement_addon.py
def get_xpath(webelement: utils_seleniumxp._WebElement, use_id: bool = True) -> str:
    """
    get_xpath - get XPATH for webelement

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        use_id (bool, optional): flag if ID attribute should be used. Defaults to True.

    Returns:
        str: XPATH to webelement
    """

    parsedhtml = parsel.Selector(text=webelement.parent.page_source)
    xpath = ""

    while "/body" not in xpath:

        webelement_id = webelement.get_attribute("id")
        webelement_tag = webelement.tag_name.lower()

        if webelement_id is not None and webelement_id != "" and webelement_tag != "body":
            # use id
            xpath_section = f"/{webelement_tag}[@id='{webelement_id}']"
            if use_id and len(parsedhtml.xpath("/" + xpath_section).getall()) == 1:
                xpath = "/" + xpath_section + xpath
                break
            else:
                xpath = xpath_section + xpath
        elif webelement_tag == "body":
            # body element reached
            xpath = "/html/body" + xpath
            break
        else:
            # get element index (two versions possible - a) generalized n-th child or b) n-th child with specific tag-name
            # idx = webelement.parent.execute_script("return Array.from(arguments[0].parentNode.children).indexOf(arguments[0])", webelement)
            # xpath_section = f"/*[{idx + 1}]"
            idx = webelement.parent.execute_script(script_get_tag_idx, webelement)
            xpath_section = f"/{webelement_tag}[{idx}]"
            xpath = xpath_section + xpath
        webelement = webelement.find_element(utils_seleniumxp.By.XPATH, "./parent::*")

    return xpath

get_xpath_recursive(webelement: utils_seleniumxp._WebElement, parsedhtml=None, use_id: bool = True) -> str

get_xpath_recursive - get XPATH for webelement

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
parsedhtml _type_

parsel selector object. Defaults to None.

None
use_id bool

flag if ID attribute should be used. Defaults to True.

True

Returns:

Name Type Description
str str

XPATH to webelement

Source code in src/utils_seleniumxp/webelement_addon.py
def get_xpath_recursive(webelement: utils_seleniumxp._WebElement, parsedhtml=None, use_id: bool = True) -> str:
    """
    get_xpath_recursive - get XPATH for webelement

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        parsedhtml (_type_, optional): parsel selector object. Defaults to None.
        use_id (bool, optional): flag if ID attribute should be used. Defaults to True.

    Returns:
        str: XPATH to webelement
    """

    if webelement is None:
        return ""

    if parsedhtml is None:
        parsedhtml = parsel.Selector(text=webelement.parent.page_source)

    webelement_id = webelement.get_attribute("id")
    webelement_tag = webelement.tag_name.lower()

    if webelement_id is not None and webelement_id != "" and webelement_tag != "body":
        # use id
        xpath_section = f"/{webelement_tag}[@id='{webelement_id}']"
        if use_id and len(parsedhtml.xpath("/" + xpath_section).getall()) == 1:
            return "/" + xpath_section
    elif webelement_tag == "body":
        # body element reached
        return "/html/body"
    else:
        # get element index (two versions possible - a) generalized n-th child or b) n-th child with specific tag-name)
        # idx = webelement.parent.execute_script("return Array.from(arguments[0].parentNode.children).indexOf(arguments[0])", webelement)
        # xpath_section = f"/*[{idx + 1}]"
        idx = webelement.parent.execute_script(script_get_tag_idx, webelement)
        xpath_section = f"/{webelement_tag}[{idx}]"

    return get_xpath_recursive(
        webelement.find_element(utils_seleniumxp.By.XPATH, "./parent::*"), parsedhtml, use_id
    ) + xpath_section

hover_over(webelement: utils_seleniumxp._WebElement) -> None

hover_over - action chain to hover over element

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
Source code in src/utils_seleniumxp/webelement_addon.py
def hover_over(webelement: utils_seleniumxp._WebElement) -> None:
    """
    hover_over -  action chain to hover over element

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
    """

    utils_seleniumxp.WebDriver.ActionChains(webelement.parent).move_to_element(webelement).perform()

is_element_present(webelement: utils_seleniumxp._WebElement, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> bool

is_element_present - check if child webelement is present (alternative caller to is_present)

Source code in src/utils_seleniumxp/webelement_addon.py
def is_element_present(webelement: utils_seleniumxp._WebElement, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> bool:
    """
    is_element_present - check if child webelement is present (alternative caller to is_present)
    """
    return is_present(webelement, by, value, use_parsel)

is_overlapped(webelement: utils_seleniumxp._WebElement) -> bool

is_overlapped - check if element is overlapped

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required

Return

Source code in src/utils_seleniumxp/webelement_addon.py
def is_overlapped(webelement: utils_seleniumxp._WebElement) -> bool:
    """
    is_overlapped -  check if element is overlapped

    Args:
        webelement (utils_seleniumxp._WebElement): webelement

    Return:
        bool: element is overlapped
    """

    check_element = get_overlapping_element(webelement)
    return not (check_element is None or check_element == webelement)

is_present(webelement: utils_seleniumxp._WebElement, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> bool

is_present - check if child webelement is present

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
by By

locator type

required
value str

locator value

required
use_parsel bool

flag to use parsel. Defaults to True

True

Returns:

Name Type Description
bool bool

flag if element is present or not

Source code in src/utils_seleniumxp/webelement_addon.py
def is_present(
    webelement: utils_seleniumxp._WebElement, by: utils_seleniumxp.By, value: str, use_parsel: bool = True
) -> bool:
    """
    is_present - check if child webelement is present

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        by (utils_seleniumxp.By): locator type
        value (str): locator value
        use_parsel (bool, optional): flag to use parsel. Defaults to True

    Returns:
        bool: flag if element is present or not
    """

    if use_parsel and by in {utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR}:
        xpath = webelement.get_xpath()
        value = xpath + "/" + value if by == utils_seleniumxp.By.XPATH else cssify.cssify(xpath) + " > " + value
        parsedhtml = utils_seleniumxp.parselSelectorExtension(text=webelement.parent.page_source)
        return len(parsedhtml.css_or_xpath(utils_seleniumxp.SeleniumLocator(by, value)).getall()) > 0
    else:
        try:
            webelement.find_element(by, value)
        except Exception:
            return False
        else:
            return True

scroll_into_view(webelement: utils_seleniumxp._WebElement, offset_pixels: int = 0, align_to_top: bool = False) -> None

scroll_into_view - scroll webelement into view

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
offset_pixels int

vertical pixel offset. Defaults to 0.

0
align_to_top bool

flag for alignment to top of page. Defaults to False.

False
Source code in src/utils_seleniumxp/webelement_addon.py
def scroll_into_view(
    webelement: utils_seleniumxp._WebElement, offset_pixels: int = 0, align_to_top: bool = False
) -> None:
    """
    scroll_into_view - scroll webelement into view

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        offset_pixels (int, optional): vertical pixel offset. Defaults to 0.
        align_to_top (bool, optional): flag for alignment to top of page. Defaults to False.
    """

    webelement.parent.execute_script("arguments[0].scrollIntoView(arguments[1]);", webelement, align_to_top)
    # compensate for the header
    # unfortunately subsequent scripts seem to interfere with previous script if no wait
    if offset_pixels != 0:
        time.sleep(0.5)
        webelement.parent.execute_script(f"window.scrollBy(0, {offset_pixels});")
    else:
        time.sleep(0.5)

scroll_into_view_and_click(webelement: utils_seleniumxp._WebElement, offset_pixels: int = 0, align_to_top: bool = False) -> None

scroll_into_view_and_click - scroll webelement into view and click

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
offset_pixels int

vertical pixel offset. Defaults to 0.

0
align_to_top bool

flag for alignment to top of page. Defaults to False.

False
Source code in src/utils_seleniumxp/webelement_addon.py
def scroll_into_view_and_click(
    webelement: utils_seleniumxp._WebElement, offset_pixels: int = 0, align_to_top: bool = False
) -> None:
    """
    scroll_into_view_and_click - scroll webelement into view and click

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
        offset_pixels (int, optional): vertical pixel offset. Defaults to 0.
        align_to_top (bool, optional): flag for alignment to top of page. Defaults to False.
    """

    webelement.scroll_into_view(offset_pixels, align_to_top)
    webelement.click()

scroll_into_viewportmid(webelement: utils_seleniumxp._WebElement) -> None

scroll_into_viewportmid - scroll webelement into mid of viewport

Parameters:

Name Type Description Default
webelement _WebElement

webelement

required
Source code in src/utils_seleniumxp/webelement_addon.py
def scroll_into_viewportmid(webelement: utils_seleniumxp._WebElement) -> None:
    """
    scroll_into_viewportmid - scroll webelement into mid of viewport

    Args:
        webelement (utils_seleniumxp._WebElement): webelement
    """

    script = (
            "var viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);"
            "var elementTop = arguments[0].getBoundingClientRect().top;"
            "window.scrollBy(0, elementTop-(viewPortHeight/2));"
        )
    webelement.parent.execute_script(script, webelement)
    time.sleep(0.5)