Warning
This document is for an old release 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.components
import re
import string
from abc import (
ABCMeta,
abstractproperty,
)
from selenium.webdriver.common.by import By
from galaxy.util.bunch import Bunch
[docs]class Target(metaclass=ABCMeta):
@abstractproperty
def description(self):
"""Return a plain-text description of the browser target for logging/messages."""
@abstractproperty
def element_locator(self):
"""Return a (by, selector) Selenium elment locator tuple for this selector."""
[docs]class SelectorTemplate(Target):
[docs] def __init__(self, selector: str, selector_type: str, children=None, kwds=None, with_classes=None, with_data=None):
if selector_type == "data-description":
selector_type = "css"
selector = f'[data-description="{selector}"]'
self._selector = selector
self.selector_type = selector_type
self._children = children or {}
self.__kwds = kwds or {}
self.with_classes = with_classes or []
self._with_data = with_data or {}
[docs] @staticmethod
def from_dict(raw_value, children=None):
children = children or {}
if isinstance(raw_value, dict):
return SelectorTemplate(raw_value["selector"], raw_value.get("type", "css"), children=children)
else:
return SelectorTemplate(raw_value, "css", children=children)
[docs] def with_class(self, class_):
assert self.selector_type == "css"
return SelectorTemplate(self._selector, self.selector_type, kwds=self.__kwds, with_classes=self.with_classes + [class_], with_data=self._with_data.copy(), children=self._children)
[docs] def with_data(self, key, value):
assert self.selector_type == "css"
with_data = self._with_data.copy()
with_data[key] = value
return SelectorTemplate(self._selector, self.selector_type, kwds=self.__kwds, with_classes=self.with_classes, with_data=with_data, children=self._children)
[docs] def descendant(self, has_selector):
assert self.selector_type == "css"
if hasattr(has_selector, "selector"):
selector = has_selector.selector
else:
selector = has_selector
return SelectorTemplate(f"{self.selector} {selector}", self.selector_type, kwds=self.__kwds, children=self._children)
def __call__(self, **kwds):
new_kwds = self.__kwds.copy()
new_kwds.update(**kwds)
return SelectorTemplate(self._selector, self.selector_type, kwds=new_kwds, with_classes=self.with_classes, children=self._children)
@property
def description(self):
if self.selector_type == "css":
template = "CSS selector [%s]"
elif self.selector_type == "xpath":
template = "XPATH selector [%s]"
elif self.selector_type == "id":
template = "DOM element with id [%s]"
return template % self.selector
@property
def selector(self):
selector = self._selector
if self.__kwds is not None:
selector = string.Template(selector).substitute(self.__kwds)
selector = selector + "".join(f".{c}" for c in self.with_classes)
if self._with_data:
for key, value in self._with_data.items():
selector = selector + f'[data-{key}="{value}"]'
return selector
@property
def element_locator(self):
if self.selector_type == "css":
by = By.CSS_SELECTOR
elif self.selector_type == "xpath":
by = By.XPATH
elif self.selector_type == "id":
by = By.ID
else:
raise Exception(f"Unknown selector type {self.selector_type}")
return (by, self.selector)
@property
def as_css_class(self):
assert self.selector_type == "css"
assert re.compile(r"\.\w+").match(self._selector)
return self._selector[1:]
def __getattr__(self, name):
if name in self._children:
return self._children[name](**{"_": self.selector})
else:
raise AttributeError(f"Could not find child [{name}] in {self._children}")
__getitem__ = __getattr__
[docs]class Label(Target):
@property
def description(self):
return f"Link text [{self.text}]"
@property
def element_locator(self):
return (By.LINK_TEXT, self.text)
[docs]class Text(Target):
@property
def description(self):
return f"Text containing [{self.text}]"
@property
def element_locator(self):
return (By.PARTIAL_LINK_TEXT, self.text)
[docs]class Component:
[docs] def __init__(self, name, sub_components, selectors, labels, text):
self._name = name
self._sub_components = sub_components
self._selectors = selectors
self._labels = labels
self._text = text
self.selectors = Bunch(**self._selectors)
self.labels = Bunch(**self._labels)
self.text = Bunch(**self._text)
@property
def selector(self):
if "_" in self._selectors:
return self._selectors["_"]
else:
raise Exception(f"No _ selector for [{self}]")
[docs] @staticmethod
def from_dict(name, raw_value):
selectors = {}
labels = {}
text = {}
sub_components = {}
for key, value in raw_value.items():
if key == "selectors":
base_selector = None
if "_" in value:
base_selector = value["_"]
del value["_"]
for selector_key, selector_value in value.items():
selectors[selector_key] = SelectorTemplate.from_dict(selector_value)
if base_selector:
selectors["_"] = SelectorTemplate.from_dict(base_selector, children=selectors)
elif key == "labels":
for label_key, label_value in value.items():
labels[label_key] = Label(label_value)
elif key == "text":
for text_key, text_value in value.items():
text[text_key] = Text(text_value)
else:
component = Component.from_dict(key, value)
sub_components[key] = component
return Component(name, sub_components, selectors, labels, text)
def __getattr__(self, attr):
if attr in self._sub_components:
return self._sub_components[attr]
elif attr in self._selectors:
return self._selectors[attr]
elif attr in self._labels:
return self._labels[attr]
elif attr in self._text:
return self._text[attr]
else:
raise AttributeError(f"Failed to find referenced sub-component/selector/label/text [{attr}]")
__getitem__ = __getattr__
def __str__(self):
return f"Component[{self._name}]"