Source code for common.selenium

import os
import socket

from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.utils.decorators import classproperty

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.common.exceptions import WebDriverException



[docs]class Env():
[docs] def __init__(self, include=None, exclude=None): # Runnig on Travis CI or local? self.in_travis = os.environ.get('TRAVIS_JOB_NUMBER') is not None self._setup_provider() if self.provider['host'] == 'local': browsers = [ {'browserName': 'Safari'}, {'browserName': 'Chrome'}, ] elif self.provider['host'] == 'none': browsers = [] else: browsers = [ # {'browserName': "internet explorer", 'version': "8"}, # Renders wrong # {'browserName': "internet explorer", 'version': "9"}, # Renders wrong # {'browserName': "internet explorer", 'version': "10"}, # Renders wrong {'browserName': "internet explorer", 'version': "11"}, {'browserName': 'MicrosoftEdge'}, {'browserName': 'Chrome'}, # Drag works. # {'browserName': 'Chrome', 'version', 49} # Last version for Windows XP {'browserName': 'Chrome', 'version': 38}, # BrowserStack support {'browserName': 'Firefox'}, # {'browserName': "Safari", 'version': "7"}, # Renders wrong # {'browserName': "Safari", 'version': "8"}, # Fails to connect # {'browserName': "Safari", 'version': "9"}, # Fails to connect {'browserName': "Safari", 'version':"12"}, ] ; if include is not None: if isinstance(include, str): include = (include,) browsers = [x for x in browsers if x['browserName'] in include] if exclude is not None: if isinstance(exclude, str): exclude = (exclude,) browsers = [x for x in browsers if x['browserName'] not in exclude] self.browsers = browsers
def _setup_provider(self): get_envs = lambda *names: [os.environ.get(x) for x in names] host = 'local' url = '' extra_caps = {} # Configure for SauceLabs params = get_envs('SAUCE_USERNAME', 'SAUCE_ACCESS_KEY') if None not in params: (username, password) = params host = 'saucelabs' url = 'http://' + username + ':' + password + '@ondemand.saucelabs.com:80/wd/hub' if self.in_travis: extra_caps['tunnel-identifier'] = os.environ.get('TRAVIS_JOB_NUMBER') extra_caps['build'] = os.environ.get("TRAVIS_BUILD_NUMBER") extra_caps['tags'] =[os.environ.get("TRAVIS_PYTHON_VERSION"), "CI"] # Configure for BrowserStack params = get_envs('BROWSERSTACK_USER', 'BROWSERSTACK_ACCESS_KEY') if None not in params: (username, password) = params host = 'browserstack' url = 'http://' + username + ':' + password + "@hub-cloud.browserstack.com/wd/hub" extra_caps['browserstack.local'] = 'true' local_id = os.environ.get('BROWSERSTACK_LOCAL_IDENTIFIER') if local_id: extra_caps['browserstack.localIdentifier'] = os.environ.get('BROWSERSTACK_LOCAL_IDENTIFIER') if self.in_travis: extra_caps['name'] = "build " + os.environ.get("TRAVIS_BUILD_NUMBER") + ". " else: extra_caps['name'] = '' # extra_caps['browserstack.debug'] = 'true' if self.in_travis and host == 'local': host = 'none' # Export settings self.provider = {} self.provider['host'] = host self.provider['extra_caps'] = extra_caps self.provider['url'] = url
[docs] def cases(self): class Browser: def __init__(self, env, browser_i): self.env = env self.browser_i = browser_i @property def browser_caps(self): return self.env.browsers[self.browser_i] def build_driver(self, desc=""): if self.env.provider['host'] == 'local': if self.browser_caps['browserName'] == 'Safari': selenium = webdriver.Safari() elif self.browser_caps['browserName'] == 'Chrome': selenium = webdriver.Chrome() else: raise ValueError("Unsupported local webdriver {}".format(self.provider['host'])) else: caps = {**self.env.provider['extra_caps'], **self.browser_caps} if self.env.provider['host'] == 'browserstack': caps['name'] = caps['name'] + desc selenium = webdriver.Remote(command_executor=self.env.provider['url'], desired_capabilities=caps) return selenium return [Browser(self, ii) for ii in range(len(self.browsers))]
[docs] def parameterized_class(self): return [{'browser': x} for x in self.cases()]
[docs]class SeleniumTestCaseHelper(StaticLiveServerTestCase): host = socket.gethostbyname(socket.gethostname()) # It can be necessary to set this to the local IP address for some Safari configurations
[docs] def setUp(self): super().setUp() self.selenium = self.browser.build_driver(self.id()) self.selenium.implicitly_wait(5)
[docs] def tearDown(self): self.selenium.quit()
[docs] def run_as_sub_tests(self, sub_tests): for st in sub_tests: with self.subTest(st): st() # Close all but first window windows = self.selenium.window_handles for w in windows[:0:-1]: self.selenium.switch_to_window(w) self.selenium.close() self.selenium.switch_to_window(self.selenium.window_handles[0])
[docs] def shortDescription(self): desc = super().shortDescription() browser_name = "Browser case " + str(self.browser.browser_caps) return desc + " " + browser_name if desc else browser_name
[docs] def wait_for_safari_load(self): class SafariWaiter: def __init__(self, selenium): self.selenium = selenium def __enter__(self): self.old_url = self.selenium.current_url def __exit__(self, *args): if self.selenium.capabilities['browserName'] != 'Safari': # Only Safari has this problem return from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # wait for URL to change with 15 seconds timeout WebDriverWait(self.selenium, 5).until(EC.url_changes(self.old_url)) return SafariWaiter(self.selenium)
[docs] def assert_selenium_logs(self): try: errors = self.selenium.get_log('browser') except (ValueError, WebDriverException) as e: # Some browsers do not support getting logs if self.selenium.capabilities['browserName'] in ('Safari', 'internet explorer', 'MicrosoftEdge', 'firefox'): # They don't support logs # print("Could not get browser logs for driver {} due to exception: {}".format(self.selenium, e)) return else: raise(e) errors = [x for x in errors if x['level'] == 'SEVERE'] self.assertFalse(errors, 'Console errors detected.')