from urllib.parse import urljoin
from selenium.webdriver.remote.command import Command
from selenium.webdriver.support import ui
from . import common, exceptions, webdrivers
__all__ = ['LiveClient']
[docs]class LiveClient(common.FindMixin):
web_driver_class = webdrivers.Firefox
[docs] def __init__(self, live_server_url, web_driver_class=None):
self.live_server_url = live_server_url
if web_driver_class:
self.web_driver_class = web_driver_class
self.web_driver = self.web_driver_class()
self._css_prefix = ''
@property
def css_prefix(self):
return self._css_prefix
@css_prefix.setter
def css_prefix(self, value):
assert not value or not self._css_prefix, self._css_prefix
self._css_prefix = value
[docs] def find_css(self, css_selector, prefix=True, force_list=False, fail=True):
"""Shortcut to find elements by CSS. Returns either a list or singleton."""
if prefix and self.css_prefix:
css_selector = f'{self.css_prefix} {css_selector}'
return self.web_driver.find_css(css_selector, force_list=force_list, fail=fail)
[docs] def find_xpath(self, xpath, force_list=False, fail=True):
return self.web_driver.find_xpath(xpath, force_list=force_list, fail=fail)
[docs] def get(self, url, data=None):
assert data is None
url = urljoin(self.live_server_url, url) if '://' not in url else url
response = type('Response', (object, ), self.web_driver.execute(Command.GET, {'url': url}))
response.status_code = 200 if self.web_driver.current_url == url else 404
return response
[docs] def quit(self):
return self.web_driver.quit()
[docs] def set_element(self, name, value, clear=None):
"""Set the properties of an element. Works with both WebElement and Select."""
element = self.find_name(name)
if clear is None:
clear = element.is_displayed()
if isinstance(element, self.web_driver.web_element_classes['select']):
return element.select_by_value(value)
if clear:
element.clear()
return element.send_keys(value)
[docs] def submit(self):
return self.find_css('form button.btn-primary[type="submit"]').click()
[docs] def wait_for_css(self, css_selector='', inverse=False, prefix=True, timeout=5, fail=True):
try:
return ui.WebDriverWait(self.web_driver, timeout).until(
lambda driver: bool(self.find_css(css_selector, prefix, fail=False)) ^ inverse
)
except exceptions.TimeoutException: # pylint:disable=no-member
if fail:
raise
return None
[docs] def wait_for_id(self, element_id, inverse=False, prefix=True, timeout=5, fail=True):
return self.wait_for_css(f'#{element_id}', inverse, prefix, timeout, fail)
[docs] def wait_for_name(self, element_name, inverse=False, prefix=True, timeout=5, fail=True):
return self.wait_for_css(f'[name="{element_name}"]', inverse, prefix, timeout, fail)