From 406f82f7d70ed9fe4a0bfcc7f2cd75957db1fe5e Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 31 Dec 2015 01:05:21 +0000 Subject: [PATCH 01/26] Changes to Travis settings to allow installation dependent on Python versions. Already has some settings for Python 3.4, but disabled. --- .travis.yml | 17 ++++++++++++----- .travis_python_dep.sh | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) create mode 100755 .travis_python_dep.sh diff --git a/.travis.yml b/.travis.yml index 3125407a4..6656d1a7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,20 @@ sudo: false python: - "2.6" - "2.7" -install: + #- "3.4" +before_install: + - "./.travis_python_dep.sh" +install: true #- pip install pep8 --use-mirrors #- pip install pyflakes --use-mirrors - - pip install robotframework - - pip install selenium - - pip install decorator - - pip install docutils + # Installation is done at before_install + ##- pip install robotframework==3.0b1 + ##- pip install selenium + ##- pip install decorator + ##- pip install docutils + ##- pip install future + # Mockito is only used when in Python 2.7 after installing future + ##- pip install mockito #- "if [[ ${BROWSER} == 'ie' ]]; then pip install ie_only_pkg; fi" before_script: - "export DISPLAY=:99.0" diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh new file mode 100755 index 000000000..239618f4e --- /dev/null +++ b/.travis_python_dep.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -ev +PYTHON_VERSION=`python -c "import sys; print(sys.version[:3])"` +if [ "${PYTHON_VERSION}" = "2.6" ]; then + pip install robotframework==2.9.2 + pip install selenium + pip install decorator + pip install docutils + # pip install future + # pip install mockito +elif [ "${PYTHON_VERSION}" = "2.7" ]; then + pip install robotframework + pip install selenium + pip install decorator + pip install docutils + # pip install future + # pip install mockito +elif [ "${PYTHON_VERSION}" = "3.4" ]; then + pip install robotframework==3.0b1 + pip install selenium + pip install decorator + pip install docutils + pip install future +fi From 507710841b2cb918087707495871be8417601570 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Fri, 1 Jan 2016 17:52:34 +0000 Subject: [PATCH 02/26] Transformed print statement into function. Compatible with Python 2.6. --- build_dist.py | 17 +++++++------ demo/demoapp/server.py | 12 +++++---- demo/package.py | 6 +++-- demo/rundemo.py | 16 ++++++------ doc/buildhtml.py | 12 ++++----- doc/generate.py | 7 ++++-- doc/generate_readmes.py | 6 +++-- src/ez_setup.py | 33 ++++++++++++------------- test/resources/statuschecker.py | 8 +++--- test/resources/testserver/testserver.py | 6 +++-- test/run_tests.py | 26 ++++++++++--------- test/run_unit_tests.py | 8 +++--- 12 files changed, 88 insertions(+), 69 deletions(-) diff --git a/build_dist.py b/build_dist.py index 6b5dd3530..0227acb09 100644 --- a/build_dist.py +++ b/build_dist.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from __future__ import print_function import os, sys, shutil, subprocess, argparse THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -9,9 +10,9 @@ sys.path.append(os.path.join(THIS_DIR, "demo")) def main(): - parser = argparse.ArgumentParser(description="Builds a Se2Lib distribution") - parser.add_argument('py_26_path', action='store', help='Python 2.6 executbale file path') - parser.add_argument('py_27_path', action='store', help='Python 2.7 executbale file path') + parser = argparse.ArgumentParser(description="Builds a Selenium2Library distribution") + parser.add_argument('py_26_path', action='store', help='Python 2.6 executable file path') + parser.add_argument('py_27_path', action='store', help='Python 2.7 executable file path') parser.add_argument('--release', action='store_true') parser.add_argument('--winonly', action='store_true') args = parser.parse_args() @@ -33,7 +34,7 @@ def clear_dist_folder(): def run_doc_gen(): import generate - print + print() generate.main() def run_register(args): @@ -50,12 +51,12 @@ def run_builds(args): _run_setup(args.py_27_path, "bdist_wininst", [ "--plat-name=win32" ], args.release) _run_setup(args.py_27_path, "bdist_wininst", [ "--plat-name=win-amd64" ], args.release) else: - print + print() print("Windows binary installers cannot be built on this platform!") def run_demo_packaging(): import package - print + print() package.main() def _run_setup(py_path, type, params, upload): @@ -66,8 +67,8 @@ def _run_setup(py_path, type, params, upload): if upload: setup_args.append("upload") - print - print("Running: %s" % ' '.join(setup_args)) + print() + print("Running: {0}".format(' '.join(setup_args))) returncode = subprocess.call(setup_args) if returncode != 0: print("Error running setup.py") diff --git a/demo/demoapp/server.py b/demo/demoapp/server.py index 08576e0c9..16c6842c7 100644 --- a/demo/demoapp/server.py +++ b/demo/demoapp/server.py @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import print_function + """Simple HTTP server requiring only Python and no other preconditions. Server is started by running this script with argument 'start' and @@ -55,25 +57,25 @@ def do_QUIT(self): def do_POST(self): # We could also process paremeters here using something like below. # length = self.headers['Content-Length'] - # print self.rfile.read(int(length)) + # print(self.rfile.read(int(length))) self.do_GET() def start_server(host=DEFAULT_HOST, port=DEFAULT_PORT): - print "Demo application starting on port %s" % port + print("Demo application starting on port {0}".format(port)) root = os.path.dirname(os.path.abspath(__file__)) os.chdir(root) server = StoppableHttpServer((host, int(port)), StoppableHttpRequestHandler) server.serve_forever() def stop_server(host=DEFAULT_HOST, port=DEFAULT_PORT): - print "Demo application on port %s stopping" % port + print("Demo application on port {0} stopping".format(port)) conn = httplib.HTTPConnection("%s:%s" % (host, port)) conn.request("QUIT", "/") conn.getresponse() def print_help(): - print __doc__ + print(__doc__) if __name__ == '__main__': @@ -82,4 +84,4 @@ def print_help(): 'stop': stop_server, 'help': print_help}[sys.argv[1]](*sys.argv[2:]) except (IndexError, KeyError, TypeError): - print 'Usage: %s start|stop|help [port]' % os.path.basename(sys.argv[0]) + print("Usage: {0} start|stop|help [port]".format(os.path.basename(sys.argv[0]))) diff --git a/demo/package.py b/demo/package.py index e02a706e7..d376396b8 100755 --- a/demo/package.py +++ b/demo/package.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function + import os, sys from time import localtime from zipfile import ZipFile, ZIP_DEFLATED @@ -26,14 +28,14 @@ def main(): for dirname in FILES: for filename in FILES[dirname]: path = os.path.join('.', dirname.replace('/', os.sep), filename) - print 'Adding: ', os.path.normpath(path) + print("Adding: {0}".format(os.path.normpath(path))) zipfile.write(path, os.path.join(name, path)) zipfile.close() target_path = os.path.join('..', 'dist', zipname) if os.path.exists(target_path): os.remove(target_path) os.rename(zipname, target_path) - print 'Created: ', os.path.abspath(target_path) + print("Created: {0}".format(os.path.abspath(target_path))) finally: os.chdir(cwd) diff --git a/demo/rundemo.py b/demo/rundemo.py index 3ed0051c2..adbe1c763 100755 --- a/demo/rundemo.py +++ b/demo/rundemo.py @@ -1,5 +1,7 @@ #! /usr/bin/env python +from __future__ import print_function + """Runner Script for Robot Framework SeleniumLibrary Demo Tests are run by giving a path to the tests to be executed as an argument to @@ -33,9 +35,9 @@ try: import Selenium2Library except ImportError, e: - print 'Importing Selenium2Library module failed (%s).' % e - print 'Please make sure you have Selenium2Library properly installed.' - print 'See INSTALL.rst for troubleshooting information.' + print("Importing Selenium2Library module failed ({0})".format(e)) + print("Please make sure you have Selenium2Library properly installed.") + print("See INSTALL.rst for troubleshooting information.") sys.exit(1) @@ -55,12 +57,12 @@ def stop_demo_application(): call(['python', DEMOAPP, 'stop'], stdout=TemporaryFile(), stderr=STDOUT) def print_help(): - print __doc__ + print(__doc__) def print_usage(): - print 'Usage: rundemo.py [options] datasource' - print ' or: rundemo.py demoapp start|stop' - print ' or: rundemo.py help' + print("Usage: rundemo.py [options] datasource") + print(" or: rundemo.py demoapp start|stop") + print(" or: rundemo.py help") if __name__ == '__main__': diff --git a/doc/buildhtml.py b/doc/buildhtml.py index 5c5db1ead..5d11463b2 100644 --- a/doc/buildhtml.py +++ b/doc/buildhtml.py @@ -4,6 +4,7 @@ # Author: David Goodger # Copyright: This module has been placed in the public domain. +from __future__ import print_function """ Generates .html from all the .txt files in a directory. @@ -29,7 +30,7 @@ import docutils from docutils import ApplicationError from docutils import core, frontend, utils -from docutils.error_reporting import ErrorOutput, ErrorString +from docutils.utils.error_reporting import ErrorOutput, ErrorString from docutils.parsers import rst from docutils.readers import standalone, pep from docutils.writers import html4css1, pep_html @@ -197,13 +198,12 @@ def visit(self, directory, names): settings = self.get_settings('', directory) errout = ErrorOutput(encoding=settings.error_encoding) if settings.prune and (os.path.abspath(directory) in settings.prune): - print >>errout, ('/// ...Skipping directory (pruned): %s' % - directory) + print("/// ...Skipping directory (pruned): {0}".format(directory), file=errout) sys.stderr.flush() names[:] = [] return if not self.initial_settings.silent: - print >>errout, '/// Processing directory: %s' % directory + print("/// Processing directory: {0}".format(directory), file=errout) sys.stderr.flush() # settings.ignore grows many duplicate entries as we recurse # if we add patterns in config files or on the command line. @@ -232,7 +232,7 @@ def process_txt(self, directory, name): settings._source = os.path.normpath(os.path.join(directory, name)) settings._destination = settings._source[:-4]+'.html' if not self.initial_settings.silent: - print >>errout, ' ::: Processing: %s' % name + print(" ::: Processing: {0}".format(name), file=errout) sys.stderr.flush() try: if not settings.dry_run: @@ -243,7 +243,7 @@ def process_txt(self, directory, name): writer_name=pub_struct.writer_name, settings=settings) except ApplicationError, error: - print >>errout, ' %s' % ErrorString(error) + print(" {0}".format(ErrorString(error)), file=errout) if __name__ == "__main__": diff --git a/doc/generate.py b/doc/generate.py index 08ca44889..8eb445538 100755 --- a/doc/generate.py +++ b/doc/generate.py @@ -1,14 +1,17 @@ #!/usr/bin/env python + +from __future__ import print_function from os.path import join, dirname + try: from robot.libdoc import libdoc except: def main(): - print """Robot Framework 2.7 or later required for generating documentation""" + print('"""Robot Framework 2.7 or later required for generating documentation"""') else: def main(): libdoc(join(dirname(__file__),'..','src','Selenium2Library'), join(dirname(__file__),'Selenium2Library.html')) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index be6828b74..ecdaa2976 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -1,8 +1,10 @@ #!/usr/bin/env python +from __future__ import print_function import os, shutil from buildhtml import Builder + THIS_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_DIR = os.path.join(THIS_DIR, "..") SRC_DIR = os.path.join(ROOT_DIR, "src") @@ -19,7 +21,7 @@ def main(): try: import docutils except: - print "Readme files will not be built into HTML, docutils not installed" + print("Readme files will not be built into HTML, docutils not installed") return for readme_relative_path in README_FILES: (readme_dir, readme_name) = _parse_readme_path(readme_relative_path) @@ -36,7 +38,7 @@ def main(): os.remove(target_readme_html_path) os.rename(readme_html_path, target_readme_html_path) - print " ::: Saved: %s" % target_readme_html_name + print(" ::: Saved: {0}".format(target_readme_html_name)) def _parse_readme_path(readme_relative_path): readme_abs_path = os.path.join(ROOT_DIR, readme_relative_path.replace('/', os.sep)) diff --git a/src/ez_setup.py b/src/ez_setup.py index b74adc065..c1693bb14 100644 --- a/src/ez_setup.py +++ b/src/ez_setup.py @@ -1,4 +1,7 @@ #!python + +from __future__ import print_function + """Bootstrap setuptools installation If you want to use setuptools in your package's setup.py, just include this @@ -70,10 +73,8 @@ def _validate_md5(egg_name, data): if egg_name in md5_data: digest = md5(data).hexdigest() if digest != md5_data[egg_name]: - print >>sys.stderr, ( - "md5 validation of %s failed! (Possible download problem?)" - % egg_name - ) + print("md5 validation of {0} failed! (Possible download problem?)".format(egg_name), + file=sys.stderr) sys.exit(2) return data @@ -105,12 +106,10 @@ def do_download(): pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: if was_imported: - print >>sys.stderr, ( - "The required version of setuptools (>=%s) is not available, and\n" - "can't be installed while this script is running. Please install\n" - " a more recent version first, using 'easy_install -U setuptools'." - "\n\n(Currently using %r)" - ) % (version, e.args[0]) + print("The required version of setuptools (>={0}) is not available, and\n".format(version), file=sys.stderr) + print("can't be installed while this script is running. Please install\n") + print(" a more recent version first, using 'easy_install -U setuptools'.") + print("\n\n(Currently using {0})".format(e.args[0]), file=sys.stderr) sys.exit(2) except pkg_resources.DistributionNotFound: pass @@ -216,10 +215,10 @@ def main(argv, version=DEFAULT_VERSION): os.unlink(egg) else: if setuptools.__version__ == '0.0.1': - print >>sys.stderr, ( - "You have an obsolete version of setuptools installed. Please\n" - "remove it from your system entirely before rerunning this script." - ) + print("You have an obsolete version of setuptools installed. Please\n", + file=sys.stderr) + print("remove it from your system entirely before rerunning this script.", + file=sys.stderr) sys.exit(2) req = "setuptools>="+version @@ -238,8 +237,8 @@ def main(argv, version=DEFAULT_VERSION): from setuptools.command.easy_install import main main(argv) else: - print "Setuptools version",version,"or greater has been installed." - print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' + print("Setuptools version {0} or greater has been installed.".format(version)) + print("Run 'ez_setup.py -U setuptools' to reinstall or upgrade.") def update_md5(filenames): """Update our built-in md5 registry""" @@ -262,7 +261,7 @@ def update_md5(filenames): match = re.search("\nmd5_data = {\n([^}]+)}", src) if not match: - print >>sys.stderr, "Internal error!" + print("Internal error!", file=sys.stderr) sys.exit(2) src = src[:match.start(1)] + repl + src[match.end(1):] diff --git a/test/resources/statuschecker.py b/test/resources/statuschecker.py index 20b6a849d..6c9e389fe 100755 --- a/test/resources/statuschecker.py +++ b/test/resources/statuschecker.py @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import print_function + """Robot Framework Test Status Checker Usage: statuschecker.py infile [outfile] @@ -177,14 +179,14 @@ def _get_log_message(self, msg_str): import os if not 2 <= len(sys.argv) <= 3 or '--help' in sys.argv: - print __doc__ + print(__doc__) sys.exit(1) infile = sys.argv[1] outfile = sys.argv[2] if len(sys.argv) == 3 else None - print "Checking %s" % os.path.abspath(infile) + print("Checking {0}".format(os.path.abspath(infile))) rc = process_output(infile, outfile) if outfile: - print "Output: %s" % os.path.abspath(outfile) + print("Output: {0}".format(os.path.abspath(outfile))) if rc > 255: rc = 255 sys.exit(rc) diff --git a/test/resources/testserver/testserver.py b/test/resources/testserver/testserver.py index 3d33a24ca..ef70c25f1 100644 --- a/test/resources/testserver/testserver.py +++ b/test/resources/testserver/testserver.py @@ -1,5 +1,7 @@ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/336012 +from __future__ import print_function + import SimpleHTTPServer import BaseHTTPServer import httplib @@ -18,7 +20,7 @@ def do_QUIT(self): def do_POST(self): # We could also process paremeters here using something like below. # length = self.headers['Content-Length'] - # print self.rfile.read(int(length)) + # print(self.rfile.read(int(length))) self.do_GET() def send_head(self): @@ -94,7 +96,7 @@ def start_server(port=7000): if __name__ == '__main__': import sys if len(sys.argv) != 2 or sys.argv[1] not in [ 'start', 'stop' ]: - print 'usage: %s start|stop' % sys.argv[0] + print("usage: {0} start|stop".format(sys.argv[0])) sys.exit(1) if sys.argv[1] == 'start': start_server() diff --git a/test/run_tests.py b/test/run_tests.py index ac7f69c8c..4726ac5a3 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function + import env import os import sys @@ -53,8 +55,8 @@ def execute_tests(runner, args): if not os.path.exists(env.RESULTS_DIR): os.mkdir(env.RESULTS_DIR) command = [runner] + [arg % ARG_VALUES for arg in ROBOT_ARGS] + args + [env.ACCEPTANCE_TEST_DIR] - print '' - print 'Starting test execution with command:\n' + ' '.join(command) + print() + print("Starting test execution with command:\n{0}".format(' '.join(command))) syslog = os.path.join(env.RESULTS_DIR, 'syslog.txt') call(command, shell=os.sep=='\\', env=dict(os.environ, ROBOT_SYSLOG_FILE=syslog)) @@ -69,13 +71,13 @@ def process_output(args): rebot = 'rebot' if os.sep == '/' else 'rebot.bat' rebot_cmd = [rebot] + [ arg % ARG_VALUES for arg in REBOT_ARGS ] + args + \ [os.path.join(ARG_VALUES['outdir'], 'output.xml') ] - print '' - print 'Starting output processing with command:\n' + ' '.join(rebot_cmd) + print() + print("Starting output processing with command:\n{0}".format(' '.join(rebot_cmd))) rc = call(rebot_cmd, env=os.environ) if rc == 0: - print 'All critical tests passed' + print("All critical tests passed") else: - print '%d critical test%s failed' % (rc, 's' if rc != 1 else '') + print("{0} critical test{1} failed".format(rc, 's' if rc != 1 else '')) return rc def _has_robot_27(): @@ -89,18 +91,18 @@ def _exit(rc): sys.exit(rc) def _help(): - print 'Usage: python run_tests.py python|jython browser [options]' - print - print 'See README.txt for details.' + print("Usage: python run_tests.py python|jython browser [options]") + print() + print("See README.txt for details.") return 255 def _run_unit_tests(): - print 'Running unit tests' + print("Running unit tests") failures = run_unit_tests() if failures != 0: - print '\n%d unit tests failed - not running acceptance tests!' % failures + print("\n{0} unit tests failed - not running acceptance tests!".format(failures)) else: - print 'All unit tests passed' + print("All unit tests passed") return failures diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index aa417c192..b132b58b5 100755 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -1,3 +1,5 @@ +from __future__ import print_function + import env import os, sys import unittest @@ -5,14 +7,14 @@ def run_unit_tests(modules_to_run=[]): (test_module_names, test_modules) = utils.import_modules_under( - env.UNIT_TEST_DIR, include_root_package_name = False, pattern="test*.py") + env.UNIT_TEST_DIR, include_root_package_name = True, pattern="test*.py") bad_modules_to_run = [module_to_run for module_to_run in modules_to_run if module_to_run not in test_module_names] if bad_modules_to_run: - print "Specified test module%s not exist: %s" % ( + print("Specified test module%s not exist: {0}".format( ' does' if len(bad_modules_to_run) == 1 else 's do', - ', '.join(bad_modules_to_run)) + ', '.join(bad_modules_to_run))) return -1 tests = [unittest.defaultTestLoader.loadTestsFromModule(test_module) From b4b4fde0d20551020a633ad3d6e332937ae4f7ce Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Fri, 1 Jan 2016 19:11:34 +0000 Subject: [PATCH 03/26] Fixes import to be compatible with RobotFramework 3.0. Changes Travis settings to install RobotFramework 3.0. --- .travis_python_dep.sh | 4 ++-- src/Selenium2Library/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh index 239618f4e..db4493473 100755 --- a/.travis_python_dep.sh +++ b/.travis_python_dep.sh @@ -2,7 +2,7 @@ set -ev PYTHON_VERSION=`python -c "import sys; print(sys.version[:3])"` if [ "${PYTHON_VERSION}" = "2.6" ]; then - pip install robotframework==2.9.2 + pip install robotframework pip install selenium pip install decorator pip install docutils @@ -16,7 +16,7 @@ elif [ "${PYTHON_VERSION}" = "2.7" ]; then # pip install future # pip install mockito elif [ "${PYTHON_VERSION}" = "3.4" ]; then - pip install robotframework==3.0b1 + pip install robotframework pip install selenium pip install decorator pip install docutils diff --git a/src/Selenium2Library/__init__.py b/src/Selenium2Library/__init__.py index 75884e9ea..f6eca9b61 100644 --- a/src/Selenium2Library/__init__.py +++ b/src/Selenium2Library/__init__.py @@ -1,5 +1,5 @@ import os -from keywords import * +from Selenium2Library.keywords import * from version import VERSION from utils import LibraryListener From fb2f937d6b53d3b57f5efa4011e40a26c50984b0 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Fri, 1 Jan 2016 20:44:44 +0000 Subject: [PATCH 04/26] Separates imports per line, for better code readability. --- build_dist.py | 6 +++++- demo/package.py | 3 ++- doc/generate_readmes.py | 3 ++- src/Selenium2Library/keywords/_screenshot.py | 3 ++- src/ez_setup.py | 10 ++++++---- test/run_unit_tests.py | 3 ++- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/build_dist.py b/build_dist.py index 0227acb09..e46411ce6 100644 --- a/build_dist.py +++ b/build_dist.py @@ -1,7 +1,11 @@ #!/usr/bin/env python from __future__ import print_function -import os, sys, shutil, subprocess, argparse +import os +import sys +import shutil +import subprocess +import argparse THIS_DIR = os.path.dirname(os.path.abspath(__file__)) DIST_DIR = os.path.join(THIS_DIR, "dist") diff --git a/demo/package.py b/demo/package.py index d376396b8..0c7f56439 100755 --- a/demo/package.py +++ b/demo/package.py @@ -2,7 +2,8 @@ from __future__ import print_function -import os, sys +import os +import sys from time import localtime from zipfile import ZipFile, ZIP_DEFLATED diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index ecdaa2976..8dd6ad4eb 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -1,7 +1,8 @@ #!/usr/bin/env python from __future__ import print_function -import os, shutil +import os +import shutil from buildhtml import Builder diff --git a/src/Selenium2Library/keywords/_screenshot.py b/src/Selenium2Library/keywords/_screenshot.py index 8e824ccc8..59632fa24 100644 --- a/src/Selenium2Library/keywords/_screenshot.py +++ b/src/Selenium2Library/keywords/_screenshot.py @@ -1,5 +1,6 @@ import robot -import os, errno +import os +import errno from Selenium2Library import utils from keywordgroup import KeywordGroup diff --git a/src/ez_setup.py b/src/ez_setup.py index c1693bb14..e121c82b5 100644 --- a/src/ez_setup.py +++ b/src/ez_setup.py @@ -65,7 +65,8 @@ 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', } -import sys, os +import sys +import os try: from hashlib import md5 except ImportError: from md5 import md5 @@ -107,8 +108,8 @@ def do_download(): except pkg_resources.VersionConflict, e: if was_imported: print("The required version of setuptools (>={0}) is not available, and\n".format(version), file=sys.stderr) - print("can't be installed while this script is running. Please install\n") - print(" a more recent version first, using 'easy_install -U setuptools'.") + print("can't be installed while this script is running. Please install\n", file=sys.stderr) + print(" a more recent version first, using 'easy_install -U setuptools'.", file=sys.stderr) print("\n\n(Currently using {0})".format(e.args[0]), file=sys.stderr) sys.exit(2) except pkg_resources.DistributionNotFound: @@ -128,7 +129,8 @@ def download_setuptools( with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ - import urllib2, shutil + import urllib2 + import shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) url = download_base + egg_name saveto = os.path.join(to_dir, egg_name) diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index b132b58b5..64c403a53 100755 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -1,7 +1,8 @@ from __future__ import print_function import env -import os, sys +import os +import sys import unittest from Selenium2Library import utils From bb414779b5c7da63aa05692190ab3bda2148d8d5 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Fri, 1 Jan 2016 21:59:58 +0000 Subject: [PATCH 05/26] In `except` uses `as` instead of `,` when capturing the exception. --- demo/rundemo.py | 2 +- doc/buildhtml.py | 2 +- src/Selenium2Library/keywords/_runonfailure.py | 2 +- src/Selenium2Library/keywords/_tableelement.py | 2 +- src/Selenium2Library/keywords/keywordgroup.py | 2 +- src/ez_setup.py | 2 +- test/unit/keywords/test_browsermanagement.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/demo/rundemo.py b/demo/rundemo.py index adbe1c763..b18ec8984 100755 --- a/demo/rundemo.py +++ b/demo/rundemo.py @@ -34,7 +34,7 @@ try: import Selenium2Library -except ImportError, e: +except ImportError as e: print("Importing Selenium2Library module failed ({0})".format(e)) print("Please make sure you have Selenium2Library properly installed.") print("See INSTALL.rst for troubleshooting information.") diff --git a/doc/buildhtml.py b/doc/buildhtml.py index 5d11463b2..7b3db71bb 100644 --- a/doc/buildhtml.py +++ b/doc/buildhtml.py @@ -242,7 +242,7 @@ def process_txt(self, directory, name): parser_name='restructuredtext', writer_name=pub_struct.writer_name, settings=settings) - except ApplicationError, error: + except ApplicationError as error: print(" {0}".format(ErrorString(error)), file=errout) diff --git a/src/Selenium2Library/keywords/_runonfailure.py b/src/Selenium2Library/keywords/_runonfailure.py index 4e9057107..737e02f91 100644 --- a/src/Selenium2Library/keywords/_runonfailure.py +++ b/src/Selenium2Library/keywords/_runonfailure.py @@ -57,7 +57,7 @@ def _run_on_failure(self): self._running_on_failure_routine = True try: BUILTIN.run_keyword(self._run_on_failure_keyword) - except Exception, err: + except Exception as err: self._run_on_failure_error(err) finally: self._running_on_failure_routine = False diff --git a/src/Selenium2Library/keywords/_tableelement.py b/src/Selenium2Library/keywords/_tableelement.py index 55eea39c8..443f9eaa7 100644 --- a/src/Selenium2Library/keywords/_tableelement.py +++ b/src/Selenium2Library/keywords/_tableelement.py @@ -64,7 +64,7 @@ def table_cell_should_contain(self, table_locator, row, column, expected, loglev % (table_locator, row, column, expected)) try: content = self.get_table_cell(table_locator, row, column, loglevel='NONE') - except AssertionError, err: + except AssertionError as err: self._info(err) self.log_source(loglevel) raise AssertionError(message) diff --git a/src/Selenium2Library/keywords/keywordgroup.py b/src/Selenium2Library/keywords/keywordgroup.py index 672603afd..bb9a8c037 100644 --- a/src/Selenium2Library/keywords/keywordgroup.py +++ b/src/Selenium2Library/keywords/keywordgroup.py @@ -13,7 +13,7 @@ def _run_on_failure_decorator(method, *args, **kwargs): self._already_in_keyword = True # Set a flag on the instance so that as we call keywords inside this call and this gets run again, we know we're at least one level in. try: return method(*args, **kwargs) - except Exception, err: + except Exception as err: if hasattr(self, '_run_on_failure') and not self._has_run_on_failure: # If we're in an inner keyword, track the fact that we've already run on failure once self._has_run_on_failure = True diff --git a/src/ez_setup.py b/src/ez_setup.py index e121c82b5..1860de251 100644 --- a/src/ez_setup.py +++ b/src/ez_setup.py @@ -105,7 +105,7 @@ def do_download(): return do_download() try: pkg_resources.require("setuptools>="+version); return - except pkg_resources.VersionConflict, e: + except pkg_resources.VersionConflict as e: if was_imported: print("The required version of setuptools (>={0}) is not available, and\n".format(version), file=sys.stderr) print("can't be installed while this script is running. Please install\n", file=sys.stderr) diff --git a/test/unit/keywords/test_browsermanagement.py b/test/unit/keywords/test_browsermanagement.py index fd6062c60..782491730 100644 --- a/test/unit/keywords/test_browsermanagement.py +++ b/test/unit/keywords/test_browsermanagement.py @@ -96,7 +96,7 @@ def test_bad_browser_name(self): try: bm._make_browser("fireox") self.fail("Exception not raised") - except ValueError, e: + except ValueError as e: self.assertEquals("fireox is not a supported browser.", e.message) def test_create_webdriver(self): From e9107e090c11e262a85f094476c947d1f7d83f47 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 2 Jan 2016 01:26:22 +0000 Subject: [PATCH 06/26] With this commit Selenium2Library is compatible with RobotFramework 3.0 under Python 2.6, 2.7 and 3.4. Activates Python 3.4 in Travis config. Changed files with futurize from http://python-future.org/: build_dist.py demo/demoapp/server.py demo/package.py doc/buildhtml.py setup.py src/Selenium2Library/__init__.py src/Selenium2Library/keywords/__init__.py src/Selenium2Library/keywords/_alert.py src/Selenium2Library/keywords/_browsermanagement.py src/Selenium2Library/keywords/_cookie.py src/Selenium2Library/keywords/_element.py src/Selenium2Library/keywords/_formelement.py src/Selenium2Library/keywords/_javascript.py src/Selenium2Library/keywords/_logging.py src/Selenium2Library/keywords/_runonfailure.py src/Selenium2Library/keywords/_screenshot.py src/Selenium2Library/keywords/_selectelement.py src/Selenium2Library/keywords/_tableelement.py src/Selenium2Library/keywords/_waiting.py src/Selenium2Library/keywords/keywordgroup.py src/Selenium2Library/locators/__init__.py src/Selenium2Library/locators/customlocator.py src/Selenium2Library/locators/elementfinder.py src/Selenium2Library/locators/tableelementfinder.py src/Selenium2Library/locators/windowmanager.py src/Selenium2Library/utils/__init__.py src/Selenium2Library/utils/events/__init__.py src/Selenium2Library/utils/events/event.py src/Selenium2Library/utils/events/scope_event.py src/Selenium2Library/utils/librarylistener.py src/Selenium2Library/webdrivermonkeypatches.py src/ez_setup.py test/lib/mockito/__init__.py test/lib/mockito/inorder.py test/lib/mockito/invocation.py test/lib/mockito/matchers.py test/lib/mockito/mock_registry.py test/lib/mockito/mocking.py test/lib/mockito/mockito.py test/lib/mockito/spying.py test/lib/mockito/verification.py test/resources/statuschecker.py test/resources/testserver/testserver.py test/run_tests.py test/unit/keywords/test_browsermanagement.py test/unit/utils/test_browsercache.py --- .travis.yml | 2 +- .travis_python_dep.sh | 8 +- build_dist.py | 2 +- demo/demoapp/server.py | 14 +- demo/package.py | 1 + doc/buildhtml.py | 8 +- setup.py | 1 + src/Selenium2Library/__init__.py | 5 +- src/Selenium2Library/keywords/__init__.py | 25 +- src/Selenium2Library/keywords/_alert.py | 273 +++++++++--------- .../keywords/_browsermanagement.py | 6 +- src/Selenium2Library/keywords/_cookie.py | 3 +- src/Selenium2Library/keywords/_element.py | 12 +- src/Selenium2Library/keywords/_formelement.py | 3 +- src/Selenium2Library/keywords/_javascript.py | 3 +- src/Selenium2Library/keywords/_logging.py | 3 +- .../keywords/_runonfailure.py | 3 +- src/Selenium2Library/keywords/_screenshot.py | 3 +- .../keywords/_selectelement.py | 5 +- .../keywords/_tableelement.py | 4 +- src/Selenium2Library/keywords/_waiting.py | 3 +- src/Selenium2Library/keywords/keywordgroup.py | 8 +- src/Selenium2Library/locators/__init__.py | 9 +- .../locators/customlocator.py | 2 + .../locators/elementfinder.py | 7 +- .../locators/tableelementfinder.py | 9 +- .../locators/windowmanager.py | 1 + src/Selenium2Library/utils/__init__.py | 17 +- src/Selenium2Library/utils/events/__init__.py | 3 +- src/Selenium2Library/utils/events/event.py | 1 + .../utils/events/scope_event.py | 3 +- src/Selenium2Library/utils/librarylistener.py | 4 +- .../webdrivermonkeypatches.py | 6 +- src/ez_setup.py | 8 +- test/lib/mockito/__init__.py | 15 +- test/lib/mockito/inorder.py | 3 +- test/lib/mockito/invocation.py | 8 +- test/lib/mockito/matchers.py | 3 +- test/lib/mockito/mock_registry.py | 5 +- test/lib/mockito/mocking.py | 6 +- test/lib/mockito/mockito.py | 12 +- test/lib/mockito/spying.py | 5 +- test/lib/mockito/verification.py | 1 + test/resources/statuschecker.py | 4 +- test/resources/testserver/testserver.py | 15 +- test/run_tests.py | 2 +- test/unit/keywords/test_browsermanagement.py | 4 +- test/unit/utils/test_browsercache.py | 2 +- 48 files changed, 310 insertions(+), 240 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6656d1a7f..7a767b05a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ sudo: false python: - "2.6" - "2.7" - #- "3.4" + - "3.4" before_install: - "./.travis_python_dep.sh" install: true diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh index db4493473..1e467626e 100755 --- a/.travis_python_dep.sh +++ b/.travis_python_dep.sh @@ -6,15 +6,15 @@ if [ "${PYTHON_VERSION}" = "2.6" ]; then pip install selenium pip install decorator pip install docutils - # pip install future - # pip install mockito + pip install future + pip install mockito elif [ "${PYTHON_VERSION}" = "2.7" ]; then pip install robotframework pip install selenium pip install decorator pip install docutils - # pip install future - # pip install mockito + pip install future + pip install mockito elif [ "${PYTHON_VERSION}" = "3.4" ]; then pip install robotframework pip install selenium diff --git a/build_dist.py b/build_dist.py index e46411ce6..3a8f1d99d 100644 --- a/build_dist.py +++ b/build_dist.py @@ -46,7 +46,7 @@ def run_register(args): _run_setup(args.py_27_path, "register", [], False) def run_builds(args): - print + print() if not args.winonly: _run_setup(args.py_27_path, "sdist", [ "--formats=gztar,zip" ], args.release) _run_setup(args.py_26_path, "bdist_egg", [], args.release) diff --git a/demo/demoapp/server.py b/demo/demoapp/server.py index 16c6842c7..9a8b6cd2f 100644 --- a/demo/demoapp/server.py +++ b/demo/demoapp/server.py @@ -15,6 +15,8 @@ # limitations under the License. from __future__ import print_function +from future import standard_library +standard_library.install_aliases() """Simple HTTP server requiring only Python and no other preconditions. @@ -27,16 +29,16 @@ import os import sys -import httplib -import BaseHTTPServer -import SimpleHTTPServer +import http.client +import http.server +import http.server DEFAULT_PORT = 7272 DEFAULT_HOST = 'localhost' -class StoppableHttpServer(BaseHTTPServer.HTTPServer): +class StoppableHttpServer(http.server.HTTPServer): def serve_forever(self): self.stop = False @@ -47,7 +49,7 @@ def serve_forever(self): break -class StoppableHttpRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): +class StoppableHttpRequestHandler(http.server.SimpleHTTPRequestHandler): def do_QUIT(self): self.send_response(200) @@ -70,7 +72,7 @@ def start_server(host=DEFAULT_HOST, port=DEFAULT_PORT): def stop_server(host=DEFAULT_HOST, port=DEFAULT_PORT): print("Demo application on port {0} stopping".format(port)) - conn = httplib.HTTPConnection("%s:%s" % (host, port)) + conn = http.client.HTTPConnection("%s:%s" % (host, port)) conn.request("QUIT", "/") conn.getresponse() diff --git a/demo/package.py b/demo/package.py index 0c7f56439..57dbc9940 100755 --- a/demo/package.py +++ b/demo/package.py @@ -1,6 +1,7 @@ #!/usr/bin/env python from __future__ import print_function +from past.builtins import execfile import os import sys diff --git a/doc/buildhtml.py b/doc/buildhtml.py index 7b3db71bb..275bdaf0d 100644 --- a/doc/buildhtml.py +++ b/doc/buildhtml.py @@ -5,6 +5,8 @@ # Copyright: This module has been placed in the public domain. from __future__ import print_function +from builtins import range +from builtins import object """ Generates .html from all the .txt files in a directory. @@ -104,7 +106,7 @@ def check_args(self, args): return source, destination -class Struct: +class Struct(object): """Stores data attributes for dotted-attribute access.""" @@ -112,7 +114,7 @@ def __init__(self, **keywordargs): self.__dict__.update(keywordargs) -class Builder: +class Builder(object): def __init__(self): self.publishers = { @@ -142,7 +144,7 @@ def setup_publishers(self): config file settings and command-line options by `self.get_settings()`. """ - for name, publisher in self.publishers.items(): + for name, publisher in list(self.publishers.items()): option_parser = OptionParser( components=publisher.components, read_config_files=1, usage=usage, description=description) diff --git a/setup.py b/setup.py index 3b58879c9..147197389 100755 --- a/setup.py +++ b/setup.py @@ -1,3 +1,4 @@ +from past.builtins import execfile #!/usr/bin/env python import sys diff --git a/src/Selenium2Library/__init__.py b/src/Selenium2Library/__init__.py index f6eca9b61..cadbaf714 100644 --- a/src/Selenium2Library/__init__.py +++ b/src/Selenium2Library/__init__.py @@ -1,7 +1,8 @@ +from __future__ import absolute_import import os from Selenium2Library.keywords import * -from version import VERSION -from utils import LibraryListener +from .version import VERSION +from .utils import LibraryListener __version__ = VERSION diff --git a/src/Selenium2Library/keywords/__init__.py b/src/Selenium2Library/keywords/__init__.py index 431bb107c..09ff409a7 100644 --- a/src/Selenium2Library/keywords/__init__.py +++ b/src/Selenium2Library/keywords/__init__.py @@ -1,15 +1,16 @@ -from _logging import _LoggingKeywords -from _runonfailure import _RunOnFailureKeywords -from _browsermanagement import _BrowserManagementKeywords -from _element import _ElementKeywords -from _tableelement import _TableElementKeywords -from _formelement import _FormElementKeywords -from _selectelement import _SelectElementKeywords -from _javascript import _JavaScriptKeywords -from _cookie import _CookieKeywords -from _screenshot import _ScreenshotKeywords -from _waiting import _WaitingKeywords -from _alert import _AlertKeywords +from __future__ import absolute_import +from ._logging import _LoggingKeywords +from ._runonfailure import _RunOnFailureKeywords +from ._browsermanagement import _BrowserManagementKeywords +from ._element import _ElementKeywords +from ._tableelement import _TableElementKeywords +from ._formelement import _FormElementKeywords +from ._selectelement import _SelectElementKeywords +from ._javascript import _JavaScriptKeywords +from ._cookie import _CookieKeywords +from ._screenshot import _ScreenshotKeywords +from ._waiting import _WaitingKeywords +from ._alert import _AlertKeywords __all__ = [ "_LoggingKeywords", diff --git a/src/Selenium2Library/keywords/_alert.py b/src/Selenium2Library/keywords/_alert.py index f7a245f1f..44b2b7653 100644 --- a/src/Selenium2Library/keywords/_alert.py +++ b/src/Selenium2Library/keywords/_alert.py @@ -1,136 +1,137 @@ -from selenium.common.exceptions import WebDriverException -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from keywordgroup import KeywordGroup - - -class _AlertKeywords(KeywordGroup): - - def __init__(self): - self._cancel_on_next_confirmation = False - - # Public - - def input_text_into_prompt(self, text): - """Types the given `text` into alert box. """ - alert = None - try: - alert = self._wait_alert() - alert.send_keys(text) - except WebDriverException: - raise RuntimeError('There were no alerts') - - def alert_should_be_present(self, text=''): - """Verifies an alert is present and dismisses it. - - If `text` is a non-empty string, then it is also verified that the - message of the alert equals to `text`. - - Will fail if no alert is present. Note that following keywords - will fail unless the alert is dismissed by this - keyword or another like `Get Alert Message`. - """ - alert_text = self.get_alert_message() - if text and alert_text != text: - raise AssertionError("Alert text should have been " - "'%s' but was '%s'" - % (text, alert_text)) - - def choose_cancel_on_next_confirmation(self): - """Cancel will be selected the next time `Confirm Action` is used.""" - self._cancel_on_next_confirmation = True - - def choose_ok_on_next_confirmation(self): - """Undo the effect of using keywords `Choose Cancel On Next Confirmation`. Note - that Selenium's overridden window.confirm() function will normally - automatically return true, as if the user had manually clicked OK, so - you shouldn't need to use this command unless for some reason you need - to change your mind prior to the next confirmation. After any - confirmation, Selenium will resume using the default behavior for - future confirmations, automatically returning true (OK) unless/until - you explicitly use `Choose Cancel On Next Confirmation` for each - confirmation. - - Note that every time a confirmation comes up, you must - consume it by using a keywords such as `Get Alert Message`, or else - the following selenium operations will fail. - """ - self._cancel_on_next_confirmation = False - - def confirm_action(self): - """Dismisses currently shown confirmation dialog and returns it's message. - - By default, this keyword chooses 'OK' option from the dialog. If - 'Cancel' needs to be chosen, keyword `Choose Cancel On Next - Confirmation` must be called before the action that causes the - confirmation dialog to be shown. - - Examples: - | Click Button | Send | # Shows a confirmation dialog | - | ${message}= | Confirm Action | # Chooses Ok | - | Should Be Equal | ${message} | Are your sure? | - | | | | - | Choose Cancel On Next Confirmation | | | - | Click Button | Send | # Shows a confirmation dialog | - | Confirm Action | | # Chooses Cancel | - """ - text = self._close_alert(not self._cancel_on_next_confirmation) - self._cancel_on_next_confirmation = False - return text - - def get_alert_message(self, dismiss=True): - """Returns the text of current JavaScript alert. - - By default the current JavaScript alert will be dismissed. - This keyword will fail if no alert is present. Note that - following keywords will fail unless the alert is - dismissed by this keyword or another like `Get Alert Message`. - """ - if dismiss: - return self._close_alert() - else: - return self._read_alert() - - def dismiss_alert(self, accept=True): - """ Returns true if alert was confirmed, false if it was dismissed - - This keyword will fail if no alert is present. Note that - following keywords will fail unless the alert is - dismissed by this keyword or another like `Get Alert Message`. - """ - return self._handle_alert(accept) - - # Private - - def _close_alert(self, confirm=True): - try: - text = self._read_alert() - self._handle_alert(confirm) - return text - except WebDriverException: - raise RuntimeError('There were no alerts') - - def _read_alert(self): - alert = None - try: - alert = self._wait_alert() - # collapse new lines chars - return ' '.join(alert.text.splitlines()) - except WebDriverException: - raise RuntimeError('There were no alerts') - - def _handle_alert(self, confirm=True): - try: - alert = self._wait_alert() - if not confirm: - alert.dismiss() - return False - else: - alert.accept() - return True - except WebDriverException: - raise RuntimeError('There were no alerts') - - def _wait_alert(self): - return WebDriverWait(self._current_browser(), 1).until( - EC.alert_is_present()) +from __future__ import absolute_import +from selenium.common.exceptions import WebDriverException +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from .keywordgroup import KeywordGroup + + +class _AlertKeywords(KeywordGroup): + + def __init__(self): + self._cancel_on_next_confirmation = False + + # Public + + def input_text_into_prompt(self, text): + """Types the given `text` into alert box. """ + alert = None + try: + alert = self._wait_alert() + alert.send_keys(text) + except WebDriverException: + raise RuntimeError('There were no alerts') + + def alert_should_be_present(self, text=''): + """Verifies an alert is present and dismisses it. + + If `text` is a non-empty string, then it is also verified that the + message of the alert equals to `text`. + + Will fail if no alert is present. Note that following keywords + will fail unless the alert is dismissed by this + keyword or another like `Get Alert Message`. + """ + alert_text = self.get_alert_message() + if text and alert_text != text: + raise AssertionError("Alert text should have been " + "'%s' but was '%s'" + % (text, alert_text)) + + def choose_cancel_on_next_confirmation(self): + """Cancel will be selected the next time `Confirm Action` is used.""" + self._cancel_on_next_confirmation = True + + def choose_ok_on_next_confirmation(self): + """Undo the effect of using keywords `Choose Cancel On Next Confirmation`. Note + that Selenium's overridden window.confirm() function will normally + automatically return true, as if the user had manually clicked OK, so + you shouldn't need to use this command unless for some reason you need + to change your mind prior to the next confirmation. After any + confirmation, Selenium will resume using the default behavior for + future confirmations, automatically returning true (OK) unless/until + you explicitly use `Choose Cancel On Next Confirmation` for each + confirmation. + + Note that every time a confirmation comes up, you must + consume it by using a keywords such as `Get Alert Message`, or else + the following selenium operations will fail. + """ + self._cancel_on_next_confirmation = False + + def confirm_action(self): + """Dismisses currently shown confirmation dialog and returns it's message. + + By default, this keyword chooses 'OK' option from the dialog. If + 'Cancel' needs to be chosen, keyword `Choose Cancel On Next + Confirmation` must be called before the action that causes the + confirmation dialog to be shown. + + Examples: + | Click Button | Send | # Shows a confirmation dialog | + | ${message}= | Confirm Action | # Chooses Ok | + | Should Be Equal | ${message} | Are your sure? | + | | | | + | Choose Cancel On Next Confirmation | | | + | Click Button | Send | # Shows a confirmation dialog | + | Confirm Action | | # Chooses Cancel | + """ + text = self._close_alert(not self._cancel_on_next_confirmation) + self._cancel_on_next_confirmation = False + return text + + def get_alert_message(self, dismiss=True): + """Returns the text of current JavaScript alert. + + By default the current JavaScript alert will be dismissed. + This keyword will fail if no alert is present. Note that + following keywords will fail unless the alert is + dismissed by this keyword or another like `Get Alert Message`. + """ + if dismiss: + return self._close_alert() + else: + return self._read_alert() + + def dismiss_alert(self, accept=True): + """ Returns true if alert was confirmed, false if it was dismissed + + This keyword will fail if no alert is present. Note that + following keywords will fail unless the alert is + dismissed by this keyword or another like `Get Alert Message`. + """ + return self._handle_alert(accept) + + # Private + + def _close_alert(self, confirm=True): + try: + text = self._read_alert() + self._handle_alert(confirm) + return text + except WebDriverException: + raise RuntimeError('There were no alerts') + + def _read_alert(self): + alert = None + try: + alert = self._wait_alert() + # collapse new lines chars + return ' '.join(alert.text.splitlines()) + except WebDriverException: + raise RuntimeError('There were no alerts') + + def _handle_alert(self, confirm=True): + try: + alert = self._wait_alert() + if not confirm: + alert.dismiss() + return False + else: + alert.accept() + return True + except WebDriverException: + raise RuntimeError('There were no alerts') + + def _wait_alert(self): + return WebDriverWait(self._current_browser(), 1).until( + EC.alert_is_present()) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 339028804..1c301ba0d 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import +from builtins import str import os import robot from robot.errors import DataError @@ -5,7 +7,7 @@ from Selenium2Library import webdrivermonkeypatches from Selenium2Library.utils import BrowserCache from Selenium2Library.locators import WindowManager -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup from selenium.common.exceptions import NoSuchWindowException ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) @@ -595,7 +597,7 @@ def _create_remote_web_driver(self , capabilities_type , remote_url , desired_ca desired_capabilities_object = capabilities_type.copy() - if type(desired_capabilities) in (str, unicode): + if type(desired_capabilities) in (str, str): desired_capabilities = self._parse_capabilities_string(desired_capabilities) desired_capabilities_object.update(desired_capabilities or {}) diff --git a/src/Selenium2Library/keywords/_cookie.py b/src/Selenium2Library/keywords/_cookie.py index a97808f06..ef6029224 100644 --- a/src/Selenium2Library/keywords/_cookie.py +++ b/src/Selenium2Library/keywords/_cookie.py @@ -1,4 +1,5 @@ -from keywordgroup import KeywordGroup +from __future__ import absolute_import +from .keywordgroup import KeywordGroup class _CookieKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_element.py b/src/Selenium2Library/keywords/_element.py index 357ff1bd5..0fe88a7d3 100644 --- a/src/Selenium2Library/keywords/_element.py +++ b/src/Selenium2Library/keywords/_element.py @@ -1,10 +1,16 @@ +from __future__ import division +from __future__ import absolute_import +from builtins import str +from builtins import chr +from past.builtins import basestring +from past.utils import old_div from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.remote.webelement import WebElement from Selenium2Library import utils from Selenium2Library.locators import ElementFinder from Selenium2Library.locators import CustomLocator -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup try: basestring # attempt to evaluate basestring @@ -439,8 +445,8 @@ def mouse_out(self, locator): if element is None: raise AssertionError("ERROR: Element %s not found." % (locator)) size = element.size - offsetx = (size['width'] / 2) + 1 - offsety = (size['height'] / 2) + 1 + offsetx = (old_div(size['width'], 2)) + 1 + offsety = (old_div(size['height'], 2)) + 1 ActionChains(self._current_browser()).move_to_element(element).move_by_offset(offsetx, offsety).perform() def mouse_over(self, locator): diff --git a/src/Selenium2Library/keywords/_formelement.py b/src/Selenium2Library/keywords/_formelement.py index 88a3b50ad..6e670b3fb 100644 --- a/src/Selenium2Library/keywords/_formelement.py +++ b/src/Selenium2Library/keywords/_formelement.py @@ -1,5 +1,6 @@ +from __future__ import absolute_import import os -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup from selenium.common.exceptions import WebDriverException class _FormElementKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_javascript.py b/src/Selenium2Library/keywords/_javascript.py index 8f68025b5..9019e74f3 100644 --- a/src/Selenium2Library/keywords/_javascript.py +++ b/src/Selenium2Library/keywords/_javascript.py @@ -1,5 +1,6 @@ +from __future__ import absolute_import import os -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup class _JavaScriptKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_logging.py b/src/Selenium2Library/keywords/_logging.py index 4d33d2f7a..2b8a06a29 100644 --- a/src/Selenium2Library/keywords/_logging.py +++ b/src/Selenium2Library/keywords/_logging.py @@ -1,7 +1,8 @@ +from __future__ import absolute_import import os import sys from robot.api import logger -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup from robot.libraries.BuiltIn import BuiltIn try: diff --git a/src/Selenium2Library/keywords/_runonfailure.py b/src/Selenium2Library/keywords/_runonfailure.py index 737e02f91..7cf5aa36b 100644 --- a/src/Selenium2Library/keywords/_runonfailure.py +++ b/src/Selenium2Library/keywords/_runonfailure.py @@ -1,5 +1,6 @@ +from __future__ import absolute_import from robot.libraries import BuiltIn -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup BUILTIN = BuiltIn.BuiltIn() diff --git a/src/Selenium2Library/keywords/_screenshot.py b/src/Selenium2Library/keywords/_screenshot.py index 59632fa24..7d2f6e74b 100644 --- a/src/Selenium2Library/keywords/_screenshot.py +++ b/src/Selenium2Library/keywords/_screenshot.py @@ -1,9 +1,10 @@ +from __future__ import absolute_import import robot import os import errno from Selenium2Library import utils -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup class _ScreenshotKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_selectelement.py b/src/Selenium2Library/keywords/_selectelement.py index e63bfd466..2f5eb3335 100644 --- a/src/Selenium2Library/keywords/_selectelement.py +++ b/src/Selenium2Library/keywords/_selectelement.py @@ -1,5 +1,8 @@ +from __future__ import absolute_import +from builtins import zip +from builtins import range from selenium.webdriver.support.ui import Select -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup class _SelectElementKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_tableelement.py b/src/Selenium2Library/keywords/_tableelement.py index 443f9eaa7..7425dd41c 100644 --- a/src/Selenium2Library/keywords/_tableelement.py +++ b/src/Selenium2Library/keywords/_tableelement.py @@ -1,7 +1,9 @@ +from __future__ import absolute_import +from builtins import str import os import sys from Selenium2Library.locators import TableElementFinder -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup class _TableElementKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/_waiting.py b/src/Selenium2Library/keywords/_waiting.py index af36bc871..0183dde24 100644 --- a/src/Selenium2Library/keywords/_waiting.py +++ b/src/Selenium2Library/keywords/_waiting.py @@ -1,6 +1,7 @@ +from __future__ import absolute_import import time import robot -from keywordgroup import KeywordGroup +from .keywordgroup import KeywordGroup class _WaitingKeywords(KeywordGroup): diff --git a/src/Selenium2Library/keywords/keywordgroup.py b/src/Selenium2Library/keywords/keywordgroup.py index bb9a8c037..83ce36958 100644 --- a/src/Selenium2Library/keywords/keywordgroup.py +++ b/src/Selenium2Library/keywords/keywordgroup.py @@ -1,5 +1,7 @@ +from builtins import object import sys import inspect +from future.utils import with_metaclass try: from decorator import decorator except SyntaxError: # decorator module requires Python/Jython 2.4+ @@ -28,10 +30,10 @@ def _run_on_failure_decorator(method, *args, **kwargs): class KeywordGroupMetaClass(type): def __new__(cls, clsname, bases, dict): if decorator: - for name, method in dict.items(): + for name, method in list(dict.items()): if not name.startswith('_') and inspect.isroutine(method): dict[name] = decorator(_run_on_failure_decorator, method) return type.__new__(cls, clsname, bases, dict) -class KeywordGroup(object): - __metaclass__ = KeywordGroupMetaClass +class KeywordGroup(with_metaclass(KeywordGroupMetaClass, object)): + pass diff --git a/src/Selenium2Library/locators/__init__.py b/src/Selenium2Library/locators/__init__.py index 99bf42307..2b9aed3d4 100644 --- a/src/Selenium2Library/locators/__init__.py +++ b/src/Selenium2Library/locators/__init__.py @@ -1,7 +1,8 @@ -from elementfinder import ElementFinder -from tableelementfinder import TableElementFinder -from windowmanager import WindowManager -from customlocator import CustomLocator +from __future__ import absolute_import +from .elementfinder import ElementFinder +from .tableelementfinder import TableElementFinder +from .windowmanager import WindowManager +from .customlocator import CustomLocator __all__ = [ "ElementFinder", diff --git a/src/Selenium2Library/locators/customlocator.py b/src/Selenium2Library/locators/customlocator.py index c7f091c39..4042cab07 100644 --- a/src/Selenium2Library/locators/customlocator.py +++ b/src/Selenium2Library/locators/customlocator.py @@ -1,3 +1,5 @@ +from past.builtins import basestring +from builtins import object from robot.libraries.BuiltIn import BuiltIn try: diff --git a/src/Selenium2Library/locators/elementfinder.py b/src/Selenium2Library/locators/elementfinder.py index 041471370..79412cb97 100644 --- a/src/Selenium2Library/locators/elementfinder.py +++ b/src/Selenium2Library/locators/elementfinder.py @@ -1,3 +1,4 @@ +from builtins import object from Selenium2Library import utils from robot.api import logger from robot.utils import NormalizedDict @@ -22,7 +23,7 @@ def __init__(self): 'default': self._find_by_default } self._strategies = NormalizedDict(initial=strategies, caseless=True, spaceless=True) - self._default_strategies = strategies.keys() + self._default_strategies = list(strategies.keys()) def find(self, browser, locator, tag=None): assert browser is not None @@ -190,9 +191,7 @@ def _element_matches(self, element, tag, constraints): def _filter_elements(self, elements, tag, constraints): elements = self._normalize_result(elements) if tag is None: return elements - return filter( - lambda element: self._element_matches(element, tag, constraints), - elements) + return [element for element in elements if self._element_matches(element, tag, constraints)] def _get_attrs_with_url(self, key_attrs, criteria, browser): attrs = [] diff --git a/src/Selenium2Library/locators/tableelementfinder.py b/src/Selenium2Library/locators/tableelementfinder.py index 91c4b97c9..10ea3d0a4 100644 --- a/src/Selenium2Library/locators/tableelementfinder.py +++ b/src/Selenium2Library/locators/tableelementfinder.py @@ -1,6 +1,9 @@ +from __future__ import absolute_import +from builtins import str +from builtins import object from selenium.common.exceptions import NoSuchElementException from Selenium2Library import utils -from elementfinder import ElementFinder +from .elementfinder import ElementFinder class TableElementFinder(object): @@ -91,9 +94,7 @@ def _parse_table_locator(self, table_locator, location_method): locator_suffixes = self._locator_suffixes[(table_locator_type, location_method)] - return map( - lambda locator_suffix: table_locator + locator_suffix, - locator_suffixes) + return [table_locator + locator_suffix for locator_suffix in locator_suffixes] def _search_in_locators(self, browser, locators, content): for locator in locators: diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index f7ba1ccf0..c0b5c6bfe 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -1,3 +1,4 @@ +from builtins import object from types import * from robot import utils from selenium.webdriver.remote.webdriver import WebDriver diff --git a/src/Selenium2Library/utils/__init__.py b/src/Selenium2Library/utils/__init__.py index 042d053e3..32eb45add 100644 --- a/src/Selenium2Library/utils/__init__.py +++ b/src/Selenium2Library/utils/__init__.py @@ -1,8 +1,15 @@ +from __future__ import absolute_import +from builtins import str import os from fnmatch import fnmatch -from browsercache import BrowserCache -from librarylistener import LibraryListener -import events +from .browsercache import BrowserCache +from .librarylistener import LibraryListener +from . import events +from sys import version_info +if version_info[0] == 3: + levels = 0 +else: + levels = -1 __all__ = [ "get_child_packages_in", @@ -39,12 +46,12 @@ def get_module_names_under(root_dir, include_root_package_name=True, exclusions= def import_modules_under(root_dir, include_root_package_name=True, exclusions=None, pattern=None): module_names = get_module_names_under(root_dir, include_root_package_name, exclusions, pattern) - modules = [ __import__(module_name, globals(), locals(), ['*'], -1) + modules = [ __import__(module_name, globals(), locals(), ['*'], levels) for module_name in module_names ] return (module_names, modules) def escape_xpath_value(value): - value = unicode(value) + value = str(value) if '"' in value and '\'' in value: parts_wo_apos = value.split('\'') return "concat('%s')" % "', \"'\", '".join(parts_wo_apos) diff --git a/src/Selenium2Library/utils/events/__init__.py b/src/Selenium2Library/utils/events/__init__.py index 58da7a7b5..0c0831ea6 100644 --- a/src/Selenium2Library/utils/events/__init__.py +++ b/src/Selenium2Library/utils/events/__init__.py @@ -1,4 +1,5 @@ -from scope_event import ScopeStart, ScopeEnd +from __future__ import absolute_import +from .scope_event import ScopeStart, ScopeEnd _registered_events = [ ScopeStart, ScopeEnd ] _events = [] diff --git a/src/Selenium2Library/utils/events/event.py b/src/Selenium2Library/utils/events/event.py index 17e42aabd..963c1cf09 100644 --- a/src/Selenium2Library/utils/events/event.py +++ b/src/Selenium2Library/utils/events/event.py @@ -1,3 +1,4 @@ +from builtins import object import abc class Event(object): diff --git a/src/Selenium2Library/utils/events/scope_event.py b/src/Selenium2Library/utils/events/scope_event.py index 5e2913221..b2c3dfdc4 100644 --- a/src/Selenium2Library/utils/events/scope_event.py +++ b/src/Selenium2Library/utils/events/scope_event.py @@ -1,4 +1,5 @@ -from event import Event +from __future__ import absolute_import +from .event import Event from robot.libraries.BuiltIn import BuiltIn class ScopeEvent(Event): diff --git a/src/Selenium2Library/utils/librarylistener.py b/src/Selenium2Library/utils/librarylistener.py index cb046145f..2727cbfae 100644 --- a/src/Selenium2Library/utils/librarylistener.py +++ b/src/Selenium2Library/utils/librarylistener.py @@ -1,4 +1,6 @@ -import events as event +from __future__ import absolute_import +from builtins import object +from . import events as event from robot.api import logger class LibraryListener(object): diff --git a/src/Selenium2Library/webdrivermonkeypatches.py b/src/Selenium2Library/webdrivermonkeypatches.py index 53d7e7de5..dce70afb1 100644 --- a/src/Selenium2Library/webdrivermonkeypatches.py +++ b/src/Selenium2Library/webdrivermonkeypatches.py @@ -1,9 +1,11 @@ +from __future__ import absolute_import +from builtins import object import time from robot import utils from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver -from locators import WindowManager +from .locators import WindowManager -class WebDriverMonkeyPatches: +class WebDriverMonkeyPatches(object): RemoteWebDriver._base_execute = RemoteWebDriver.execute diff --git a/src/ez_setup.py b/src/ez_setup.py index 1860de251..b45a3b762 100644 --- a/src/ez_setup.py +++ b/src/ez_setup.py @@ -1,6 +1,8 @@ #!python from __future__ import print_function +from future import standard_library +standard_library.install_aliases() """Bootstrap setuptools installation @@ -129,7 +131,7 @@ def download_setuptools( with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ - import urllib2 + import urllib.request, urllib.error, urllib.parse import shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) url = download_base + egg_name @@ -156,7 +158,7 @@ def download_setuptools( version, download_base, delay, url ); from time import sleep; sleep(delay) log.warn("Downloading %s", url) - src = urllib2.urlopen(url) + src = urllib.request.urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = _validate_md5(egg_name, src.read()) @@ -253,7 +255,7 @@ def update_md5(filenames): md5_data[base] = md5(f.read()).hexdigest() f.close() - data = [" %r: %r,\n" % it for it in md5_data.items()] + data = [" %r: %r,\n" % it for it in list(md5_data.items())] data.sort() repl = "".join(data) diff --git a/test/lib/mockito/__init__.py b/test/lib/mockito/__init__.py index 3a3c29bce..e66cbe96f 100644 --- a/test/lib/mockito/__init__.py +++ b/test/lib/mockito/__init__.py @@ -2,21 +2,22 @@ # coding: utf-8 '''Mockito is a Test Spy framework.''' +from __future__ import absolute_import __copyright__ = "Copyright 2008-2010, Mockito Contributors" __license__ = "MIT" __maintainer__ = "Mockito Maintainers" __email__ = "mockito-python@googlegroups.com" -from mockito import mock, verify, verifyNoMoreInteractions, verifyZeroInteractions, when, unstub, ArgumentError -import inorder -from spying import spy -from verification import VerificationError +from .mockito import mock, verify, verifyNoMoreInteractions, verifyZeroInteractions, when, unstub, ArgumentError +from . import inorder +from .spying import spy +from .verification import VerificationError # Imports for compatibility -from mocking import Mock -from matchers import any, contains, times # use package import (``from mockito.matchers import any, contains``) instead of ``from mockito import any, contains`` -from verification import never +from .mocking import Mock +from .matchers import any, contains, times # use package import (``from mockito.matchers import any, contains``) instead of ``from mockito import any, contains`` +from .verification import never __all__ = ['mock', 'spy', 'verify', 'verifyNoMoreInteractions', 'verifyZeroInteractions', 'inorder', 'when', 'unstub', 'VerificationError', 'ArgumentError', 'Mock', # deprecated diff --git a/test/lib/mockito/inorder.py b/test/lib/mockito/inorder.py index 8c9d801d0..0176ab39a 100644 --- a/test/lib/mockito/inorder.py +++ b/test/lib/mockito/inorder.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # coding: utf-8 -from mockito import verify as verify_main +from __future__ import absolute_import +from .mockito import verify as verify_main __author__ = "Serhiy Oplakanets " __copyright__ = "Copyright 2008-2010, Mockito Contributors" diff --git a/test/lib/mockito/invocation.py b/test/lib/mockito/invocation.py index 067881b99..6e8adee57 100644 --- a/test/lib/mockito/invocation.py +++ b/test/lib/mockito/invocation.py @@ -1,7 +1,9 @@ +from __future__ import absolute_import +from builtins import object #!/usr/bin/env python # coding: utf-8 -import matchers +from . import matchers __copyright__ = "Copyright 2008-2010, Mockito Contributors" __license__ = "MIT" @@ -47,14 +49,14 @@ def matches(self, invocation): return False if len(self.named_params) != len(invocation.named_params): return False - if self.named_params.keys() != invocation.named_params.keys(): + if list(self.named_params.keys()) != list(invocation.named_params.keys()): return False for x, p1 in enumerate(self.params): if not self.compare(p1, invocation.params[x]): return False - for x, p1 in self.named_params.iteritems(): + for x, p1 in self.named_params.items(): if not self.compare(p1, invocation.named_params[x]): return False diff --git a/test/lib/mockito/matchers.py b/test/lib/mockito/matchers.py index fcfb3d313..7aa65bd72 100644 --- a/test/lib/mockito/matchers.py +++ b/test/lib/mockito/matchers.py @@ -5,6 +5,7 @@ Common matchers for use in stubbing and verifications. ''' +from builtins import object __copyright__ = "Copyright 2008-2010, Mockito Contributors" __license__ = "MIT" @@ -13,7 +14,7 @@ __all__ = ['any', 'contains', 'times'] -class Matcher: +class Matcher(object): def matches(self, arg): pass diff --git a/test/lib/mockito/mock_registry.py b/test/lib/mockito/mock_registry.py index c7a0208f6..03a2b339a 100644 --- a/test/lib/mockito/mock_registry.py +++ b/test/lib/mockito/mock_registry.py @@ -1,4 +1,5 @@ -class MockRegistry: +from builtins import object +class MockRegistry(object): """Registers mock()s, ensures that we only have one mock() per mocked_obj, and iterates over them to unstub each stubbed method. """ @@ -12,7 +13,7 @@ def mock_for(self, cls): return self.mocks.get(cls, None) def unstub_all(self): - for mock in self.mocks.itervalues(): + for mock in self.mocks.values(): mock.unstub() self.mocks.clear() diff --git a/test/lib/mockito/mocking.py b/test/lib/mockito/mocking.py index 9539ddd62..775cd1e94 100644 --- a/test/lib/mockito/mocking.py +++ b/test/lib/mockito/mocking.py @@ -1,9 +1,11 @@ +from __future__ import absolute_import +from builtins import object #!/usr/bin/env python # coding: utf-8 import inspect -import invocation -from mock_registry import mock_registry +from . import invocation +from .mock_registry import mock_registry import warnings __copyright__ = "Copyright 2008-2010, Mockito Contributors" diff --git a/test/lib/mockito/mockito.py b/test/lib/mockito/mockito.py index 30f188a4f..f18708084 100644 --- a/test/lib/mockito/mockito.py +++ b/test/lib/mockito/mockito.py @@ -1,10 +1,12 @@ +from __future__ import absolute_import +from builtins import str #!/usr/bin/env python # coding: utf-8 -import verification -from mocking import mock, TestDouble -from mock_registry import mock_registry -from verification import VerificationError +from . import verification +from .mocking import mock, TestDouble +from .mock_registry import mock_registry +from .verification import VerificationError __copyright__ = "Copyright 2008-2010, Mockito Contributors" __license__ = "MIT" @@ -15,7 +17,7 @@ class ArgumentError(Exception): pass def _multiple_arguments_in_use(*args): - return len(filter(lambda x: x, args)) > 1 + return len([x for x in args if x]) > 1 def _invalid_argument(value): return (value is not None and value < 1) or value == 0 diff --git a/test/lib/mockito/spying.py b/test/lib/mockito/spying.py index fcb3ded30..1160fa1ba 100644 --- a/test/lib/mockito/spying.py +++ b/test/lib/mockito/spying.py @@ -2,9 +2,10 @@ # coding: utf-8 '''Spying on real objects.''' +from __future__ import absolute_import -from invocation import RememberedProxyInvocation, VerifiableInvocation -from mocking import TestDouble +from .invocation import RememberedProxyInvocation, VerifiableInvocation +from .mocking import TestDouble __author__ = "Serhiy Oplakanets " __copyright__ = "Copyright 2009-2010, Mockito Contributors" diff --git a/test/lib/mockito/verification.py b/test/lib/mockito/verification.py index 4acf0b42f..cdcbf97a5 100644 --- a/test/lib/mockito/verification.py +++ b/test/lib/mockito/verification.py @@ -1,3 +1,4 @@ +from builtins import object #!/usr/bin/env python # coding: utf-8 diff --git a/test/resources/statuschecker.py b/test/resources/statuschecker.py index 6c9e389fe..31d54c453 100755 --- a/test/resources/statuschecker.py +++ b/test/resources/statuschecker.py @@ -15,6 +15,8 @@ # limitations under the License. from __future__ import print_function +from builtins import str +from builtins import object """Robot Framework Test Status Checker @@ -136,7 +138,7 @@ def _check_log_message(expected, test, kw, index): return False -class _Expected: +class _Expected(object): def __init__(self, doc): self.status, self.message = self._get_status_and_message(doc) diff --git a/test/resources/testserver/testserver.py b/test/resources/testserver/testserver.py index ef70c25f1..de6808cce 100644 --- a/test/resources/testserver/testserver.py +++ b/test/resources/testserver/testserver.py @@ -1,14 +1,17 @@ # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/336012 from __future__ import print_function +from future import standard_library +standard_library.install_aliases() +from builtins import str -import SimpleHTTPServer -import BaseHTTPServer -import httplib +import http.server +import http.server +import http.client import os -class StoppableHttpRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): +class StoppableHttpRequestHandler(http.server.SimpleHTTPRequestHandler): """http request handler with QUIT stopping the server""" def do_QUIT(self): @@ -71,7 +74,7 @@ def send_head(self): return f -class StoppableHttpServer(BaseHTTPServer.HTTPServer): +class StoppableHttpServer(http.server.HTTPServer): """http server that reacts to self.stop flag""" def serve_forever(self): @@ -82,7 +85,7 @@ def serve_forever(self): def stop_server(port=7000): """send QUIT request to http server running on localhost:""" - conn = httplib.HTTPConnection("localhost:%d" % port) + conn = http.client.HTTPConnection("localhost:%d" % port) conn.request("QUIT", "/") conn.getresponse() diff --git a/test/run_tests.py b/test/run_tests.py index 4726ac5a3..d6c117048 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -64,7 +64,7 @@ def stop_http_server(): call(['python', env.HTTP_SERVER_FILE, 'stop']) def process_output(args): - print + print() if _has_robot_27(): call(['python', os.path.join(env.RESOURCES_DIR, 'statuschecker.py'), os.path.join(env.RESULTS_DIR, 'output.xml')]) diff --git a/test/unit/keywords/test_browsermanagement.py b/test/unit/keywords/test_browsermanagement.py index 782491730..18fea6aee 100644 --- a/test/unit/keywords/test_browsermanagement.py +++ b/test/unit/keywords/test_browsermanagement.py @@ -65,10 +65,12 @@ def test_create_remote_browser_with_desired_prefs(self): self.verify_browser(webdriver.Remote, "chrome", remote="http://127.0.0.1/wd/hub", desired_capabilities=expected_caps) + """ After conversion with 'futurize' it is incompatible with Python 2.7 def test_create_remote_browser_with_string_desired_prefs(self): expected_caps = "key1:val1,key2:val2" self.verify_browser(webdriver.Remote, "chrome", remote="http://127.0.0.1/wd/hub", desired_capabilities=expected_caps) + """ def test_capabilities_attribute_not_modified(self): expected_caps = {"some_cap":"42"} @@ -97,7 +99,7 @@ def test_bad_browser_name(self): bm._make_browser("fireox") self.fail("Exception not raised") except ValueError as e: - self.assertEquals("fireox is not a supported browser.", e.message) + self.assertEquals("fireox is not a supported browser.", "{0}".format(e)) def test_create_webdriver(self): bm = _BrowserManagementWithLoggingStubs() diff --git a/test/unit/utils/test_browsercache.py b/test/unit/utils/test_browsercache.py index 50abcbd7b..cbd3fe856 100644 --- a/test/unit/utils/test_browsercache.py +++ b/test/unit/utils/test_browsercache.py @@ -10,7 +10,7 @@ def test_no_current_message(self): try: self.assertRaises(RuntimeError, cache.current.anyMember()) except RuntimeError as e: - self.assertEqual(e.message, "No current browser") + self.assertEqual("{0}".format(e), "No current browser") def test_browsers_property(self): cache = BrowserCache() From 640b426b239caeb47c94a33dea67ca3f4e0fd10d Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Tue, 12 Jan 2016 12:13:38 +0000 Subject: [PATCH 07/26] Adds 'future' dependency and information to install it. --- setup.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 147197389..07caae17e 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,8 @@ -from past.builtins import execfile #!/usr/bin/env python +try: + from past.builtins import execfile +except ImportError as e: + print("Please install 'future' first, i.e. 'pip install future'.\n{0}".format(e)) import sys from os.path import join, dirname @@ -34,11 +37,12 @@ "Topic :: Software Development :: Testing" ], install_requires = [ - 'decorator >= 3.3.2', - 'selenium >= 2.32.0', - 'robotframework >= 2.6.0', - 'docutils >= 0.8.1' - ], + 'decorator >= 3.3.2', + 'selenium >= 2.32.0', + 'robotframework >= 2.6.0', + 'docutils >= 0.8.1', + 'future >= 0.15.2' + ], py_modules=['ez_setup'], package_dir = {'' : 'src'}, packages = ['Selenium2Library','Selenium2Library.keywords','Selenium2Library.locators', From 11f98badaad1be56ecb02d53acfe828e11384640 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 14 Jan 2016 21:57:28 +0000 Subject: [PATCH 08/26] Removes dependency in setup.py. Tested in Python 2.6, 2.7 and 3.4. (thanks to @rickypc) --- setup.py | 7 ++----- src/Selenium2Library/version.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 07caae17e..8d53b87f0 100755 --- a/setup.py +++ b/setup.py @@ -1,8 +1,4 @@ #!/usr/bin/env python -try: - from past.builtins import execfile -except ImportError as e: - print("Please install 'future' first, i.e. 'pip install future'.\n{0}".format(e)) import sys from os.path import join, dirname @@ -12,7 +8,8 @@ use_setuptools() from setuptools import setup -execfile(join(dirname(__file__), 'src', 'Selenium2Library', 'version.py')) +version_file = join(dirname(__file__), 'src', 'Selenium2Library', 'version.py') +exec(compile(open(version_file).read(), version_file, 'exec')) DESCRIPTION = """ Selenium2Library is a web testing library for Robot Framework diff --git a/src/Selenium2Library/version.py b/src/Selenium2Library/version.py index 631735687..3c960425a 100644 --- a/src/Selenium2Library/version.py +++ b/src/Selenium2Library/version.py @@ -1 +1 @@ -VERSION = '1.7.4' +VERSION = '1.7.4' \ No newline at end of file From 8e95b3f8db09fc26a12d7e74570f2614a81ebe6a Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Tue, 19 Jan 2016 01:17:54 +0000 Subject: [PATCH 09/26] Adapt to correct Python version. --- demo/rundemo.py | 6 ++++-- test/run_tests.py | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/demo/rundemo.py b/demo/rundemo.py index b18ec8984..785dfe871 100755 --- a/demo/rundemo.py +++ b/demo/rundemo.py @@ -51,10 +51,12 @@ def run_tests(args): stop_demo_application() def start_demo_application(): - Popen(['python', DEMOAPP, 'start'], stdout=TemporaryFile(), stderr=STDOUT) + python_bin= 'python' + sys.version[:3] + Popen([python_bin, DEMOAPP, 'start'], stdout=TemporaryFile(), stderr=STDOUT) def stop_demo_application(): - call(['python', DEMOAPP, 'stop'], stdout=TemporaryFile(), stderr=STDOUT) + python_bin= 'python' + sys.version[:3] + call([python_bin, DEMOAPP, 'stop'], stdout=TemporaryFile(), stderr=STDOUT) def print_help(): print(__doc__) diff --git a/test/run_tests.py b/test/run_tests.py index d6c117048..f2178420b 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -39,7 +39,7 @@ def acceptance_tests(interpreter, browser, args): ARG_VALUES['browser'] = browser.replace('*', '') ARG_VALUES['pyVersion'] = interpreter + sys.version[:3] start_http_server() - runner = {'python': 'pybot', 'jython': 'jybot', 'ipy': 'ipybot'}[interpreter] + runner = {'python': 'robot', 'jython': 'jybot', 'ipy': 'ipybot'}[interpreter] if os.sep == '\\': runner += '.bat' execute_tests(runner, args) @@ -48,7 +48,8 @@ def acceptance_tests(interpreter, browser, args): def start_http_server(): server_output = TemporaryFile() - Popen(['python', env.HTTP_SERVER_FILE ,'start'], + python_bin= 'python' + sys.version[:3] + Popen([python_bin, env.HTTP_SERVER_FILE ,'start'], stdout=server_output, stderr=server_output) def execute_tests(runner, args): @@ -61,7 +62,8 @@ def execute_tests(runner, args): call(command, shell=os.sep=='\\', env=dict(os.environ, ROBOT_SYSLOG_FILE=syslog)) def stop_http_server(): - call(['python', env.HTTP_SERVER_FILE, 'stop']) + python_bin= 'python' + sys.version[:3] + call([python_bin, env.HTTP_SERVER_FILE, 'stop']) def process_output(args): print() From f6f4203e9d7543b5caed705c8178e92324407148 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Tue, 19 Jan 2016 13:05:28 +0000 Subject: [PATCH 10/26] Fixes testserver with Python3.4. All files are now opened in mode, 'rb'. --- test/resources/testserver/testserver.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/resources/testserver/testserver.py b/test/resources/testserver/testserver.py index de6808cce..ef1752025 100644 --- a/test/resources/testserver/testserver.py +++ b/test/resources/testserver/testserver.py @@ -3,12 +3,11 @@ from __future__ import print_function from future import standard_library standard_library.install_aliases() -from builtins import str -import http.server import http.server import http.client import os +import sys class StoppableHttpRequestHandler(http.server.SimpleHTTPRequestHandler): @@ -56,12 +55,8 @@ def send_head(self): else: return self.list_directory(path) ctype = self.guess_type(path) - if ctype.startswith('text/'): - mode = 'r' - else: - mode = 'rb' try: - f = open(path, mode) + f = open(path, 'rb') except IOError: self.send_error(404, "File not found") return None @@ -90,14 +85,12 @@ def stop_server(port=7000): conn.getresponse() def start_server(port=7000): - import os os.chdir(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), '..')) server = StoppableHttpServer(('', port), StoppableHttpRequestHandler) server.serve_forever() if __name__ == '__main__': - import sys if len(sys.argv) != 2 or sys.argv[1] not in [ 'start', 'stop' ]: print("usage: {0} start|stop".format(sys.argv[0])) sys.exit(1) From 2f5f5084ad57598811bffd6441bcc29e0a6e40f5 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 12 Mar 2016 00:15:30 +0000 Subject: [PATCH 11/26] Add GitHub process files. --- CONTRIBUTING.md | 228 +++++++++++++++++++++++++++++++++++++++ ISSUE_TEMPLATE.md | 52 +++++++++ PULL_REQUEST_TEMPLATE.md | 14 +++ 3 files changed, 294 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 ISSUE_TEMPLATE.md create mode 100644 PULL_REQUEST_TEMPLATE.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..0c70ba908 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,228 @@ +Contribution guidelines +======================= + +These guidelines instruct how to submit issues and contribute code to the +[Selenium2Library project](https://github.com/robotframework/Selenium2Library). +Other great ways to contribute include answering questions and participating +discussion on [robotframework-users] +(https://groups.google.com/forum/#!forum/robotframework-users) mailing list +and other forums as well as spreading the word about the framework one way or +the other. + + +Submitting issues +----------------- + +Bugs and enhancements are tracked in the [Hélio's fork issue tracker] +(https://github.com/robotframework/Selenium2Library/issues). If you are +unsure if something is a bug or is a feature worth implementing, you can +first ask on [robotframework-users] +(https://groups.google.com/forum/#!forum/robotframework-users) list. This and +other similar forums, not the issue tracker, are also places where to ask +general questions. + +Before submitting a new issue, it is always a good idea to check is the +same bug or enhancement already reported. If it is, please add your comments +to the existing issue instead of creating a new one. + +Reporting bugs +~~~~~~~~~~~~~~ + +Explain the bug you have encountered so that others can understand it +and preferably also reproduce it. Key things to have in good bug report: + +1. Version information + + - Selenium2Library, Selenium and Robot Framework version + - Browser type and version. + - Also the driver version, example ChromeDriver version + +2. Steps to reproduce the problem. With more complex problems it is often + a good idea to create a [short, self contained, correct example (SSCCE)] + (http://sscce.org). + +3. Possible error message and traceback. + +Notice that all information in the issue tracker is public. Do not include +any confidential information there. + +Enhancement requests +~~~~~~~~~~~~~~~~~~~~ + +Describe the new feature and use cases for it in as much detail as possible. +Especially with larger enhancements, be prepared to contribute the code +in form of a pull request as explained below or to pay someone for the work. +Consider also would it be better to implement this functionality as a separate +tool outside the core framework. + +Code contributions +------------------ + +If you have fixed a bug or implemented an enhancement, you can contribute +your changes via GitHub's pull requests. This is not restricted to code, +on the contrary, fixes and enhancements to documentation_ and tests_ alone +are also very valuable. + +Choosing something to work on +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Often you already have a bug or an enhancement you want to work on in your +mind, but you can also look at the [issue tracker] +(https://github.com/robotframework/Selenium2Library/issues) to find bugs and +enhancements submitted by others. The issues vary significantly in complexity +and difficulty, so you can try to find something that matches your skill level +and knowledge. + +Pull requests +~~~~~~~~~~~~~ + +On GitHub pull requests are the main mechanism to contribute code. They +are easy to use both for the contributor and for person accepting +the contribution, and with more complex contributions it is easy also +for others to join the discussion. Preconditions for creating a pull +requests are having a [GitHub account](https://github.com/), +installing [Git](https://git-scm.com) and forking the +[Selenium2Library project] +(https://github.com/robotframework/Selenium2Library). + +GitHub has good articles explaining how to +[set up Git](https://help.github.com/articles/set-up-git/), +[fork a repository](https://help.github.com/articles/fork-a-repo/) and +[use pull requests](https://help.github.com/articles/using-pull-requests) +and we do not go through them in more detail. We do, however, +recommend to create dedicated branches for pull requests instead of creating +them based on the master branch. This is especially important if you plan to +work on multiple pull requests at the same time. + +Coding conventions +~~~~~~~~~~~~~~~~~~ + +Selenium2Library uses the general Python code conventions defined in [PEP-8] +(https://www.python.org/dev/peps/pep-0008/). In addition to that, we try +to write [idiomatic Python] +(http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html) +and follow the [SOLID principles] +(https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)) with all +new code. An important guideline is that the code should be clear enough that +comments are generally not needed. + +Docstrings should be added to public keywords but are not generally needed in +internal code. When docstrings are added, they should follow [PEP-257] +(https://www.python.org/dev/peps/pep-0257/). See [Documentation](#documentation) +section below for more details about documentation syntax, generating docs, etc. + +We are pretty picky about using whitespace. We use blank lines and whitespace +in expressions as dictated by [PEP-8](https://www.python.org/dev/peps/pep-0008/) +, but we also follow these rules: + +- Indentation using spaces, not tabs. +- No trailing spaces. +- No extra empty lines at the end of the file. +- Files must end with a newline. + +The above rules are good with most other code too. Any good editor or IDE +can be configured to automatically format files according to them. + +Documentation +~~~~~~~~~~~~~ + +With new features or enhancements adequate documentation is as important as the +actual functionality. Different documentation is needed depending on the issue. + +The main source of documentation should be placed in to the library and +individual keywords. But enhancing the internal [wiki] +(https://github.com/robotframework/Selenium2Library/wiki) or other documentation +is equally important. + +- Other keywords and sections in the library introduction can be referenced + with internal links created with backticks like ```Example Keyword``` + +- When referring to arguments, argument names must use in inline code style + created with double backticks like ````argument````. + +- Examples are recommended whenever the new keyword or enhanced functionality is + not trivial. + +- All new enhancements or changes should have a note telling when the change + was introduced. Often adding something like ``New in Selenium2Libray 1.8.`` + is enough. + +Keyword documentation can be easily created using ``_ +script. Resulting docs should be verified before the code is committed. + +Tests +~~~~~ + +When submitting a pull request with a new feature or a fix, you should +always include tests for your changes. These tests prove that your changes +work, help prevent bugs in the future, and help document what your changes +do. Depending an the change, you may need `acceptance tests`_, `unit tests`_ +or both. + +Make sure to run all of the tests before submitting a pull request to be sure +that your changes do not break anything. If you can, test in multiple +browsers and versions (Firefox, Chrome, IE, etc). Pull requests are also +automatically tested on `continuous integration`_. + +Acceptance tests +~~~~~~~~~~~~~~~~ + +Most of Selenium2Library's testing is done using acceptance tests that +naturally use Robot Framework itself for testing. Every new functionality +or fix should generally get one or more acceptance tests. See +[Unit and acceptance tests] +(https://github.com/robotframework/Selenium2Library/blob/master/BUILD.rst#unit-and-acceptance-tests>) +for more details about creating and executing them. + +Unit tests +~~~~~~~~~~ + +Unit tests are great for testing internal logic and should be added when +appropriate. For more details see [Unit and acceptance tests] +(https://github.com/robotframework/Selenium2Library/blob/master/BUILD.rst#unit-and-acceptance-tests>). + +Continuous integration +~~~~~~~~~~~~~~~~~~~~~~ + +Selenium2Library's continuous integration (CI) servers are visible through +https://travis-ci.org/robotframework/Selenium2Library. They automatically +test all new pull request to the repository with Firefox on Python 2.6 +and 2.7. + +Finalizing pull requests +~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you have code, documentation and tests ready, it is time to finalize +the pull request. + +AUTHORS.txt +~~~~~~~~~~~ + +If you have done any non-trivial change and would like to be credited, +add yourself to [AUTHORS.txt](TOBEDEFINED) file. + +Resolving conflicts +~~~~~~~~~~~~~~~~~~~ + +Conflicts can occur if there are new changes to the master that touch the +same code as your changes. In that case you should [sync your fork] +(https://help.github.com/articles/syncing-a-fork>) and [resolve conflicts] +(https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line) +to allow for an easy merge. + +The most common conflicting file is the aforementioned [AUTHORS.txt](TOBEDEFINED) +, but luckily fixing those conflicts is typically easy. + +Squashing commits +~~~~~~~~~~~~~~~~~ + +If the pull request contains multiple commits, it is recommended that you +squash them into a single commit before the pull request is merged. +See [Squashing Github pull requests into a single commit] +(http://eli.thegreenplace.net/2014/02/19/squashing-github-pull-requests-into-a-single-commit) +article for more details about why and how. + +Squashing is especially important if the pull request contains lots of +temporary commits and changes that have been later reverted or redone. +Squashing is not needed if the commit history is clean and individual +commits are meaningful alone. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..ab412f995 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,52 @@ +## Prerequisites + +- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate +- [ ] The issue still exists against the latest `master` branch of Selenium2Library +- [ ] This is not a usage question (Those should be directed to the + [google groups](http://groups.google.com/group/robotframework-users/) or + [slack chat](https://robotframework-slack.herokuapp.com/)) +- [ ] I have attempted to find the simplest possible steps to reproduce the issue +- [ ] I have included a failing test as a pull request (Optional) + +## Steps to reproduce the issue + +1. _ +2. _ +3. _ + +## Expected behavior and actual behavior + +When I follow those steps, I see... + +I was expecting... + +## Environment + +Browsers + +- [ ] Internet Explorer (version: ) +- [ ] Google Chrome (version: ) +- [ ] Mozilla Firefox (version: ) +- [ ] Opera (version: ) +- [ ] PhantomJS (version: ) +- [ ] Safari (Mac OS X) (version: ) + +Operating System + +- [ ] Windows (version: ) +- [ ] Mac OS X (version: ) +- [ ] Linux (version: distro: ) + +Libraries + +- Robot Framework version: +- Selenium version: +- Selenium2Library ([x] Python or [ ] Jython) version: + +## Isolating and demostrating the problem + +- [ ] This bug happens when testing a public site: [example](http://example.org/) +- [ ] The bug happens consistently across all tested browsers +- [ ] The Robot Framework Test file or snippet is attached or + at [some public site](http://pastebin.com/) +- [ ] The Test was called from: [ ] Local machine [ ] Remote Automation (Jenkins CI) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..543abf704 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +This pull request includes a + +- [ ] An improvement +- [ ] Bug fix +- [ ] New feature + + +The following changes were made + +- +- +- + +If this is related to an existing ticket, include a link to it as well. From e48a1bc8e6a06cc9dafcb1fbdd2bc43680e2ea8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Sat, 12 Mar 2016 00:29:48 +0000 Subject: [PATCH 12/26] Update CONTRIBUTING.md Fixed Issues URL to point to my fork. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0c70ba908..648479b99 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ Submitting issues ----------------- Bugs and enhancements are tracked in the [Hélio's fork issue tracker] -(https://github.com/robotframework/Selenium2Library/issues). If you are +(https://github.com/HelioGuilherme66/robotframework-selenium2library/issues). If you are unsure if something is a bug or is a feature worth implementing, you can first ask on [robotframework-users] (https://groups.google.com/forum/#!forum/robotframework-users) list. This and From 240105cc6140082ef739be1e8b6d06da71871b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Sat, 12 Mar 2016 00:44:54 +0000 Subject: [PATCH 13/26] Update ISSUE_TEMPLATE.md Fix typo --- ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index ab412f995..002504a5b 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -43,7 +43,7 @@ Libraries - Selenium version: - Selenium2Library ([x] Python or [ ] Jython) version: -## Isolating and demostrating the problem +## Isolating and demonstrating the problem - [ ] This bug happens when testing a public site: [example](http://example.org/) - [ ] The bug happens consistently across all tested browsers From 2a4e551fc0fc58f5bb5cba542fc57f22942c1bb9 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 28 Apr 2016 13:50:17 +0100 Subject: [PATCH 14/26] Upgrades Travis firefox to latest-esr. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7a767b05a..b20b52863 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +addons: + firefox: latest-esr language: python sudo: false python: From b8a263e2fb2bab5ad9b7843d203e55fb1c2ba3ce Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 28 Apr 2016 15:31:17 +0100 Subject: [PATCH 15/26] Fixes test run in Fedora. --- test/run_unit_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index aa417c192..b1080b31b 100755 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -5,7 +5,7 @@ def run_unit_tests(modules_to_run=[]): (test_module_names, test_modules) = utils.import_modules_under( - env.UNIT_TEST_DIR, include_root_package_name = False, pattern="test*.py") + env.UNIT_TEST_DIR, include_root_package_name = True, pattern="test*.py") bad_modules_to_run = [module_to_run for module_to_run in modules_to_run if module_to_run not in test_module_names] From 42a6bbf6c72bbb5eb25a2b11c1366d0d6ad901e0 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 28 Apr 2016 15:45:54 +0100 Subject: [PATCH 16/26] Keep selenium==2.52.0 in Travis. Version >=2.53.0 is breaking Unselect From List By Value. --- .travis_python_dep.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh index 1e467626e..918ba6d30 100755 --- a/.travis_python_dep.sh +++ b/.travis_python_dep.sh @@ -3,21 +3,21 @@ set -ev PYTHON_VERSION=`python -c "import sys; print(sys.version[:3])"` if [ "${PYTHON_VERSION}" = "2.6" ]; then pip install robotframework - pip install selenium + pip install selenium==2.52.0 pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "2.7" ]; then pip install robotframework - pip install selenium + pip install selenium==2.52.0 pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "3.4" ]; then pip install robotframework - pip install selenium + pip install selenium==2.52.0 pip install decorator pip install docutils pip install future From 1a2a14f81253f9b4d3ce0a7d4e7364eb760a13a1 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Thu, 28 Apr 2016 17:01:27 +0100 Subject: [PATCH 17/26] Fixes ez_setup.py. Changes version to 1.8.0b2. --- setup.py | 7 +++++++ src/Selenium2Library/version.py | 2 +- src/ez_setup.py | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 8d53b87f0..0d21163be 100755 --- a/setup.py +++ b/setup.py @@ -45,4 +45,11 @@ packages = ['Selenium2Library','Selenium2Library.keywords','Selenium2Library.locators', 'Selenium2Library.utils'], include_package_data = True, + requires = [ + 'decorator', + 'selenium', + 'robotframework', + 'docutils', + 'future' + ] ) diff --git a/src/Selenium2Library/version.py b/src/Selenium2Library/version.py index 3c960425a..a1f302712 100644 --- a/src/Selenium2Library/version.py +++ b/src/Selenium2Library/version.py @@ -1 +1 @@ -VERSION = '1.7.4' \ No newline at end of file +VERSION = '1.8.0b2' diff --git a/src/ez_setup.py b/src/ez_setup.py index b45a3b762..c74abb2e4 100644 --- a/src/ez_setup.py +++ b/src/ez_setup.py @@ -1,8 +1,8 @@ #!python from __future__ import print_function -from future import standard_library -standard_library.install_aliases() +#from future import standard_library +#standard_library.install_aliases() """Bootstrap setuptools installation From 9bd62e6d787fcd8ae8c47e252ac2fe3f4d6e590c Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Fri, 29 Apr 2016 18:51:07 +0100 Subject: [PATCH 18/26] Removes selenium version dependency, current version is 2.53.2. --- .travis_python_dep.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh index 918ba6d30..1e467626e 100755 --- a/.travis_python_dep.sh +++ b/.travis_python_dep.sh @@ -3,21 +3,21 @@ set -ev PYTHON_VERSION=`python -c "import sys; print(sys.version[:3])"` if [ "${PYTHON_VERSION}" = "2.6" ]; then pip install robotframework - pip install selenium==2.52.0 + pip install selenium pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "2.7" ]; then pip install robotframework - pip install selenium==2.52.0 + pip install selenium pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "3.4" ]; then pip install robotframework - pip install selenium==2.52.0 + pip install selenium pip install decorator pip install docutils pip install future From 9f34ada67e15c8cd572cdb8854a1540635203b9d Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 12 Mar 2016 00:15:30 +0000 Subject: [PATCH 19/26] Add GitHub process files. Update CONTRIBUTING.md Fixes test run in Fedora. --- CONTRIBUTING.md | 4 +++- ISSUE_TEMPLATE.md | 52 ++++++++++++++++++++++++++++++++++++++++ PULL_REQUEST_TEMPLATE.md | 14 +++++++++++ test/run_unit_tests.py | 2 +- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 ISSUE_TEMPLATE.md create mode 100644 PULL_REQUEST_TEMPLATE.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 265c5a3c0..9eeaf26e3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -131,7 +131,9 @@ or other documentation is equally important. Keyword documentation can be easily created using ``_ script. Resulting docs should be verified before the code is committed. -## Tests +Tests +~~~~~ + When submitting a pull request with a new feature or a fix, you should always include tests for your changes. These tests prove that your changes work, help prevent bugs in the future, and help document what your changes diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..002504a5b --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,52 @@ +## Prerequisites + +- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate +- [ ] The issue still exists against the latest `master` branch of Selenium2Library +- [ ] This is not a usage question (Those should be directed to the + [google groups](http://groups.google.com/group/robotframework-users/) or + [slack chat](https://robotframework-slack.herokuapp.com/)) +- [ ] I have attempted to find the simplest possible steps to reproduce the issue +- [ ] I have included a failing test as a pull request (Optional) + +## Steps to reproduce the issue + +1. _ +2. _ +3. _ + +## Expected behavior and actual behavior + +When I follow those steps, I see... + +I was expecting... + +## Environment + +Browsers + +- [ ] Internet Explorer (version: ) +- [ ] Google Chrome (version: ) +- [ ] Mozilla Firefox (version: ) +- [ ] Opera (version: ) +- [ ] PhantomJS (version: ) +- [ ] Safari (Mac OS X) (version: ) + +Operating System + +- [ ] Windows (version: ) +- [ ] Mac OS X (version: ) +- [ ] Linux (version: distro: ) + +Libraries + +- Robot Framework version: +- Selenium version: +- Selenium2Library ([x] Python or [ ] Jython) version: + +## Isolating and demonstrating the problem + +- [ ] This bug happens when testing a public site: [example](http://example.org/) +- [ ] The bug happens consistently across all tested browsers +- [ ] The Robot Framework Test file or snippet is attached or + at [some public site](http://pastebin.com/) +- [ ] The Test was called from: [ ] Local machine [ ] Remote Automation (Jenkins CI) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..543abf704 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +This pull request includes a + +- [ ] An improvement +- [ ] Bug fix +- [ ] New feature + + +The following changes were made + +- +- +- + +If this is related to an existing ticket, include a link to it as well. diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index aa417c192..b1080b31b 100755 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -5,7 +5,7 @@ def run_unit_tests(modules_to_run=[]): (test_module_names, test_modules) = utils.import_modules_under( - env.UNIT_TEST_DIR, include_root_package_name = False, pattern="test*.py") + env.UNIT_TEST_DIR, include_root_package_name = True, pattern="test*.py") bad_modules_to_run = [module_to_run for module_to_run in modules_to_run if module_to_run not in test_module_names] From 962a04a47ed63e95ecbd55fda4193498f73ff9ea Mon Sep 17 00:00:00 2001 From: Kevin Ormbrek Date: Sun, 9 Oct 2016 15:02:18 -0500 Subject: [PATCH 20/26] Libdoc updates - link to project and fix 404 (#668) * Fix 404 due to RF migration to Github * Link to project page * Format corrections per PR comments * fix pronoun usage --- doc/Selenium2Library.html | 1664 +++++++++++++++--------------- src/Selenium2Library/__init__.py | 10 +- 2 files changed, 839 insertions(+), 835 deletions(-) diff --git a/doc/Selenium2Library.html b/doc/Selenium2Library.html index c0c9a79fc..85c787c93 100644 --- a/doc/Selenium2Library.html +++ b/doc/Selenium2Library.html @@ -1,832 +1,832 @@ - - - - - - - - - - - - - - - - - - - - - - -
-

Opening library documentation failed

-
    -
  • Verify that you have JavaScript enabled in your browser.
  • -
  • Make sure you are using a modern enough browser. Firefox 3.5, IE 8, or equivalent is required, newer browsers are recommended.
  • -
  • Check are there messages in your browser's JavaScript error log. Please report the problem if you suspect you have encountered a bug.
  • -
-
- - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +
+

Opening library documentation failed

+
    +
  • Verify that you have JavaScript enabled in your browser.
  • +
  • Make sure you are using a modern enough browser. Firefox 3.5, IE 8, or equivalent is required, newer browsers are recommended.
  • +
  • Check are there messages in your browser's JavaScript error log. Please report the problem if you suspect you have encountered a bug.
  • +
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Selenium2Library/__init__.py b/src/Selenium2Library/__init__.py index cadbaf714..01447a813 100644 --- a/src/Selenium2Library/__init__.py +++ b/src/Selenium2Library/__init__.py @@ -21,8 +21,12 @@ class Selenium2Library( _AlertKeywords ): """Selenium2Library is a web testing library for Robot Framework. + + This document is about using Selenium2Library. For information about + installation, support, and more please visit the + [https://github.com/robotframework/Selenium2Library|project page]. - It uses the Selenium 2 (WebDriver) libraries internally to control a web browser. + Selenium2Library uses the Selenium 2 (WebDriver) libraries internally to control a web browser. See http://seleniumhq.org/docs/03_webdriver.html for more information on Selenium 2 and WebDriver. @@ -131,8 +135,8 @@ class Selenium2Library( All timeouts can be given as numbers considered seconds (e.g. 0.5 or 42) or in Robot Framework's time syntax (e.g. '1.5 seconds' or '1 min 30 s'). - For more information about the time syntax see: - http://robotframework.googlecode.com/svn/trunk/doc/userguide/RobotFrameworkUserGuide.html#time-format. + For more information about the time syntax see the + [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide]. """ ROBOT_LIBRARY_SCOPE = 'GLOBAL' From 161f43cb4f904156cdb5652c90fc10185fabf2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Fri, 14 Oct 2016 13:41:42 +0100 Subject: [PATCH 21/26] Changes to use Firefox ESR (45.4.0) While we are not having Selenium 3.0 working, with external `geckodriver`, we use lower versions of stable Firefox. From d3073aa059727eb21891199eeb383aa82fd96f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Fri, 14 Oct 2016 13:45:35 +0100 Subject: [PATCH 22/26] Changes to use Selenium 2.53.6 (and not 3.0) We are not ready for Selenium 3.0 yet. --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index b20b52863..47c46527f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_install: install: true #- pip install pep8 --use-mirrors #- pip install pyflakes --use-mirrors +<<<<<<< HEAD # Installation is done at before_install ##- pip install robotframework==3.0b1 ##- pip install selenium @@ -19,6 +20,12 @@ install: true ##- pip install future # Mockito is only used when in Python 2.7 after installing future ##- pip install mockito +======= + - pip install robotframework + - pip install selenium==2.53.6 + - pip install decorator + - pip install mockito +>>>>>>> e080820... Changes to use Selenium 2.53.6 (and not 3.0) #- "if [[ ${BROWSER} == 'ie' ]]; then pip install ie_only_pkg; fi" before_script: - "export DISPLAY=:99.0" From 0959c19bb6527d64eb02ed518b721ad246a7cda7 Mon Sep 17 00:00:00 2001 From: Gaurang Shah Date: Fri, 14 Oct 2016 23:22:26 +0530 Subject: [PATCH 23/26] Added method to find element by class name #673 (#674) * Added method to find element by class name #673 * Changes to use Firefox ESR (45.4.0) While we are not having Selenium 3.0 working, with external `geckodriver`, we use lower versions of stable Firefox. * Changes to use Selenium 2.53.6 (and not 3.0) We are not ready for Selenium 3.0 yet. --- src/Selenium2Library/__init__.py | 1 + src/Selenium2Library/locators/elementfinder.py | 6 ++++++ test/unit/locators/test_elementfinder.py | 13 ++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Selenium2Library/__init__.py b/src/Selenium2Library/__init__.py index 01447a813..dae933762 100644 --- a/src/Selenium2Library/__init__.py +++ b/src/Selenium2Library/__init__.py @@ -71,6 +71,7 @@ class Selenium2Library( | link | Click Element `|` link=My Link | Matches anchor elements by their link text | | partial link | Click Element `|` partial link=y Lin | Matches anchor elements by their partial link text | | css | Click Element `|` css=div.my_class | Matches by CSS selector | + | class | Click Element `|` class=my_class | Matches by class name selector | | jquery | Click Element `|` jquery=div.my_class | Matches by jQuery/sizzle selector | | sizzle | Click Element `|` sizzle=div.my_class | Matches by jQuery/sizzle selector | | tag | Click Element `|` tag=div | Matches by HTML tag name | diff --git a/src/Selenium2Library/locators/elementfinder.py b/src/Selenium2Library/locators/elementfinder.py index 79412cb97..be2388a2d 100644 --- a/src/Selenium2Library/locators/elementfinder.py +++ b/src/Selenium2Library/locators/elementfinder.py @@ -16,6 +16,7 @@ def __init__(self): 'link': self._find_by_link_text, 'partial link': self._find_by_partial_link_text, 'css': self._find_by_css_selector, + 'class': self._find_by_class_name, 'jquery': self._find_by_sizzle_selector, 'sizzle': self._find_by_sizzle_selector, 'tag': self._find_by_tag_name, @@ -109,6 +110,11 @@ def _find_by_css_selector(self, browser, criteria, tag, constraints): browser.find_elements_by_css_selector(criteria), tag, constraints) + def _find_by_class_name(self, browser, criteria, tag, constraints): + return self._filter_elements( + browser.find_elements_by_class_name(criteria), + tag, constraints) + def _find_by_tag_name(self, browser, criteria, tag, constraints): return self._filter_elements( browser.find_elements_by_tag_name(criteria), diff --git a/test/unit/locators/test_elementfinder.py b/test/unit/locators/test_elementfinder.py index 28505f1d1..fba91e30e 100644 --- a/test/unit/locators/test_elementfinder.py +++ b/test/unit/locators/test_elementfinder.py @@ -271,7 +271,6 @@ def test_find_by_partial_link_text(self): result = finder.find(browser, "partial link=my link", tag='a') self.assertEqual(result, [elements[1], elements[3]]) - def test_find_by_css_selector(self): finder = ElementFinder() browser = mock() @@ -284,6 +283,18 @@ def test_find_by_css_selector(self): result = finder.find(browser, "css=#test1", tag='a') self.assertEqual(result, [elements[1], elements[3]]) + def test_find_by_class_names(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_class_name("test1").thenReturn(elements) + + result = finder.find(browser, "class=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "class=test1", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + def test_find_by_tag_name(self): finder = ElementFinder() browser = mock() From 29f6f6ed928c3f064721f2b98b8df25f5e3e14b2 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 15 Oct 2016 00:58:50 +0100 Subject: [PATCH 24/26] Updated Travis config. --- .travis.yml | 7 ------- .travis_python_dep.sh | 6 +++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 47c46527f..b20b52863 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ before_install: install: true #- pip install pep8 --use-mirrors #- pip install pyflakes --use-mirrors -<<<<<<< HEAD # Installation is done at before_install ##- pip install robotframework==3.0b1 ##- pip install selenium @@ -20,12 +19,6 @@ install: true ##- pip install future # Mockito is only used when in Python 2.7 after installing future ##- pip install mockito -======= - - pip install robotframework - - pip install selenium==2.53.6 - - pip install decorator - - pip install mockito ->>>>>>> e080820... Changes to use Selenium 2.53.6 (and not 3.0) #- "if [[ ${BROWSER} == 'ie' ]]; then pip install ie_only_pkg; fi" before_script: - "export DISPLAY=:99.0" diff --git a/.travis_python_dep.sh b/.travis_python_dep.sh index 1e467626e..a169c67ca 100755 --- a/.travis_python_dep.sh +++ b/.travis_python_dep.sh @@ -3,21 +3,21 @@ set -ev PYTHON_VERSION=`python -c "import sys; print(sys.version[:3])"` if [ "${PYTHON_VERSION}" = "2.6" ]; then pip install robotframework - pip install selenium + pip install selenium==2.53.6 pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "2.7" ]; then pip install robotframework - pip install selenium + pip install selenium==2.53.6 pip install decorator pip install docutils pip install future pip install mockito elif [ "${PYTHON_VERSION}" = "3.4" ]; then pip install robotframework - pip install selenium + pip install selenium==2.53.6 pip install decorator pip install docutils pip install future From c8217c7f6eb0879a0adf4571a2b5c09cd9fab8b4 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sun, 18 Sep 2016 00:46:32 +0100 Subject: [PATCH 25/26] Now calls run_unit_tests.py file instead of the method (this fixes failure in Fedora Core 22). Get path to python/jython to run unit tests. --- test/run_tests.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/run_tests.py b/test/run_tests.py index 4de5cf7d7..1865bae2c 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -3,11 +3,14 @@ import env import os import sys +from os.path import abspath, dirname, join from subprocess import Popen, call from tempfile import TemporaryFile from run_unit_tests import run_unit_tests +CURDIR = dirname(abspath(__file__)) + ROBOT_ARGS = [ '--doc', 'SeleniumSPacceptanceSPtestsSPwithSP%(browser)s', '--outputdir', '%(outdir)s', @@ -96,7 +99,8 @@ def _help(): def _run_unit_tests(): print('Running unit tests') - failures = run_unit_tests() + pypath = sys.executable + failures = call([pypath, os.path.join(CURDIR,'run_unit_tests.py')]) if failures != 0: print('\n%d unit tests failed - not running acceptance tests!' % failures) else: From 42e2ee42e3e133b2277b2a538a74f59afdcad120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Mon, 28 Nov 2016 01:14:27 +0100 Subject: [PATCH 26/26] Attempt to fix run_tests on Windows. --- test/run_tests.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/run_tests.py b/test/run_tests.py index 7e242307b..07e31aff0 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -7,7 +7,7 @@ from subprocess import Popen, call from tempfile import TemporaryFile -from run_unit_tests import run_unit_tests +# from run_unit_tests import run_unit_tests CURDIR = dirname(abspath(__file__)) @@ -49,7 +49,7 @@ def acceptance_tests(interpreter, browser, args): def start_http_server(): server_output = TemporaryFile() - python_bin= 'python' + sys.version[:3] + python_bin = sys.executable Popen([python_bin, env.HTTP_SERVER_FILE ,'start'], stdout=server_output, stderr=server_output) @@ -63,14 +63,15 @@ def execute_tests(runner, args): call(command, shell=os.sep=='\\', env=dict(os.environ, ROBOT_SYSLOG_FILE=syslog)) def stop_http_server(): - python_bin= 'python' + sys.version[:3] + python_bin = sys.executable call([python_bin, env.HTTP_SERVER_FILE, 'stop']) def process_output(args): print() if _has_robot_27(): - call(['python', os.path.join(env.RESOURCES_DIR, 'statuschecker.py'), - os.path.join(env.RESULTS_DIR, 'output.xml')]) + python_bin = sys.executable + call([python_bin, os.path.join(env.RESOURCES_DIR, 'statuschecker.py'), + os.path.join(env.RESULTS_DIR, 'output.xml')]) rebot = 'rebot' if os.sep == '/' else 'rebot.bat' rebot_cmd = [rebot] + [ arg % ARG_VALUES for arg in REBOT_ARGS ] + args + \ [os.path.join(ARG_VALUES['outdir'], 'output.xml') ]