Warning

This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.selenium.sizzle

"""Utilities for using sizzle (jQuery-style) selectors with Selenium."""

import json

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

from .has_driver import exception_indicates_stale_element

SIZZLE_LOAD_TIMEOUT = 5
SIZZLE_URL = "//cdnjs.cloudflare.com/ajax/libs/sizzle/1.10.18/sizzle.js"


[docs]def sizzle_selector_clickable(selector): def ec(driver): elements = find_elements_by_sizzle(driver, selector) if not elements: return False element = elements[0] try: clickable = element.is_displayed() and element.is_enabled() except Exception as e: # Handle the case where the element is detached between when it is # discovered and when it is checked - it is likely changing quickly # and the next pass will be the final state. If not, this should be # wrapped in a wait anyway - so no problems there. For other # non-custom selectors I believe this all happens on the Selenium # server and so there is likely no need to handle this case - they # are effectively atomic. if exception_indicates_stale_element(e): return None raise if clickable: return element else: return None return ec
[docs]def sizzle_presence_of_selector(selector): def ec(driver): elements = find_elements_by_sizzle(driver, selector) if not elements: return False element = elements[0] try: displayed = element.is_displayed() except Exception as e: # See note above insizzle_selector_clickable about this exception. if exception_indicates_stale_element(e): return None raise if displayed: return element else: return None return ec
[docs]def find_element_by_sizzle(driver, sizzle_selector: str): """ Finds an element by sizzle selector. :param sizzle_selector: The sizzle selector to use when finding element. """ if elements := driver.find_elements_by_sizzle(sizzle_selector): return elements[0] else: raise NoSuchElementException(f"Unable to locate element by Sizzle: {sizzle_selector}")
[docs]def find_elements_by_sizzle(driver, sizzle_selector: str): """ Finds elements by sizzle selector. :param sizzle_selector: The sizzle selector to use when finding elements. """ if not _is_sizzle_loaded(driver): _inject_sizzle(driver, SIZZLE_URL, SIZZLE_LOAD_TIMEOUT) elements = driver.execute_script(_make_sizzle_string(sizzle_selector)) return elements
def _inject_sizzle(driver, sizzle_url, timeout): script = f""" if(typeof(window.$) != "undefined") {{ // Just reuse jQuery if it is available, avoids potential amd problems // that have cropped up with Galaxy for instance. window.Sizzle = window.$; }} else {{ var _s = document.createElement("script"); _s.type = "text/javascript"; _s.src = "{sizzle_url}"; var _h = document.getElementsByTagName("head")[0]; _h.appendChild(_s); }} """ driver.execute_script(script) wait = WebDriverWait(driver, timeout) wait.until(lambda d: _is_sizzle_loaded(d), f"Can't inject Sizzle in {timeout} seconds") def _is_sizzle_loaded(driver): script = 'return typeof(Sizzle) != "undefined";' return driver.execute_script(script) def _make_sizzle_string(sizzle_selector): # Use json.dumps to escape quotes selector = json.dumps(sizzle_selector) return f"return Sizzle({selector});" __all__ = ( "find_element_by_sizzle", "find_elements_by_sizzle", "sizzle_selector_clickable", "sizzle_presence_of_selector", )