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",
)