diff --git a/.travis.yml b/.travis.yml index 72669d3d..74ac30de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ sudo: false branches: only: - master + - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ before_install: - wget https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-linux64.tar.gz - mkdir geckodriver diff --git a/CHANGELOG b/CHANGELOG index b9b1de7b..aff6d4ef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v0.9.3 (02/14/19) +* PageLoadError and WrongPageError now inherit WebDriverException so + they can trigger retries instead of immediately failing tests + v0.9.2 (11/20/18) (0.9.1 skipped due to PyPI deployment issue) * Support passing additional desired capabilities to remote WebDriver instances. diff --git a/bok_choy/a11y/a11y_audit.py b/bok_choy/a11y/a11y_audit.py index f48cf6fa..64656efc 100644 --- a/bok_choy/a11y/a11y_audit.py +++ b/bok_choy/a11y/a11y_audit.py @@ -133,7 +133,7 @@ def _get_rules_js(self): Raises: `RuntimeError` if the file isn't found. """ if not os.path.isfile(self.config.rules_file): - msg = 'Could not find the accessibility tools JS file: {}'.format( + msg = u'Could not find the accessibility tools JS file: {}'.format( self.config.rules_file) raise RuntimeError(msg) diff --git a/bok_choy/a11y/axe_core_ruleset.py b/bok_choy/a11y/axe_core_ruleset.py index d94eff71..c7c92ac0 100644 --- a/bok_choy/a11y/axe_core_ruleset.py +++ b/bok_choy/a11y/axe_core_ruleset.py @@ -24,7 +24,7 @@ class AxeCoreAuditConfig(A11yAuditConfig): def __init__(self, *args, **kwargs): super(AxeCoreAuditConfig, self).__init__(*args, **kwargs) self.rules, self.context = None, None - self.custom_rules = "customRules={}" + self.custom_rules = u"customRules={}" self.rules_file = os.path.join( os.path.split(CUR_DIR)[0], 'vendor/axe-core/axe.min.js' @@ -243,7 +243,7 @@ def _check_rules(browser, rules_js, config): __Caution__: You probably don't really want to call this method directly! It will be used by `AxeCoreAudit.do_audit`. """ - audit_run_script = dedent(""" + audit_run_script = dedent(u""" {rules_js} {custom_rules} axe.configure(customRules); @@ -259,7 +259,7 @@ def _check_rules(browser, rules_js, config): options=config.rules ) - audit_results_script = dedent(""" + audit_results_script = dedent(u""" window.console.log(window.a11yAuditResults); return window.a11yAuditResults; """) @@ -350,14 +350,14 @@ def _get_message(node): lines = [] for error_type in errors: - lines.append("Severity: {}".format(error_type.get("impact"))) - lines.append("Rule ID: {}".format(error_type.get("id"))) - lines.append("Help URL: {}\n".format(error_type.get('helpUrl'))) + lines.append(u"Severity: {}".format(error_type.get("impact"))) + lines.append(u"Rule ID: {}".format(error_type.get("id"))) + lines.append(u"Help URL: {}\n".format(error_type.get('helpUrl'))) for node in error_type['nodes']: - msg = "Message: {}".format(_get_message(node)) - html = "Html: {}".format(node.get('html').encode('utf-8')) - target = "Target: {}".format(node.get('target')) + msg = u"Message: {}".format(_get_message(node)) + html = u"Html: {}".format(node.get('html').encode('utf-8')) + target = u"Target: {}".format(node.get('target')) fill_opts = { 'width': 100, 'initial_indent': '\t', @@ -382,7 +382,7 @@ def report_errors(audit, url): """ errors = AxeCoreAudit.get_errors(audit) if errors["total"] > 0: - msg = "URL '{}' has {} errors:\n\n{}".format( + msg = u"URL '{}' has {} errors:\n\n{}".format( url, errors["total"], AxeCoreAudit.format_errors(errors["errors"]) diff --git a/bok_choy/a11y/axs_ruleset.py b/bok_choy/a11y/axs_ruleset.py index ef86e401..4806f600 100644 --- a/bok_choy/a11y/axs_ruleset.py +++ b/bok_choy/a11y/axs_ruleset.py @@ -90,8 +90,8 @@ def set_scope(self, include=None, exclude=None): page.a11y_audit.config.set_scope() """ if include: - self.scope = "document.querySelector(\"{}\")".format( - ', '.join(include) + self.scope = u"document.querySelector(\"{}\")".format( + u', '.join(include) ) else: self.scope = "null" @@ -160,7 +160,7 @@ def _check_rules(browser, rules_js, config): # run all rules. rules = config.rules_to_run if rules: - rules_config = "auditConfig.auditRulesToRun = {rules};".format( + rules_config = u"auditConfig.auditRulesToRun = {rules};".format( rules=rules) else: rules_config = "" @@ -168,12 +168,12 @@ def _check_rules(browser, rules_js, config): ignored_rules = config.rules_to_ignore if ignored_rules: rules_config += ( - "\nauditConfig.auditRulesToIgnore = {rules};".format( + u"\nauditConfig.auditRulesToIgnore = {rules};".format( rules=ignored_rules ) ) - script = dedent(""" + script = dedent(u""" {rules_js} var auditConfig = new axs.AuditConfiguration(); {rules_config} @@ -219,9 +219,9 @@ def report_errors(audit, url): """ errors = AxsAudit.get_errors(audit) if errors: - msg = "URL '{}' has {} errors:\n{}".format( + msg = u"URL '{}' has {} errors:\n{}".format( url, len(errors), - (', ').join(errors) + ', '.join(errors) ) raise AccessibilityError(msg) diff --git a/bok_choy/browser.py b/bok_choy/browser.py index e239f77c..7d6e1aca 100644 --- a/bok_choy/browser.py +++ b/bok_choy/browser.py @@ -100,7 +100,7 @@ def save_source(driver, name): with open(file_name, 'wb') as output_file: output_file.write(source.encode('utf-8')) except Exception: # pylint: disable=broad-except - msg = "Could not save the browser page source to {}.".format(file_name) + msg = u"Could not save the browser page source to {}.".format(file_name) LOGGER.warning(msg) @@ -131,8 +131,8 @@ def save_screenshot(driver, name): else: msg = ( - "Browser does not support screenshots. " - "Could not save screenshot '{name}'" + u"Browser does not support screenshots. " + u"Could not save screenshot '{name}'" ).format(name=name) LOGGER.warning(msg) @@ -182,8 +182,8 @@ def save_driver_logs(driver, prefix): output_file.write("{}{}".format(dumps(line), '\n')) except: # pylint: disable=bare-except msg = ( - "Could not save browser log of type '{log_type}'. " - "It may be that the browser does not support it." + u"Could not save browser log of type '{log_type}'. " + u"It may be that the browser does not support it." ).format(log_type=log_type) LOGGER.warning(msg, exc_info=True) @@ -311,22 +311,22 @@ def _firefox_profile(): profile_dir = os.environ.get(FIREFOX_PROFILE_ENV_VAR) if profile_dir: - LOGGER.info("Using firefox profile: %s", profile_dir) + LOGGER.info(u"Using firefox profile: %s", profile_dir) try: firefox_profile = webdriver.FirefoxProfile(profile_dir) except OSError as err: if err.errno == errno.ENOENT: raise BrowserConfigError( - "Firefox profile directory {env_var}={profile_dir} does not exist".format( + u"Firefox profile directory {env_var}={profile_dir} does not exist".format( env_var=FIREFOX_PROFILE_ENV_VAR, profile_dir=profile_dir)) elif err.errno == errno.EACCES: raise BrowserConfigError( - "Firefox profile directory {env_var}={profile_dir} has incorrect permissions. It must be \ + u"Firefox profile directory {env_var}={profile_dir} has incorrect permissions. It must be \ readable and executable.".format(env_var=FIREFOX_PROFILE_ENV_VAR, profile_dir=profile_dir)) else: # Some other OSError: raise BrowserConfigError( - "Problem with firefox profile directory {env_var}={profile_dir}: {msg}" + u"Problem with firefox profile directory {env_var}={profile_dir}: {msg}" .format(env_var=FIREFOX_PROFILE_ENV_VAR, profile_dir=profile_dir, msg=str(err))) else: LOGGER.info("Using default firefox profile") @@ -373,14 +373,14 @@ def _local_browser_class(browser_name): """ # Log name of local browser - LOGGER.info("Using local browser: %s [Default is firefox]", browser_name) + LOGGER.info(u"Using local browser: %s [Default is firefox]", browser_name) # Get class of local browser based on name browser_class = BROWSERS.get(browser_name) headless = os.environ.get('BOKCHOY_HEADLESS', 'false').lower() == 'true' if browser_class is None: raise BrowserConfigError( - "Invalid browser name {name}. Options are: {options}".format( + u"Invalid browser name {name}. Options are: {options}".format( name=browser_name, options=", ".join(list(BROWSERS.keys())))) else: if browser_name == 'firefox': @@ -392,7 +392,7 @@ def _local_browser_class(browser_name): firefox_options = FirefoxOptions() firefox_options.log.level = 'trace' if headless: - firefox_options.set_headless(True) + firefox_options.headless = True browser_args = [] browser_kwargs = { 'firefox_profile': _firefox_profile(), @@ -418,7 +418,7 @@ def _local_browser_class(browser_name): elif browser_name == 'chrome': chrome_options = ChromeOptions() if headless: - chrome_options.set_headless(True) + chrome_options.headless = True # Emulate webcam and microphone for testing purposes chrome_options.add_argument('--use-fake-device-for-media-stream') @@ -429,7 +429,7 @@ def _local_browser_class(browser_name): browser_args = [] browser_kwargs = { - 'chrome_options': chrome_options, + 'options': chrome_options, } else: browser_args, browser_kwargs = [], {} @@ -453,14 +453,14 @@ def _remote_browser_class(env_vars, tags=None): caps = _capabilities_dict(envs, tags) if 'accessKey' in caps: - LOGGER.info("Using SauceLabs: %s %s %s", caps['platform'], caps['browserName'], caps['version']) + LOGGER.info(u"Using SauceLabs: %s %s %s", caps['platform'], caps['browserName'], caps['version']) else: - LOGGER.info("Using Remote Browser: %s", caps['browserName']) + LOGGER.info(u"Using Remote Browser: %s", caps['browserName']) # Create and return a new Browser # We assume that the WebDriver end-point is running locally (e.g. using # SauceConnect) - url = "http://{0}:{1}/wd/hub".format( + url = u"http://{0}:{1}/wd/hub".format( envs['SELENIUM_HOST'], envs['SELENIUM_PORT']) browser_args = [] @@ -532,13 +532,13 @@ def _required_envs(env_vars): missing = [key for key, val in list(envs.items()) if val is None] if missing: msg = ( - "These environment variables must be set: " + ", ".join(missing) + u"These environment variables must be set: " + u", ".join(missing) ) raise BrowserConfigError(msg) # Check that we support this browser if envs['SELENIUM_BROWSER'] not in BROWSERS: - msg = "Unsuppported browser: {0}".format(envs['SELENIUM_BROWSER']) + msg = u"Unsuppported browser: {0}".format(envs['SELENIUM_BROWSER']) raise BrowserConfigError(msg) return envs diff --git a/bok_choy/javascript.py b/bok_choy/javascript.py index 543f4c69..9257afca 100644 --- a/bok_choy/javascript.py +++ b/bok_choy/javascript.py @@ -123,14 +123,14 @@ def _wait_for_js(self): if hasattr(self, '_js_vars') and self._js_vars: EmptyPromise( lambda: _are_js_vars_defined(self.browser, self._js_vars), - "JavaScript variables defined: {0}".format(", ".join(self._js_vars)) + u"JavaScript variables defined: {0}".format(", ".join(self._js_vars)) ).fulfill() # Wait for RequireJS dependencies to load if hasattr(self, '_requirejs_deps') and self._requirejs_deps: EmptyPromise( lambda: _are_requirejs_deps_loaded(self.browser, self._requirejs_deps), - "RequireJS dependencies loaded: {0}".format(", ".join(self._requirejs_deps)), + u"RequireJS dependencies loaded: {0}".format(", ".join(self._requirejs_deps)), try_limit=5 ).fulfill() @@ -144,13 +144,13 @@ def _are_js_vars_defined(browser, js_vars): """ # This script will evaluate to True iff all of # the required vars are defined. - script = " && ".join([ - "!(typeof {0} === 'undefined')".format(var) + script = u" && ".join([ + u"!(typeof {0} === 'undefined')".format(var) for var in js_vars ]) try: - return browser.execute_script("return {}".format(script)) + return browser.execute_script(u"return {}".format(script)) except WebDriverException as exc: if "is not defined" in exc.msg or "is undefined" in exc.msg: return False @@ -176,7 +176,7 @@ def _are_requirejs_deps_loaded(browser, deps): # We install a RequireJS module with the dependencies we want # to ensure are loaded. When our module loads, we return # control to the test suite. - script = dedent(""" + script = dedent(u""" // Retrieve the callback function used to return control to the test suite var callback = arguments[arguments.length - 1]; diff --git a/bok_choy/page_object.py b/bok_choy/page_object.py index 0c06f55e..42dec0d9 100644 --- a/bok_choy/page_object.py +++ b/bok_choy/page_object.py @@ -40,14 +40,14 @@ XSS_HTML = " safe_hits_count: potential_hits = re.findall('<[^<]+=2,<4 # Browser automation driver six # For Python 2 & 3 compatibility diff --git a/requirements/base.txt b/requirements/base.txt index e76924a2..d17c1df6 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,7 +4,7 @@ # # make upgrade # -lazy==1.3 -selenium==3.14.0 -six==1.11.0 -urllib3==1.23 # via selenium +lazy==1.4 +selenium==3.141.0 +six==1.12.0 +urllib3==1.24.1 # via selenium diff --git a/requirements/constraints.txt b/requirements/constraints.txt new file mode 100644 index 00000000..fff6e400 --- /dev/null +++ b/requirements/constraints.txt @@ -0,0 +1,15 @@ +# Version constraints for pip-installation. +# +# This file doesn't install any packages. It specifies version constraints +# that will be applied if a package is needed. +# +# When pinning something here, please provide an explanation of why. Ideally, +# link to other information that will help people in the future to remove the +# pin when possible. Writing an issue against the offending project and +# linking to it here is good. + +# more-itertools 6.0.0 dropped Python 2.7 support +more-itertools<6.0.0 + +# Newer versions of pylint-plugin-utils drop Python 2.7 support +pylint-plugin-utils<0.4 diff --git a/requirements/dev.in b/requirements/dev.in index 95c6cd0a..24511c47 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -1,6 +1,8 @@ # Dependencies that are used in development environments. # Please do not use this file for packages that are needed for test runs. +-c constraints.txt + -r pip-tools.txt # pip-tools and its dependencies, for managing requirements files -r needle.txt # Dependencies for running the various test suites -r travis.txt # Dependencies for tox and related utilities diff --git a/requirements/dev.txt b/requirements/dev.txt index 6e47df9b..ec630f93 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -5,57 +5,50 @@ # make upgrade # apipkg==1.5 -astroid==1.5.2 -atomicwrites==1.1.5 -attrs==18.1.0 -backports.functools-lru-cache==1.5 -certifi==2018.4.16 +astroid==1.5.3 +atomicwrites==1.3.0 +attrs==18.2.0 +certifi==2018.11.29 chardet==3.0.4 click-log==0.1.8 -click==6.7 +click==7.0 codecov==2.0.15 -configparser==3.5.0 -coverage==4.5.1 -edx-lint==0.5.5 -enum34==1.1.6 +coverage==4.5.2 +edx-lint==1.1.0 execnet==1.5.0 -first==2.0.1 -funcsigs==1.0.2 -futures==3.2.0 ; python_version == "2.7" -idna==2.7 +filelock==3.0.10 +idna==2.8 isort==4.3.4 lazy-object-proxy==1.3.1 -lazy==1.3 +lazy==1.4 mccabe==0.6.1 mock==2.0.0 -more-itertools==4.3.0 +more-itertools==5.0.0 needle==0.5.0 nose==1.3.7 -packaging==17.1 -pathlib2==2.3.2 -pbr==4.2.0 -pillow==5.2.0 -pip-tools==2.0.2 -pluggy==0.7.1 -py==1.5.4 -pycodestyle==2.4.0 +packaging==19.0 +pbr==5.1.2 +pillow==5.4.1 +pip-tools==3.3.2 +pluggy==0.8.1 +py==1.7.0 +pycodestyle==2.5.0 pylint-celery==0.3 pylint-django==0.7.2 pylint-plugin-utils==0.3 -pylint==1.7.1 -pyparsing==2.2.0 -pytest-cov==2.5.1 -pytest-forked==0.2 -pytest-xdist==1.22.5 -pytest==3.7.1 -requests==2.19.1 -scandir==1.9.0 -selenium==3.14.0 -singledispatch==3.4.0.3 -six==1.11.0 +pylint==1.7.6 +pyparsing==2.3.1 +pytest-cov==2.6.1 +pytest-forked==1.0.2 +pytest-xdist==1.26.1 +pytest==4.2.1 +requests==2.21.0 +selenium==3.141.0 +six==1.12.0 +toml==0.10.0 tox-battery==0.5.1 -tox-travis==0.10 -tox==3.2.1 -urllib3==1.23 -virtualenv==16.0.0 -wrapt==1.10.11 +tox-travis==0.11 +tox==3.7.0 +urllib3==1.24.1 +virtualenv==16.4.0 +wrapt==1.11.1 diff --git a/requirements/doc.in b/requirements/doc.in index 71980bfd..fafbf859 100644 --- a/requirements/doc.in +++ b/requirements/doc.in @@ -1,5 +1,7 @@ # Requirements for documentation generation +-c constraints.txt + -r base.txt # Core bok-choy dependencies edx-sphinx-theme # edX theme for Sphinx output diff --git a/requirements/doc.txt b/requirements/doc.txt index 59fea2e7..5aa4ba51 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -4,34 +4,28 @@ # # make upgrade # -alabaster==0.7.11 # via sphinx +alabaster==0.7.12 # via sphinx babel==2.6.0 # via sphinx -bleach==2.1.3 # via readme-renderer -certifi==2018.4.16 # via requests -cffi==1.11.5 # via cmarkgfm +bleach==3.1.0 # via readme-renderer +certifi==2018.11.29 # via requests chardet==3.0.4 # via requests -cmarkgfm==0.4.2 # via readme-renderer docutils==0.14 # via readme-renderer, sphinx -edx-sphinx-theme==1.3.0 -future==0.16.0 # via readme-renderer -html5lib==1.0.1 # via bleach -idna==2.7 # via requests -imagesize==1.0.0 # via sphinx +edx-sphinx-theme==1.4.0 +idna==2.8 # via requests +imagesize==1.1.0 # via sphinx jinja2==2.10 # via sphinx -lazy==1.3 -markupsafe==1.0 # via jinja2 -packaging==17.1 # via sphinx -pycparser==2.18 # via cffi -pygments==2.2.0 # via readme-renderer, sphinx -pyparsing==2.2.0 # via packaging -pytz==2018.5 # via babel -readme-renderer==21.0 -requests==2.19.1 # via sphinx -selenium==3.14.0 -six==1.11.0 +lazy==1.4 +markupsafe==1.1.0 # via jinja2 +packaging==19.0 # via sphinx +pygments==2.3.1 # via readme-renderer, sphinx +pyparsing==2.3.1 # via packaging +pytz==2018.9 # via babel +readme-renderer==24.0 +requests==2.21.0 # via sphinx +selenium==3.141.0 +six==1.12.0 snowballstemmer==1.2.1 # via sphinx -sphinx==1.7.6 +sphinx==1.8.4 sphinxcontrib-websupport==1.1.0 # via sphinx -typing==3.6.4 # via sphinx -urllib3==1.23 -webencodings==0.5.1 # via html5lib +urllib3==1.24.1 +webencodings==0.5.1 # via bleach diff --git a/requirements/needle.in b/requirements/needle.in index a31a95a4..3e442e51 100644 --- a/requirements/needle.in +++ b/requirements/needle.in @@ -1,5 +1,7 @@ # Requirements for test runs with needle installed for visual diff support +-c constraints.txt + -r test.txt # Base testing dependencies needle # For test assertions involving screenshots and visual diffs diff --git a/requirements/needle.txt b/requirements/needle.txt index e9f3bc9f..ae15ffc3 100644 --- a/requirements/needle.txt +++ b/requirements/needle.txt @@ -5,46 +5,38 @@ # make upgrade # apipkg==1.5 -astroid==1.5.2 -atomicwrites==1.1.5 -attrs==18.1.0 -backports.functools-lru-cache==1.5 +astroid==1.5.3 +atomicwrites==1.3.0 +attrs==18.2.0 click-log==0.1.8 -click==6.7 -configparser==3.5.0 -coverage==4.5.1 -edx-lint==0.5.5 -enum34==1.1.6 +click==7.0 +coverage==4.5.2 +edx-lint==1.1.0 execnet==1.5.0 -funcsigs==1.0.2 -futures==3.2.0 ; python_version == "2.7" isort==4.3.4 lazy-object-proxy==1.3.1 -lazy==1.3 +lazy==1.4 mccabe==0.6.1 mock==2.0.0 -more-itertools==4.3.0 +more-itertools==5.0.0 needle==0.5.0 nose==1.3.7 # via needle -packaging==17.1 -pathlib2==2.3.2 -pbr==4.2.0 -pillow==5.2.0 # via needle -pluggy==0.7.1 -py==1.5.4 -pycodestyle==2.4.0 +packaging==19.0 +pbr==5.1.2 +pillow==5.4.1 # via needle +pluggy==0.8.1 +py==1.7.0 +pycodestyle==2.5.0 pylint-celery==0.3 pylint-django==0.7.2 pylint-plugin-utils==0.3 -pylint==1.7.1 -pyparsing==2.2.0 -pytest-cov==2.5.1 -pytest-forked==0.2 -pytest-xdist==1.22.5 -pytest==3.7.1 -scandir==1.9.0 -selenium==3.14.0 -singledispatch==3.4.0.3 -six==1.11.0 -urllib3==1.23 -wrapt==1.10.11 +pylint==1.7.6 +pyparsing==2.3.1 +pytest-cov==2.6.1 +pytest-forked==1.0.2 +pytest-xdist==1.26.1 +pytest==4.2.1 +selenium==3.141.0 +six==1.12.0 +urllib3==1.24.1 +wrapt==1.11.1 diff --git a/requirements/pip-tools.in b/requirements/pip-tools.in index c17d0b41..0295d2c8 100644 --- a/requirements/pip-tools.in +++ b/requirements/pip-tools.in @@ -1,3 +1,5 @@ # Just the dependencies to run pip-tools, mainly for the "upgrade" make target +-c constraints.txt + pip-tools # Contains pip-compile, used to generate pip requirements files diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index e7027f3f..9de74284 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -4,7 +4,6 @@ # # make upgrade # -click==6.7 # via pip-tools -first==2.0.1 # via pip-tools -pip-tools==2.0.2 -six==1.11.0 # via pip-tools +click==7.0 # via pip-tools +pip-tools==3.3.2 +six==1.12.0 # via pip-tools diff --git a/requirements/test.in b/requirements/test.in index 8eb59582..d3e640c8 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -1,5 +1,7 @@ # Additional requirements for test runs. +-c constraints.txt + -r base.txt # Core bok-choy dependencies edx_lint # pylint plug-ins for additional code quality checks @@ -7,6 +9,5 @@ futures ; python_version == "2.7" # via isort mock # For mocking functionality in assorted tests packaging # For version number parsing and comparisons pycodestyle # For checking compliance with PEP 8 coding style guidelines -pylint-plugin-utils<0.4 # via pylint-celery, pylint-django; newer versions drop Python 2 support pytest-cov # For code coverage statistics generation pytest-xdist # For parallel test execution diff --git a/requirements/test.txt b/requirements/test.txt index 48e46c7f..810bc832 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -5,43 +5,35 @@ # make upgrade # apipkg==1.5 # via execnet -astroid==1.5.2 # via edx-lint, pylint, pylint-celery -atomicwrites==1.1.5 # via pytest -attrs==18.1.0 # via pytest -backports.functools-lru-cache==1.5 # via astroid, pylint +astroid==1.5.3 # via edx-lint, pylint, pylint-celery +atomicwrites==1.3.0 # via pytest +attrs==18.2.0 # via pytest click-log==0.1.8 # via edx-lint -click==6.7 # via click-log, edx-lint -configparser==3.5.0 # via pylint -coverage==4.5.1 # via pytest-cov -edx-lint==0.5.5 -enum34==1.1.6 # via astroid +click==7.0 # via click-log, edx-lint +coverage==4.5.2 # via pytest-cov +edx-lint==1.1.0 execnet==1.5.0 # via pytest-xdist -funcsigs==1.0.2 # via mock, pytest -futures==3.2.0 ; python_version == "2.7" isort==4.3.4 # via pylint lazy-object-proxy==1.3.1 # via astroid -lazy==1.3 +lazy==1.4 mccabe==0.6.1 # via pylint mock==2.0.0 -more-itertools==4.3.0 # via pytest -packaging==17.1 -pathlib2==2.3.2 # via pytest -pbr==4.2.0 # via mock -pluggy==0.7.1 # via pytest -py==1.5.4 # via pytest -pycodestyle==2.4.0 +more-itertools==5.0.0 # via pytest +packaging==19.0 +pbr==5.1.2 # via mock +pluggy==0.8.1 # via pytest +py==1.7.0 # via pytest +pycodestyle==2.5.0 pylint-celery==0.3 # via edx-lint pylint-django==0.7.2 # via edx-lint -pylint-plugin-utils==0.3 -pylint==1.7.1 # via edx-lint, pylint-celery, pylint-django, pylint-plugin-utils -pyparsing==2.2.0 # via packaging -pytest-cov==2.5.1 -pytest-forked==0.2 # via pytest-xdist -pytest-xdist==1.22.5 -pytest==3.7.1 # via pytest-cov, pytest-forked, pytest-xdist -scandir==1.9.0 # via pathlib2 -selenium==3.14.0 -singledispatch==3.4.0.3 # via astroid, pylint -six==1.11.0 -urllib3==1.23 -wrapt==1.10.11 # via astroid +pylint-plugin-utils==0.3 # via pylint-celery, pylint-django +pylint==1.7.6 # via edx-lint, pylint-celery, pylint-django, pylint-plugin-utils +pyparsing==2.3.1 # via packaging +pytest-cov==2.6.1 +pytest-forked==1.0.2 # via pytest-xdist +pytest-xdist==1.26.1 +pytest==4.2.1 # via pytest-cov, pytest-forked, pytest-xdist +selenium==3.141.0 +six==1.12.0 +urllib3==1.24.1 +wrapt==1.11.1 # via astroid diff --git a/requirements/travis.in b/requirements/travis.in index f2337814..7ba64b41 100644 --- a/requirements/travis.in +++ b/requirements/travis.in @@ -1,6 +1,8 @@ # Packages needed in order to run tox. # Installed by Travis and dev environments. +-c constraints.txt + codecov # Code coverage reporting tox # Virtualenv management for tests tox-battery # Makes tox aware of requirements file changes diff --git a/requirements/travis.txt b/requirements/travis.txt index 4dc4ec6d..68f38243 100644 --- a/requirements/travis.txt +++ b/requirements/travis.txt @@ -4,17 +4,19 @@ # # make upgrade # -certifi==2018.4.16 # via requests +certifi==2018.11.29 # via requests chardet==3.0.4 # via requests codecov==2.0.15 -coverage==4.5.1 # via codecov -idna==2.7 # via requests -pluggy==0.7.1 # via tox -py==1.5.4 # via tox -requests==2.19.1 # via codecov -six==1.11.0 # via tox +coverage==4.5.2 # via codecov +filelock==3.0.10 # via tox +idna==2.8 # via requests +pluggy==0.8.1 # via tox +py==1.7.0 # via tox +requests==2.21.0 # via codecov +six==1.12.0 # via tox +toml==0.10.0 # via tox tox-battery==0.5.1 -tox-travis==0.10 -tox==3.2.1 -urllib3==1.23 # via requests -virtualenv==16.0.0 # via tox +tox-travis==0.11 +tox==3.7.0 +urllib3==1.24.1 # via requests +virtualenv==16.4.0 # via tox diff --git a/setup.py b/setup.py index 06277522..4693b695 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ import sys from setuptools import setup -VERSION = '0.9.2' +VERSION = '0.9.3' DESCRIPTION = 'UI-level acceptance test framework' @@ -31,6 +31,7 @@ def is_requirement(line): """ return not ( line == '' or + line.startswith('-c') or line.startswith('-r') or line.startswith('#') or line.startswith('-e') or diff --git a/tests/pages.py b/tests/pages.py index f44374e9..65a685f2 100644 --- a/tests/pages.py +++ b/tests/pages.py @@ -78,13 +78,13 @@ def select_car(self, car_value): """ Select the car with ``car_value`` in the drop-down list. """ - self.q(css='select[name="cars"] option[value="{}"]'.format(car_value)).first.click() + self.q(css=u'select[name="cars"] option[value="{}"]'.format(car_value)).first.click() def is_car_selected(self, car): """ Return ``True`` if the given ``car`` is selected, ``False`` otherwise. """ - return self.q(css='select[name="cars"] option[value="{}"]'.format(car)).selected + return self.q(css=u'select[name="cars"] option[value="{}"]'.format(car)).selected class CheckboxPage(SitePage): @@ -97,7 +97,7 @@ def toggle_pill(self, pill_name): """ Toggle the box for the pill with `pill_name` (red or blue). """ - self.q(css="#fixture input#{}".format(pill_name)).first.click() + self.q(css=u"#fixture input#{}".format(pill_name)).first.click() class AlertPage(SitePage): diff --git a/tests/test_browser.py b/tests/test_browser.py index 855276b6..eb39a7d2 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -299,9 +299,9 @@ def test_save_driver_logs_exception(self, caplog): # Check that no files were created. log_types = browser.log_types for log_type in log_types: - expected_file = os.path.join(tempdir_path, 'js_page_{}.log'.format(log_type)) + expected_file = os.path.join(tempdir_path, u'js_page_{}.log'.format(log_type)) assert not os.path.exists(expected_file) - assert "Could not save browser log of type '{}'.".format(log_type) in caplog.text + assert u"Could not save browser log of type '{}'.".format(log_type) in caplog.text def test_save_source(self): browser = self.browser diff --git a/tests/test_page_object.py b/tests/test_page_object.py index e86e6bd4..1514247f 100644 --- a/tests/test_page_object.py +++ b/tests/test_page_object.py @@ -118,7 +118,7 @@ def test_validate_url(self): self.assertEqual( returned_val, is_valid, - msg="Url: {0}, Expected {1} but got {2}".format(url, is_valid, returned_val) + msg=u"Url: {0}, Expected {1} but got {2}".format(url, is_valid, returned_val) ) def test_guarded_methods(self):