|
@@ -45,18 +45,22 @@ class Browser(object):
|
|
|
|
|
|
def get(self, path, *args, **kwargs):
|
|
|
self.driver.get(self.route(path), *args, **kwargs)
|
|
|
+ self._has_initialized_cookie_store = True
|
|
|
return self
|
|
|
|
|
|
def post(self, path, *args, **kwargs):
|
|
|
self.driver.post(self.route(path), *args, **kwargs)
|
|
|
+ self._has_initialized_cookie_store = True
|
|
|
return self
|
|
|
|
|
|
def put(self, path, *args, **kwargs):
|
|
|
self.driver.put(self.route(path), *args, **kwargs)
|
|
|
+ self._has_initialized_cookie_store = True
|
|
|
return self
|
|
|
|
|
|
def delete(self, path, *args, **kwargs):
|
|
|
self.driver.delete(self.route(path), *args, **kwargs)
|
|
|
+ self._has_initialized_cookie_store = True
|
|
|
return self
|
|
|
|
|
|
def element(self, selector):
|
|
@@ -72,32 +76,59 @@ class Browser(object):
|
|
|
def click(self, selector):
|
|
|
self.element(selector).click()
|
|
|
|
|
|
- def wait_until(self, selector, timeout=3):
|
|
|
+ def wait_until(self, selector=None, title=None, timeout=3):
|
|
|
"""
|
|
|
Waits until ``selector`` is found in the browser, or until ``timeout``
|
|
|
is hit, whichever happens first.
|
|
|
"""
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
|
|
+ if selector:
|
|
|
+ condition = expected_conditions.presence_of_element_located((By.CSS_SELECTOR, selector))
|
|
|
+ elif title:
|
|
|
+ condition = expected_conditions.title_is(title)
|
|
|
+ else:
|
|
|
+ raise ValueError
|
|
|
+
|
|
|
WebDriverWait(
|
|
|
self.driver, timeout
|
|
|
- ).until(expected_conditions.presence_of_element_located((By.CSS_SELECTOR, selector)))
|
|
|
+ ).until(condition)
|
|
|
|
|
|
return self
|
|
|
|
|
|
- def wait_until_not(self, selector, timeout=3):
|
|
|
+ def wait_until_not(self, selector=None, title=None, timeout=3):
|
|
|
"""
|
|
|
Waits until ``selector`` is NOT found in the browser, or until
|
|
|
``timeout`` is hit, whichever happens first.
|
|
|
"""
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
|
|
+ if selector:
|
|
|
+ condition = expected_conditions.presence_of_element_located((By.CSS_SELECTOR, selector))
|
|
|
+ elif title:
|
|
|
+ condition = expected_conditions.title_is(title)
|
|
|
+ else:
|
|
|
+ raise
|
|
|
+
|
|
|
WebDriverWait(
|
|
|
self.driver, timeout
|
|
|
- ).until_not(expected_conditions.presence_of_element_located((By.CSS_SELECTOR, selector)))
|
|
|
+ ).until_not(condition)
|
|
|
|
|
|
return self
|
|
|
|
|
|
+ @property
|
|
|
+ def switch_to(self):
|
|
|
+ return self.driver.switch_to
|
|
|
+
|
|
|
+ def implicitly_wait(self, duration):
|
|
|
+ """
|
|
|
+ An implicit wait tells WebDriver to poll the DOM for a certain amount of
|
|
|
+ time when trying to find any element (or elements) not immediately
|
|
|
+ available. The default setting is 0. Once set, the implicit wait is set
|
|
|
+ for the life of the WebDriver object.
|
|
|
+ """
|
|
|
+ self.driver.implicitly_wait(duration)
|
|
|
+
|
|
|
def snapshot(self, name):
|
|
|
"""
|
|
|
Capture a screenshot of the current state of the page. Screenshots
|
|
@@ -110,40 +141,51 @@ class Browser(object):
|
|
|
return self
|
|
|
|
|
|
def save_cookie(self, name, value, path='/', expires='Tue, 20 Jun 2025 19:07:44 GMT'):
|
|
|
- # XXX(dcramer): "hit a url before trying to set cookies"
|
|
|
+ cookie = {
|
|
|
+ 'name': name,
|
|
|
+ 'value': value,
|
|
|
+ 'expires': expires,
|
|
|
+ 'path': path,
|
|
|
+ 'domain': self.domain,
|
|
|
+ }
|
|
|
+
|
|
|
+ # XXX(dcramer): the cookie store must be initialized via a URL
|
|
|
if not self._has_initialized_cookie_store:
|
|
|
logger.info('selenium.initialize-cookies')
|
|
|
self.get('/')
|
|
|
- self._has_initialized_cookie_store = True
|
|
|
|
|
|
# XXX(dcramer): PhantomJS does not let us add cookies with the native
|
|
|
# selenium API because....
|
|
|
# http://stackoverflow.com/questions/37103621/adding-cookies-working-with-firefox-webdriver-but-not-in-phantomjs
|
|
|
+
|
|
|
# TODO(dcramer): this should be escaped, but idgaf
|
|
|
- logger.info('selenium.set-cookies.{}'.format(name), extra={
|
|
|
+ logger.info('selenium.set-cookie.{}'.format(name), extra={
|
|
|
'value': value,
|
|
|
})
|
|
|
-
|
|
|
- self.driver.execute_script(
|
|
|
- "document.cookie = '{name}={value}; path={path}; domain={domain}; expires={expires}';\n".
|
|
|
- format(
|
|
|
- name=name,
|
|
|
- value=value,
|
|
|
- expires=expires,
|
|
|
- path=path,
|
|
|
- domain=self.domain,
|
|
|
+ if isinstance(self.driver, webdriver.PhantomJS):
|
|
|
+ self.driver.execute_script(
|
|
|
+ "document.cookie = '{name}={value}; path={path}; domain={domain}; expires={expires}';\n".format(
|
|
|
+ **cookie)
|
|
|
)
|
|
|
- )
|
|
|
+ else:
|
|
|
+ self.driver.add_cookie(cookie)
|
|
|
|
|
|
|
|
|
def pytest_addoption(parser):
|
|
|
- parser.addini('selenium_driver', help='selenium driver (phantomjs or firefox)')
|
|
|
+ parser.addini('selenium_driver', help='selenium driver (chrome, phantomjs, or firefox)')
|
|
|
|
|
|
group = parser.getgroup('selenium', 'selenium')
|
|
|
group._addoption(
|
|
|
- '--selenium-driver', dest='selenium_driver', help='selenium driver (phantomjs or firefox)'
|
|
|
+ '--selenium-driver', dest='selenium_driver', help='selenium driver (chrome, phantomjs, or firefox)'
|
|
|
)
|
|
|
+ group._addoption(
|
|
|
+ '--window-size',
|
|
|
+ dest='window_size',
|
|
|
+ help='window size (WIDTHxHEIGHT)',
|
|
|
+ default='1280x800')
|
|
|
group._addoption('--phantomjs-path', dest='phantomjs_path', help='path to phantomjs driver')
|
|
|
+ group._addoption('--chrome-path', dest='chrome_path', help='path to google-chrome')
|
|
|
+ group._addoption('--chromedriver-path', dest='chromedriver_path', help='path to chromedriver')
|
|
|
|
|
|
|
|
|
def pytest_configure(config):
|
|
@@ -174,8 +216,29 @@ def percy(request):
|
|
|
|
|
|
@pytest.fixture(scope='function')
|
|
|
def browser(request, percy, live_server):
|
|
|
+ window_size = request.config.getoption('window_size')
|
|
|
+ window_width, window_height = list(map(int, window_size.split('x', 1)))
|
|
|
+
|
|
|
driver_type = request.config.getoption('selenium_driver')
|
|
|
- if driver_type == 'firefox':
|
|
|
+ if driver_type == 'chrome':
|
|
|
+ options = webdriver.ChromeOptions()
|
|
|
+ options.add_argument('headless')
|
|
|
+ options.add_argument('disable-gpu')
|
|
|
+ options.add_argument('window-size={}'.format(window_size))
|
|
|
+ chrome_path = request.config.getoption('chrome_path')
|
|
|
+ if chrome_path:
|
|
|
+ options.binary_location = chrome_path
|
|
|
+ chromedriver_path = request.config.getoption('chromedriver_path')
|
|
|
+ if chromedriver_path:
|
|
|
+ driver = webdriver.Chrome(
|
|
|
+ executable_path=chromedriver_path,
|
|
|
+ chrome_options=options,
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ driver = webdriver.Chrome(
|
|
|
+ chrome_options=options,
|
|
|
+ )
|
|
|
+ elif driver_type == 'firefox':
|
|
|
driver = webdriver.Firefox()
|
|
|
elif driver_type == 'phantomjs':
|
|
|
phantomjs_path = request.config.getoption('phantomjs_path')
|
|
@@ -187,10 +250,11 @@ def browser(request, percy, live_server):
|
|
|
'phantomjs',
|
|
|
)
|
|
|
driver = webdriver.PhantomJS(executable_path=phantomjs_path)
|
|
|
- driver.set_window_size(1280, 800)
|
|
|
else:
|
|
|
raise pytest.UsageError('--driver must be specified')
|
|
|
|
|
|
+ driver.set_window_size(window_width, window_height)
|
|
|
+
|
|
|
def fin():
|
|
|
# Teardown Selenium.
|
|
|
try:
|