From 5c48703d1ce506c6715ce8f5bd8bbea74f905991 Mon Sep 17 00:00:00 2001 From: Mike Uehara Date: Fri, 19 Aug 2011 15:59:09 -0700 Subject: [PATCH 001/105] Add test file. --- test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 000000000..b6fc4c620 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +hello \ No newline at end of file From e9b2534f84516861e7dad72f1d14c71d4b9de171 Mon Sep 17 00:00:00 2001 From: Mike Uehara Date: Fri, 19 Aug 2011 16:11:33 -0700 Subject: [PATCH 002/105] removed test file --- test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index b6fc4c620..000000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -hello \ No newline at end of file From 0587f3fe84039c29d5d11bd046893a771dd0f72f Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 21 Oct 2011 23:25:40 -0700 Subject: [PATCH 003/105] Clean up inconsistent line endings --- .hgignore | 20 +- doc/libdoc.py | 1438 ++++++++--------- src/Selenium2Library/keywords/__init__.py | 50 +- .../keywords/_selectelement.py | 2 +- src/Selenium2Library/locators/__init__.py | 16 +- .../locators/elementfinder.py | 42 +- .../locators/windowmanager.py | 38 +- src/Selenium2Library/metadata.py | 2 +- src/Selenium2Library/utils/__init__.py | 8 +- src/Selenium2Library/utils/browsercache.py | 26 +- test/acceptance/keywords/click_element.txt | 10 +- test/acceptance/keywords/elements.txt | 14 +- test/resources/html/mouse/index.html | 40 +- test/resources/html/tables/tables.html | 450 +++--- test/resources/html/visibility.html | 16 +- test/unit/locators/test_elementfinder.py | 652 ++++---- test/unit/locators/test_tableelementfinder.py | 358 ++-- test/unit/locators/test_windowmanager.py | 554 +++---- test/unit/utils/test_browsercache.py | 156 +- test/unit/utils/test_package.py | 38 +- 20 files changed, 1965 insertions(+), 1965 deletions(-) diff --git a/.hgignore b/.hgignore index 22a97db7e..f94adb660 100644 --- a/.hgignore +++ b/.hgignore @@ -1,10 +1,10 @@ -syntax:glob -.project -.pydevproject -test/results -*.pyc -*.orig -MANIFEST - -dist -build +syntax:glob +.project +.pydevproject +test/results +*.pyc +*.orig +MANIFEST + +dist +build diff --git a/doc/libdoc.py b/doc/libdoc.py index 2a2660358..77acfa85c 100755 --- a/doc/libdoc.py +++ b/doc/libdoc.py @@ -1,719 +1,719 @@ - -#!/usr/bin/env python - -# Copyright 2008-2011 Nokia Siemens Networks Oyj -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Robot Framework Library and Resource File Documentation Generator - -Usage: libdoc.py [options] library_or_resource - -This script can generate keyword documentation in HTML and XML formats. The -former is suitable for humans and the latter for RIDE, RFDoc, and other tools. -This script can also upload XML documentation to RFDoc system. - -Documentation can be created for both test libraries and resource files. All -library and resource file types are supported, and also earlier generated -documentation in XML format can be used as input. - -Options: - -a --argument value * Possible arguments that a library needs. - -f --format HTML|XML Specifies whether to generate HTML or XML output. - The default value is got from the output file - extension and if the output is not specified the - default is HTML. - -o --output path Where to write the generated documentation. Can be - either a directory or a file, or a URL pointing to - RFDoc system's upload page. The default value is the - directory where the script is executed from. If - a URL is given, it must start with 'http://'. - -N --name newname Sets the name of the documented library or resource. - -V --version newversion Sets the version of the documented library or - resource. - -T --title title Sets the title of the generated HTML documentation. - Underscores in the given title are automatically - converted to spaces. - -S --styles styles Overrides the default styles. If the given 'styles' - is a path to an existing files, styles will be read - from it. If it is string a 'NONE', no styles will be - used. Otherwise the given text is used as-is. - -P --pythonpath path * Additional path(s) to insert into PYTHONPATH. - -E --escape what:with * Escapes characters which are problematic in console. - 'what' is the name of the character to escape and - 'with' is the string to escape it with. - <-------------------ESCAPES------------------------> - -h --help Print this help. - -For more information see either the tool's wiki page at -http://code.google.com/p/robotframework/wiki/LibraryDocumentationTool -or tools/libdoc/doc/libdoc.html file inside source distributions. -""" - -from __future__ import with_statement -import sys -import os -import re -import tempfile -from httplib import HTTPConnection -from HTMLParser import HTMLParser - -from robot.running import TestLibrary, UserLibrary -try: - from robot.utils.templating import Template, Namespace -except ImportError: # Support for 2.5.x - from robot.serializing.templating import Template, Namespace -from robot.errors import DataError, Information -from robot.parsing import populators -from robot import utils - - -populators.PROCESS_CURDIR = False - - -def _uploading(output): - return output.startswith('http://') - - -def create_html_doc(lib, outpath, title=None, styles=None): - if title: - title = title.replace('_', ' ') - else: - title = lib.name - generated = utils.get_timestamp(daysep='-', millissep=None) - namespace = Namespace(LIB=lib, TITLE=title, STYLES=_get_styles(styles), - GENERATED=generated) - doc = Template(template=HTML_TEMPLATE).generate(namespace) + '\n' - with open(outpath, 'w') as outfile: - outfile.write(doc.encode('UTF-8')) - -def _get_styles(styles): - if not styles: - return DEFAULT_STYLES - if styles.upper() == 'NONE': - return '' - if os.path.isfile(styles): - with open(styles) as f: - return f.read() - return styles - - -def create_xml_doc(lib, outpath): - writer = utils.XmlWriter(outpath) - writer.start('keywordspec', {'name': lib.name, 'type': lib.type, - 'generated': utils.get_timestamp(millissep=None)}) - writer.element('version', lib.version) - writer.element('scope', lib.scope) - writer.element('namedargs', 'yes' if lib.supports_named_arguments else 'no') - writer.element('doc', lib.doc) - _write_keywords_to_xml(writer, 'init', lib.inits) - _write_keywords_to_xml(writer, 'kw', lib.keywords) - writer.end('keywordspec') - writer.close() - -def _write_keywords_to_xml(writer, kwtype, keywords): - for kw in keywords: - writer.start(kwtype, {'name': kw.name} if kwtype == 'kw' else {}) - writer.element('doc', kw.doc) - writer.start('arguments') - for arg in kw.args: - writer.element('arg', arg) - writer.end('arguments') - writer.end(kwtype) - - -def upload_xml_doc(outpath, uploadurl): - RFDocUploader().upload(outpath, uploadurl) - - -def LibraryDoc(libname, arguments=None, name=None, version=None): - libdoc = _import_library(libname, arguments) - if name: - libdoc.name = name - if version: - libdoc.version = version - return libdoc - -def _import_library(name, arguments): - ext = os.path.splitext(name)[1].lower()[1:] - if ext in ('html', 'htm', 'xhtml', 'tsv', 'txt', 'rst', 'rest'): - return ResourceDoc(name) - elif ext == 'xml': - return XmlLibraryDoc(name) - elif ext == 'java': - return JavaLibraryDoc(name) - else: - return PythonLibraryDoc(name, arguments) - - -class _DocHelper: - _name_regexp = re.compile("`(.+?)`") - _list_or_table_regexp = re.compile('^(\d+\.|[-*|]|\[\d+\]) .') - - @property - def htmldoc(self): - return self._get_htmldoc(self.doc) - - @property - def htmlshortdoc(self): - return utils.html_attr_escape(self.shortdoc) - - @property - def htmlname(self): - return utils.html_attr_escape(self.name) - - def _process_doc(self, doc): - ret = [''] - for line in doc.splitlines(): - line = line.strip() - ret.append(self._get_doc_line_separator(line, ret[-1])) - ret.append(line) - return ''.join(ret) - - def _get_doc_line_separator(self, line, prev): - if prev == '': - return '' - if line == '': - return '\n\n' - if self._list_or_table_regexp.search(line): - return '\n' - if prev.startswith('| ') and prev.endswith(' |'): - return '\n' - if self.type == 'resource': - return '\n\n' - return ' ' - - def _get_htmldoc(self, doc): - doc = utils.html_format(doc) - return self._name_regexp.sub(self._link_keywords, doc) - - def _link_keywords(self, res): - name = res.group(1) - lib = self.lib if hasattr(self, 'lib') else self - for kw in lib.keywords: - if utils.eq(name, kw.name): - return '%s' % (kw.name, name) - if utils.eq_any(name, ['introduction', 'library introduction']): - return '%s' % name - if utils.eq_any(name, ['importing', 'library importing']): - return '%s' % name - return '%s' % name - - -class PythonLibraryDoc(_DocHelper): - type = 'library' - - def __init__(self, name, arguments=None): - lib = self._import(name, arguments) - self.supports_named_arguments = lib.supports_named_arguments - self.name = lib.name - self.version = utils.html_escape(getattr(lib, 'version', '')) - self.scope = self._get_scope(lib) - self.doc = self._process_doc(self._get_doc(lib)) - self.inits = self._get_initializers(lib) - self.keywords = sorted(KeywordDoc(handler, self) - for handler in lib.handlers.values()) - - def _import(self, name, args): - return TestLibrary(name, args) - - def _get_scope(self, lib): - if hasattr(lib, 'scope'): - return {'TESTCASE': 'test case', 'TESTSUITE': 'test suite', - 'GLOBAL': 'global'}[lib.scope] - return '' - - def _get_doc(self, lib): - return lib.doc or "Documentation for test library `%s`." % self.name - - def _get_initializers(self, lib): - if lib.init.arguments.maxargs == 0: - return [] - return [KeywordDoc(lib.init, self)] - - -class ResourceDoc(PythonLibraryDoc): - type = 'resource' - supports_named_arguments = True - - def _import(self, path, arguments): - return UserLibrary(self._find_resource_file(path)) - - def _find_resource_file(self, path): - if os.path.isfile(path): - return path - for dire in [item for item in sys.path if os.path.isdir(item)]: - if os.path.isfile(os.path.join(dire, path)): - return os.path.join(dire, path) - raise DataError("Resource file '%s' doesn't exist." % path) - - def _get_doc(self, resource): - doc = getattr(resource, 'doc', '') # doc available only in 2.1+ - if not doc: - doc = "Documentation for resource file `%s`." % self.name - return utils.unescape(doc) - - def _get_initializers(self, lib): - return [] - - -class XmlLibraryDoc(_DocHelper): - - def __init__(self, path): - dom = utils.DomWrapper(path) - self.name = dom.get_attr('name') - self.type = dom.get_attr('type') - self.version = dom.get_node('version').text - self.scope = dom.get_node('scope').text - self.supports_named_arguments = self._supports_named_args(dom) - self.doc = dom.get_node('doc').text - self.inits = [XmlKeywordDoc(node, self) - for node in dom.get_nodes('init')] - self.keywords = [XmlKeywordDoc(node, self) - for node in dom.get_nodes('kw')] - - def _supports_named_args(self, dom): - try: - node = dom.get_node('namedargs') - except AttributeError: # Backwards compatiblity with RF < 2.6.2 - return False - else: - return node.text == 'yes' - - -class _BaseKeywordDoc(_DocHelper): - - def __init__(self, library): - self.lib = library - self.type = library.type - - def __cmp__(self, other): - return cmp(self.name.lower(), other.name.lower()) - - @property - def argstr(self): - return ', '.join(self.args) - - @property - def shortdoc(self): - return self.doc.splitlines()[0] if self.doc else '' - - def __repr__(self): - return "'Keyword %s from library %s'" % (self.name, self.lib.name) - - -class KeywordDoc(_BaseKeywordDoc): - - def __init__(self, handler, library): - _BaseKeywordDoc.__init__(self, library) - self.name = handler.name - self.args = self._get_args(handler) - self.doc = self._process_doc(handler.doc) - self.shortdoc = handler.shortdoc - - def _get_args(self, handler): - required, defaults, varargs = self._parse_args(handler) - args = required + ['%s=%s' % item for item in defaults] - if varargs: - args.append('*%s' % varargs) - return args - - def _parse_args(self, handler): - args = [self._normalize_arg(arg, handler.type == 'user') - for arg in handler.arguments.names] - default_count = len(handler.arguments.defaults) - if default_count == 0: - required = args[:] - defaults = [] - else: - required = args[:-default_count] - defaults = zip(args[-default_count:], - list(handler.arguments.defaults)) - varargs = self._normalize_arg(handler.arguments.varargs, - handler.type == 'user') - return required, defaults, varargs - - def _normalize_arg(self, arg, userkeyword=False): - if arg is None: - return arg - arg = arg.rstrip('_') - if userkeyword: # strip ${} to make args look consistent - arg = arg[2:-1] - return arg - - -class XmlKeywordDoc(_BaseKeywordDoc): - - def __init__(self, node, library): - _BaseKeywordDoc.__init__(self, library) - self.name = node.get_attr('name', '') - self.args = [arg.text for arg in node.get_nodes('arguments/arg')] - self.doc = node.get_node('doc').text - - -if not utils.is_jython: - - def JavaLibraryDoc(path): - raise DataError('Documenting Java test libraries requires Jython.') - -else: - - class JavaLibraryDoc(_DocHelper): - type = 'library' - supports_named_arguments = False - - def __init__(self, path): - cls = self._get_class(path) - self.name = cls.qualifiedName() - self.version = self._get_version(cls) - self.scope = self._get_scope(cls) - self.doc = self._process_doc(cls.getRawCommentText()) - self.keywords = sorted(JavaKeywordDoc(method, self) - for method in cls.methods()) - self.inits = [JavaKeywordDoc(init, self) - for init in cls.constructors()] - if len(self.inits) == 1 and not self.inits[0].args: - self.inits = [] - - def _get_class(self, path): - """Processes the given Java source file and returns ClassDoc. - - Processing is done using com.sun.tools.javadoc APIs. The usage has - been figured out from sources at - http://www.java2s.com/Open-Source/Java-Document/JDK-Modules-com.sun/tools/com.sun.tools.javadoc.htm - - Returned object implements com.sun.javadoc.ClassDoc interface, see - http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/doclet/ - """ - try: - from com.sun.tools.javadoc import JavadocTool, Messager, ModifierFilter - from com.sun.tools.javac.util import List, Context - from com.sun.tools.javac.code.Flags import PUBLIC - except ImportError: - raise DataError("Creating documentation from Java source files " - "requires 'tools.jar' to be in CLASSPATH.") - context = Context() - Messager.preRegister(context, 'libdoc.py') - jdoctool = JavadocTool.make0(context) - filter = ModifierFilter(PUBLIC) - java_names = List.of(path) - root = jdoctool.getRootDocImpl('en', 'utf-8', filter, java_names, - List.nil(), False, List.nil(), - List.nil(), False, False, True) - return root.classes()[0] - - def _get_version(self, cls): - version = self._get_attr(cls, 'VERSION', '') - return utils.html_escape(version) - - def _get_scope(self, cls): - scope = self._get_attr(cls, 'SCOPE', 'TEST CASE') - return scope.replace('_', ' ').lower() - - def _get_attr(self, cls, name, default): - for field in cls.fields(): - if field.name() == 'ROBOT_LIBRARY_' + name \ - and field.isPublic() and field.constantValue(): - return field.constantValue() - return default - - - class JavaKeywordDoc(_BaseKeywordDoc): - # TODO: handle keyword default values and varargs. - def __init__(self, method, library): - _BaseKeywordDoc.__init__(self, library) - self.name = utils.printable_name(method.name(), True) - self.args = [param.name() for param in method.parameters()] - self.doc = self._process_doc(method.getRawCommentText()) - - -class RFDocUploader(object): - - def upload(self, file_path, host): - if host.startswith('http://'): - host = host[len('http://'):] - xml_file = open(file_path, 'rb') - conn = HTTPConnection(host) - try: - resp = self._post_multipart(conn, xml_file) - self._validate_success(resp) - finally: - xml_file.close() - conn.close() - - def _post_multipart(self, conn, xml_file): - conn.connect() - content_type, body = self._encode_multipart_formdata(xml_file) - headers = {'User-Agent': 'libdoc.py', 'Content-Type': content_type} - conn.request('POST', '/upload/', body, headers) - return conn.getresponse() - - def _encode_multipart_formdata(self, xml_file): - boundary = '----------ThIs_Is_tHe_bouNdaRY_$' - body = """--%(boundary)s -Content-Disposition: form-data; name="override" - -on ---%(boundary)s -Content-Disposition: form-data; name="file"; filename="%(filename)s" -Content-Type: text/xml - -%(content)s ---%(boundary)s-- -""" % {'boundary': boundary, 'filename': xml_file.name, 'content': xml_file.read()} - content_type = 'multipart/form-data; boundary=%s' % boundary - return content_type, body.replace('\n', '\r\n') - - def _validate_success(self, resp): - html = resp.read() - if resp.status != 200: - raise DataError(resp.reason.strip()) - if 'Successfully uploaded library' not in html: - raise DataError('\n'.join(_ErrorParser(html).errors)) - - -class _ErrorParser(HTMLParser): - - def __init__(self, html): - HTMLParser.__init__(self) - self._inside_errors = False - self.errors = [] - self.feed(html) - self.close() - - def handle_starttag(self, tag, attributes): - if ('class', 'errorlist') in attributes: - self._inside_errors = True - - def handle_endtag(self, tag): - if tag == 'ul': - self._inside_errors = False - - def handle_data(self, data): - if self._inside_errors and data.strip(): - self.errors.append(data) - - -DEFAULT_STYLES = ''' - - -'''.strip() - - -HTML_TEMPLATE = ''' - - -${TITLE} - -${STYLES} - - -

${TITLE}

- -Version: ${LIB.version}
- - -Scope: ${LIB.scope}
- -Named arguments: - -supported - -not supported - - -

Introduction

-
${LIB.htmldoc}
- - -

Importing

- - - - - - - - - - - -
ArgumentsDocumentation
${init.argstr}${init.htmldoc}
- - -

Shortcuts

- - -

Keywords

- - - - - - - - - - - - - -
KeywordArgumentsDocumentation
${kw.htmlname}${kw.argstr}${kw.htmldoc}
- - - -''' - -if __name__ == '__main__': - - def get_format(format, output): - if format: - return format.upper() - if os.path.splitext(output)[1].upper() == '.XML': - return 'XML' - return 'HTML' - - def get_unique_path(base, ext, index=0): - if index == 0: - path = '%s.%s' % (base, ext) - else: - path = '%s-%d.%s' % (base, index, ext) - if os.path.exists(path): - return get_unique_path(base, ext, index+1) - return path - - - try: - argparser = utils.ArgumentParser(__doc__) - opts, args = argparser.parse_args(sys.argv[1:], pythonpath='pythonpath', - help='help', unescape='escape', - check_args=True) - libname = args[0] - library = LibraryDoc(libname, opts['argument'], opts['name'], - opts['version']) - output = opts['output'] or '.' - if _uploading(output): - file_path = os.path.join(tempfile.gettempdir(), 'libdoc_upload.xml') - create_xml_doc(library, file_path) - upload_xml_doc(file_path, output) - os.remove(file_path) - else: - format = get_format(opts['format'], output) - if os.path.isdir(output): - output = get_unique_path(os.path.join(output, library.name), - format.lower()) - output = os.path.abspath(output) - if format == 'HTML': - create_html_doc(library, output, opts['title'], opts['styles']) - else: - create_xml_doc(library, output) - except Information, msg: - print msg - except DataError, err: - print err, '\n\nTry --help for usage information.' - except Exception, err: - print err - else: - print '%s -> %s' % (library.name, output) + +#!/usr/bin/env python + +# Copyright 2008-2011 Nokia Siemens Networks Oyj +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Robot Framework Library and Resource File Documentation Generator + +Usage: libdoc.py [options] library_or_resource + +This script can generate keyword documentation in HTML and XML formats. The +former is suitable for humans and the latter for RIDE, RFDoc, and other tools. +This script can also upload XML documentation to RFDoc system. + +Documentation can be created for both test libraries and resource files. All +library and resource file types are supported, and also earlier generated +documentation in XML format can be used as input. + +Options: + -a --argument value * Possible arguments that a library needs. + -f --format HTML|XML Specifies whether to generate HTML or XML output. + The default value is got from the output file + extension and if the output is not specified the + default is HTML. + -o --output path Where to write the generated documentation. Can be + either a directory or a file, or a URL pointing to + RFDoc system's upload page. The default value is the + directory where the script is executed from. If + a URL is given, it must start with 'http://'. + -N --name newname Sets the name of the documented library or resource. + -V --version newversion Sets the version of the documented library or + resource. + -T --title title Sets the title of the generated HTML documentation. + Underscores in the given title are automatically + converted to spaces. + -S --styles styles Overrides the default styles. If the given 'styles' + is a path to an existing files, styles will be read + from it. If it is string a 'NONE', no styles will be + used. Otherwise the given text is used as-is. + -P --pythonpath path * Additional path(s) to insert into PYTHONPATH. + -E --escape what:with * Escapes characters which are problematic in console. + 'what' is the name of the character to escape and + 'with' is the string to escape it with. + <-------------------ESCAPES------------------------> + -h --help Print this help. + +For more information see either the tool's wiki page at +http://code.google.com/p/robotframework/wiki/LibraryDocumentationTool +or tools/libdoc/doc/libdoc.html file inside source distributions. +""" + +from __future__ import with_statement +import sys +import os +import re +import tempfile +from httplib import HTTPConnection +from HTMLParser import HTMLParser + +from robot.running import TestLibrary, UserLibrary +try: + from robot.utils.templating import Template, Namespace +except ImportError: # Support for 2.5.x + from robot.serializing.templating import Template, Namespace +from robot.errors import DataError, Information +from robot.parsing import populators +from robot import utils + + +populators.PROCESS_CURDIR = False + + +def _uploading(output): + return output.startswith('http://') + + +def create_html_doc(lib, outpath, title=None, styles=None): + if title: + title = title.replace('_', ' ') + else: + title = lib.name + generated = utils.get_timestamp(daysep='-', millissep=None) + namespace = Namespace(LIB=lib, TITLE=title, STYLES=_get_styles(styles), + GENERATED=generated) + doc = Template(template=HTML_TEMPLATE).generate(namespace) + '\n' + with open(outpath, 'w') as outfile: + outfile.write(doc.encode('UTF-8')) + +def _get_styles(styles): + if not styles: + return DEFAULT_STYLES + if styles.upper() == 'NONE': + return '' + if os.path.isfile(styles): + with open(styles) as f: + return f.read() + return styles + + +def create_xml_doc(lib, outpath): + writer = utils.XmlWriter(outpath) + writer.start('keywordspec', {'name': lib.name, 'type': lib.type, + 'generated': utils.get_timestamp(millissep=None)}) + writer.element('version', lib.version) + writer.element('scope', lib.scope) + writer.element('namedargs', 'yes' if lib.supports_named_arguments else 'no') + writer.element('doc', lib.doc) + _write_keywords_to_xml(writer, 'init', lib.inits) + _write_keywords_to_xml(writer, 'kw', lib.keywords) + writer.end('keywordspec') + writer.close() + +def _write_keywords_to_xml(writer, kwtype, keywords): + for kw in keywords: + writer.start(kwtype, {'name': kw.name} if kwtype == 'kw' else {}) + writer.element('doc', kw.doc) + writer.start('arguments') + for arg in kw.args: + writer.element('arg', arg) + writer.end('arguments') + writer.end(kwtype) + + +def upload_xml_doc(outpath, uploadurl): + RFDocUploader().upload(outpath, uploadurl) + + +def LibraryDoc(libname, arguments=None, name=None, version=None): + libdoc = _import_library(libname, arguments) + if name: + libdoc.name = name + if version: + libdoc.version = version + return libdoc + +def _import_library(name, arguments): + ext = os.path.splitext(name)[1].lower()[1:] + if ext in ('html', 'htm', 'xhtml', 'tsv', 'txt', 'rst', 'rest'): + return ResourceDoc(name) + elif ext == 'xml': + return XmlLibraryDoc(name) + elif ext == 'java': + return JavaLibraryDoc(name) + else: + return PythonLibraryDoc(name, arguments) + + +class _DocHelper: + _name_regexp = re.compile("`(.+?)`") + _list_or_table_regexp = re.compile('^(\d+\.|[-*|]|\[\d+\]) .') + + @property + def htmldoc(self): + return self._get_htmldoc(self.doc) + + @property + def htmlshortdoc(self): + return utils.html_attr_escape(self.shortdoc) + + @property + def htmlname(self): + return utils.html_attr_escape(self.name) + + def _process_doc(self, doc): + ret = [''] + for line in doc.splitlines(): + line = line.strip() + ret.append(self._get_doc_line_separator(line, ret[-1])) + ret.append(line) + return ''.join(ret) + + def _get_doc_line_separator(self, line, prev): + if prev == '': + return '' + if line == '': + return '\n\n' + if self._list_or_table_regexp.search(line): + return '\n' + if prev.startswith('| ') and prev.endswith(' |'): + return '\n' + if self.type == 'resource': + return '\n\n' + return ' ' + + def _get_htmldoc(self, doc): + doc = utils.html_format(doc) + return self._name_regexp.sub(self._link_keywords, doc) + + def _link_keywords(self, res): + name = res.group(1) + lib = self.lib if hasattr(self, 'lib') else self + for kw in lib.keywords: + if utils.eq(name, kw.name): + return '%s' % (kw.name, name) + if utils.eq_any(name, ['introduction', 'library introduction']): + return '%s' % name + if utils.eq_any(name, ['importing', 'library importing']): + return '%s' % name + return '%s' % name + + +class PythonLibraryDoc(_DocHelper): + type = 'library' + + def __init__(self, name, arguments=None): + lib = self._import(name, arguments) + self.supports_named_arguments = lib.supports_named_arguments + self.name = lib.name + self.version = utils.html_escape(getattr(lib, 'version', '')) + self.scope = self._get_scope(lib) + self.doc = self._process_doc(self._get_doc(lib)) + self.inits = self._get_initializers(lib) + self.keywords = sorted(KeywordDoc(handler, self) + for handler in lib.handlers.values()) + + def _import(self, name, args): + return TestLibrary(name, args) + + def _get_scope(self, lib): + if hasattr(lib, 'scope'): + return {'TESTCASE': 'test case', 'TESTSUITE': 'test suite', + 'GLOBAL': 'global'}[lib.scope] + return '' + + def _get_doc(self, lib): + return lib.doc or "Documentation for test library `%s`." % self.name + + def _get_initializers(self, lib): + if lib.init.arguments.maxargs == 0: + return [] + return [KeywordDoc(lib.init, self)] + + +class ResourceDoc(PythonLibraryDoc): + type = 'resource' + supports_named_arguments = True + + def _import(self, path, arguments): + return UserLibrary(self._find_resource_file(path)) + + def _find_resource_file(self, path): + if os.path.isfile(path): + return path + for dire in [item for item in sys.path if os.path.isdir(item)]: + if os.path.isfile(os.path.join(dire, path)): + return os.path.join(dire, path) + raise DataError("Resource file '%s' doesn't exist." % path) + + def _get_doc(self, resource): + doc = getattr(resource, 'doc', '') # doc available only in 2.1+ + if not doc: + doc = "Documentation for resource file `%s`." % self.name + return utils.unescape(doc) + + def _get_initializers(self, lib): + return [] + + +class XmlLibraryDoc(_DocHelper): + + def __init__(self, path): + dom = utils.DomWrapper(path) + self.name = dom.get_attr('name') + self.type = dom.get_attr('type') + self.version = dom.get_node('version').text + self.scope = dom.get_node('scope').text + self.supports_named_arguments = self._supports_named_args(dom) + self.doc = dom.get_node('doc').text + self.inits = [XmlKeywordDoc(node, self) + for node in dom.get_nodes('init')] + self.keywords = [XmlKeywordDoc(node, self) + for node in dom.get_nodes('kw')] + + def _supports_named_args(self, dom): + try: + node = dom.get_node('namedargs') + except AttributeError: # Backwards compatiblity with RF < 2.6.2 + return False + else: + return node.text == 'yes' + + +class _BaseKeywordDoc(_DocHelper): + + def __init__(self, library): + self.lib = library + self.type = library.type + + def __cmp__(self, other): + return cmp(self.name.lower(), other.name.lower()) + + @property + def argstr(self): + return ', '.join(self.args) + + @property + def shortdoc(self): + return self.doc.splitlines()[0] if self.doc else '' + + def __repr__(self): + return "'Keyword %s from library %s'" % (self.name, self.lib.name) + + +class KeywordDoc(_BaseKeywordDoc): + + def __init__(self, handler, library): + _BaseKeywordDoc.__init__(self, library) + self.name = handler.name + self.args = self._get_args(handler) + self.doc = self._process_doc(handler.doc) + self.shortdoc = handler.shortdoc + + def _get_args(self, handler): + required, defaults, varargs = self._parse_args(handler) + args = required + ['%s=%s' % item for item in defaults] + if varargs: + args.append('*%s' % varargs) + return args + + def _parse_args(self, handler): + args = [self._normalize_arg(arg, handler.type == 'user') + for arg in handler.arguments.names] + default_count = len(handler.arguments.defaults) + if default_count == 0: + required = args[:] + defaults = [] + else: + required = args[:-default_count] + defaults = zip(args[-default_count:], + list(handler.arguments.defaults)) + varargs = self._normalize_arg(handler.arguments.varargs, + handler.type == 'user') + return required, defaults, varargs + + def _normalize_arg(self, arg, userkeyword=False): + if arg is None: + return arg + arg = arg.rstrip('_') + if userkeyword: # strip ${} to make args look consistent + arg = arg[2:-1] + return arg + + +class XmlKeywordDoc(_BaseKeywordDoc): + + def __init__(self, node, library): + _BaseKeywordDoc.__init__(self, library) + self.name = node.get_attr('name', '') + self.args = [arg.text for arg in node.get_nodes('arguments/arg')] + self.doc = node.get_node('doc').text + + +if not utils.is_jython: + + def JavaLibraryDoc(path): + raise DataError('Documenting Java test libraries requires Jython.') + +else: + + class JavaLibraryDoc(_DocHelper): + type = 'library' + supports_named_arguments = False + + def __init__(self, path): + cls = self._get_class(path) + self.name = cls.qualifiedName() + self.version = self._get_version(cls) + self.scope = self._get_scope(cls) + self.doc = self._process_doc(cls.getRawCommentText()) + self.keywords = sorted(JavaKeywordDoc(method, self) + for method in cls.methods()) + self.inits = [JavaKeywordDoc(init, self) + for init in cls.constructors()] + if len(self.inits) == 1 and not self.inits[0].args: + self.inits = [] + + def _get_class(self, path): + """Processes the given Java source file and returns ClassDoc. + + Processing is done using com.sun.tools.javadoc APIs. The usage has + been figured out from sources at + http://www.java2s.com/Open-Source/Java-Document/JDK-Modules-com.sun/tools/com.sun.tools.javadoc.htm + + Returned object implements com.sun.javadoc.ClassDoc interface, see + http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/doclet/ + """ + try: + from com.sun.tools.javadoc import JavadocTool, Messager, ModifierFilter + from com.sun.tools.javac.util import List, Context + from com.sun.tools.javac.code.Flags import PUBLIC + except ImportError: + raise DataError("Creating documentation from Java source files " + "requires 'tools.jar' to be in CLASSPATH.") + context = Context() + Messager.preRegister(context, 'libdoc.py') + jdoctool = JavadocTool.make0(context) + filter = ModifierFilter(PUBLIC) + java_names = List.of(path) + root = jdoctool.getRootDocImpl('en', 'utf-8', filter, java_names, + List.nil(), False, List.nil(), + List.nil(), False, False, True) + return root.classes()[0] + + def _get_version(self, cls): + version = self._get_attr(cls, 'VERSION', '') + return utils.html_escape(version) + + def _get_scope(self, cls): + scope = self._get_attr(cls, 'SCOPE', 'TEST CASE') + return scope.replace('_', ' ').lower() + + def _get_attr(self, cls, name, default): + for field in cls.fields(): + if field.name() == 'ROBOT_LIBRARY_' + name \ + and field.isPublic() and field.constantValue(): + return field.constantValue() + return default + + + class JavaKeywordDoc(_BaseKeywordDoc): + # TODO: handle keyword default values and varargs. + def __init__(self, method, library): + _BaseKeywordDoc.__init__(self, library) + self.name = utils.printable_name(method.name(), True) + self.args = [param.name() for param in method.parameters()] + self.doc = self._process_doc(method.getRawCommentText()) + + +class RFDocUploader(object): + + def upload(self, file_path, host): + if host.startswith('http://'): + host = host[len('http://'):] + xml_file = open(file_path, 'rb') + conn = HTTPConnection(host) + try: + resp = self._post_multipart(conn, xml_file) + self._validate_success(resp) + finally: + xml_file.close() + conn.close() + + def _post_multipart(self, conn, xml_file): + conn.connect() + content_type, body = self._encode_multipart_formdata(xml_file) + headers = {'User-Agent': 'libdoc.py', 'Content-Type': content_type} + conn.request('POST', '/upload/', body, headers) + return conn.getresponse() + + def _encode_multipart_formdata(self, xml_file): + boundary = '----------ThIs_Is_tHe_bouNdaRY_$' + body = """--%(boundary)s +Content-Disposition: form-data; name="override" + +on +--%(boundary)s +Content-Disposition: form-data; name="file"; filename="%(filename)s" +Content-Type: text/xml + +%(content)s +--%(boundary)s-- +""" % {'boundary': boundary, 'filename': xml_file.name, 'content': xml_file.read()} + content_type = 'multipart/form-data; boundary=%s' % boundary + return content_type, body.replace('\n', '\r\n') + + def _validate_success(self, resp): + html = resp.read() + if resp.status != 200: + raise DataError(resp.reason.strip()) + if 'Successfully uploaded library' not in html: + raise DataError('\n'.join(_ErrorParser(html).errors)) + + +class _ErrorParser(HTMLParser): + + def __init__(self, html): + HTMLParser.__init__(self) + self._inside_errors = False + self.errors = [] + self.feed(html) + self.close() + + def handle_starttag(self, tag, attributes): + if ('class', 'errorlist') in attributes: + self._inside_errors = True + + def handle_endtag(self, tag): + if tag == 'ul': + self._inside_errors = False + + def handle_data(self, data): + if self._inside_errors and data.strip(): + self.errors.append(data) + + +DEFAULT_STYLES = ''' + + +'''.strip() + + +HTML_TEMPLATE = ''' + + +${TITLE} + +${STYLES} + + +

${TITLE}

+ +Version: ${LIB.version}
+ + +Scope: ${LIB.scope}
+ +Named arguments: + +supported + +not supported + + +

Introduction

+
${LIB.htmldoc}
+ + +

Importing

+ + + + + + + + + + + +
ArgumentsDocumentation
${init.argstr}${init.htmldoc}
+ + +

Shortcuts

+ + +

Keywords

+ + + + + + + + + + + + + +
KeywordArgumentsDocumentation
${kw.htmlname}${kw.argstr}${kw.htmldoc}
+ + + +''' + +if __name__ == '__main__': + + def get_format(format, output): + if format: + return format.upper() + if os.path.splitext(output)[1].upper() == '.XML': + return 'XML' + return 'HTML' + + def get_unique_path(base, ext, index=0): + if index == 0: + path = '%s.%s' % (base, ext) + else: + path = '%s-%d.%s' % (base, index, ext) + if os.path.exists(path): + return get_unique_path(base, ext, index+1) + return path + + + try: + argparser = utils.ArgumentParser(__doc__) + opts, args = argparser.parse_args(sys.argv[1:], pythonpath='pythonpath', + help='help', unescape='escape', + check_args=True) + libname = args[0] + library = LibraryDoc(libname, opts['argument'], opts['name'], + opts['version']) + output = opts['output'] or '.' + if _uploading(output): + file_path = os.path.join(tempfile.gettempdir(), 'libdoc_upload.xml') + create_xml_doc(library, file_path) + upload_xml_doc(file_path, output) + os.remove(file_path) + else: + format = get_format(opts['format'], output) + if os.path.isdir(output): + output = get_unique_path(os.path.join(output, library.name), + format.lower()) + output = os.path.abspath(output) + if format == 'HTML': + create_html_doc(library, output, opts['title'], opts['styles']) + else: + create_xml_doc(library, output) + except Information, msg: + print msg + except DataError, err: + print err, '\n\nTry --help for usage information.' + except Exception, err: + print err + else: + print '%s -> %s' % (library.name, output) diff --git a/src/Selenium2Library/keywords/__init__.py b/src/Selenium2Library/keywords/__init__.py index 831d307a0..4ebc4407a 100644 --- a/src/Selenium2Library/keywords/__init__.py +++ b/src/Selenium2Library/keywords/__init__.py @@ -1,25 +1,25 @@ -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 - -__all__ = [ - "_LoggingKeywords", - "_RunOnFailureKeywords", - "_BrowserManagementKeywords", - "_ElementKeywords", - "_TableElementKeywords", - "_FormElementKeywords", - "_SelectElementKeywords", - "_JavaScriptKeywords", - "_CookieKeywords", - "_ScreenshotKeywords", - "_WaitingKeywords" -] +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 + +__all__ = [ + "_LoggingKeywords", + "_RunOnFailureKeywords", + "_BrowserManagementKeywords", + "_ElementKeywords", + "_TableElementKeywords", + "_FormElementKeywords", + "_SelectElementKeywords", + "_JavaScriptKeywords", + "_CookieKeywords", + "_ScreenshotKeywords", + "_WaitingKeywords" +] diff --git a/src/Selenium2Library/keywords/_selectelement.py b/src/Selenium2Library/keywords/_selectelement.py index f5869f924..d0fb5f147 100644 --- a/src/Selenium2Library/keywords/_selectelement.py +++ b/src/Selenium2Library/keywords/_selectelement.py @@ -134,7 +134,7 @@ def page_should_not_contain_list(self, locator, message='', loglevel='INFO'): Key attributes for lists are `id` and `name`. See `introduction` for details about locating elements. """ - self._page_should_not_contain_element(locator, 'list', message, loglevel) + self._page_should_not_contain_element(locator, 'list', message, loglevel) def select_all_from_list(self, locator): """Selects all values from multi-select list identified by `id`. diff --git a/src/Selenium2Library/locators/__init__.py b/src/Selenium2Library/locators/__init__.py index e0a0b3b4f..c7a5d18a7 100644 --- a/src/Selenium2Library/locators/__init__.py +++ b/src/Selenium2Library/locators/__init__.py @@ -1,9 +1,9 @@ -from elementfinder import ElementFinder -from tableelementfinder import TableElementFinder -from windowmanager import WindowManager - -__all__ = [ - "ElementFinder", - "TableElementFinder", - "WindowManager" +from elementfinder import ElementFinder +from tableelementfinder import TableElementFinder +from windowmanager import WindowManager + +__all__ = [ + "ElementFinder", + "TableElementFinder", + "WindowManager" ] \ No newline at end of file diff --git a/src/Selenium2Library/locators/elementfinder.py b/src/Selenium2Library/locators/elementfinder.py index 2d074ec1b..48ac5c169 100644 --- a/src/Selenium2Library/locators/elementfinder.py +++ b/src/Selenium2Library/locators/elementfinder.py @@ -1,23 +1,23 @@ from Selenium2Library import utils -class ElementFinder(object): - - def __init__(self): - self._strategies = { - 'identifier': self._find_by_identifier, - 'id': self._find_by_id, - 'name': self._find_by_name, - 'xpath': self._find_by_xpath, - 'link': self._find_by_link_text, - 'css': self._find_by_css_selector, - 'tag': self._find_by_tag_name, - None: self._find_by_default - } - - def find(self, browser, locator, tag=None): - assert browser is not None - assert locator is not None and len(locator) > 0 - +class ElementFinder(object): + + def __init__(self): + self._strategies = { + 'identifier': self._find_by_identifier, + 'id': self._find_by_id, + 'name': self._find_by_name, + 'xpath': self._find_by_xpath, + 'link': self._find_by_link_text, + 'css': self._find_by_css_selector, + 'tag': self._find_by_tag_name, + None: self._find_by_default + } + + def find(self, browser, locator, tag=None): + assert browser is not None + assert locator is not None and len(locator) > 0 + (prefix, criteria) = self._parse_locator(locator) strategy = self._strategies.get(prefix) if strategy is None: @@ -150,8 +150,8 @@ def _get_base_url(self, browser): url = browser.get_current_url() if '/' in url: url = '/'.join(url.split('/')[:-1]) - return url - + return url + def _parse_locator(self, locator): prefix = None criteria = locator @@ -159,5 +159,5 @@ def _parse_locator(self, locator): locator_parts = locator.partition('=') if len(locator_parts[1]) > 0: prefix = locator_parts[0].strip().lower() - criteria = locator_parts[2].strip() + criteria = locator_parts[2].strip() return (prefix, criteria) diff --git a/src/Selenium2Library/locators/windowmanager.py b/src/Selenium2Library/locators/windowmanager.py index 561725ec7..0a549d136 100644 --- a/src/Selenium2Library/locators/windowmanager.py +++ b/src/Selenium2Library/locators/windowmanager.py @@ -2,22 +2,22 @@ from robot import utils from selenium.common.exceptions import NoSuchWindowException -class WindowManager(object): - - def __init__(self): - self._strategies = { - 'title': self._select_by_title, - 'name': self._select_by_name, - 'url': self._select_by_url, - None: self._select_by_default - } - - def get_window_handles(self, browser): - return browser.get_window_handles() - - def select(self, browser, locator): - assert browser is not None - +class WindowManager(object): + + def __init__(self): + self._strategies = { + 'title': self._select_by_title, + 'name': self._select_by_name, + 'url': self._select_by_url, + None: self._select_by_default + } + + def get_window_handles(self, browser): + return browser.get_window_handles() + + def select(self, browser, locator): + assert browser is not None + (prefix, criteria) = self._parse_locator(locator) strategy = self._strategies.get(prefix) if strategy is None: @@ -61,8 +61,8 @@ def _select_by_default(self, browser, criteria): raise ValueError("Unable to locate window with name or title '" + criteria + "'") - # Private - + # Private + def _parse_locator(self, locator): prefix = None criteria = locator @@ -70,7 +70,7 @@ def _parse_locator(self, locator): locator_parts = locator.partition('=') if len(locator_parts[1]) > 0: prefix = locator_parts[0].strip().lower() - criteria = locator_parts[2].strip() + criteria = locator_parts[2].strip() return (prefix, criteria) def _select_matching(self, browser, matcher, error): diff --git a/src/Selenium2Library/metadata.py b/src/Selenium2Library/metadata.py index 2bc170a7c..ebe391284 100644 --- a/src/Selenium2Library/metadata.py +++ b/src/Selenium2Library/metadata.py @@ -39,7 +39,7 @@ def get_all_packages(): def get_all_package_data(): files = [] for data_dir in DATA_DIRS: - for path, dirnames, filenames in os.walk(os.path.join(ROOT_DIR, data_dir)): + for path, dirnames, filenames in os.walk(os.path.join(ROOT_DIR, data_dir)): files.extend( [ os.path.join(path, filename)[len(ROOT_DIR)+1:] for filename in filenames ] ) return { PACKAGE_NAME: files } diff --git a/src/Selenium2Library/utils/__init__.py b/src/Selenium2Library/utils/__init__.py index d51150bcd..c73348123 100644 --- a/src/Selenium2Library/utils/__init__.py +++ b/src/Selenium2Library/utils/__init__.py @@ -1,7 +1,7 @@ -import os -from fnmatch import fnmatch -from browsercache import BrowserCache - +import os +from fnmatch import fnmatch +from browsercache import BrowserCache + __all__ = [ "get_child_packages_in", "get_module_names_under", diff --git a/src/Selenium2Library/utils/browsercache.py b/src/Selenium2Library/utils/browsercache.py index 9daca4b8e..f05f2f055 100644 --- a/src/Selenium2Library/utils/browsercache.py +++ b/src/Selenium2Library/utils/browsercache.py @@ -1,7 +1,7 @@ from robot.utils import ConnectionCache -class BrowserCache(ConnectionCache): - +class BrowserCache(ConnectionCache): + def __init__(self): ConnectionCache.__init__(self, no_current_msg='No current browser') self._closed = set() @@ -12,22 +12,22 @@ def browsers(self): def get_open_browsers(self): open_browsers = [] - for browser in self._connections: - if browser not in self._closed: + for browser in self._connections: + if browser not in self._closed: open_browsers.append(browser) return open_browsers def close(self): if self.current: browser = self.current - browser.quit() - self.current = self._no_current + browser.quit() + self.current = self._no_current self.current_index = None self._closed.add(browser) - - def close_all(self): - for browser in self._connections: - if browser not in self._closed: - browser.quit() - self.empty_cache() - return self.current + + def close_all(self): + for browser in self._connections: + if browser not in self._closed: + browser.quit() + self.empty_cache() + return self.current diff --git a/test/acceptance/keywords/click_element.txt b/test/acceptance/keywords/click_element.txt index 36b996c30..a799dc950 100644 --- a/test/acceptance/keywords/click_element.txt +++ b/test/acceptance/keywords/click_element.txt @@ -7,11 +7,11 @@ Resource ../resource.txt Click Element [Documentation] LOG 1 Clicking element 'singleClickButton'. Click Element singleClickButton - Element Text Should Be output single clicked - -Double Click Element - [Documentation] LOG 1 Double clicking element 'doubleClickButton'. - Double Click Element doubleClickButton + Element Text Should Be output single clicked + +Double Click Element + [Documentation] LOG 1 Double clicking element 'doubleClickButton'. + Double Click Element doubleClickButton Element Text Should Be output double clicked *** Keywords *** diff --git a/test/acceptance/keywords/elements.txt b/test/acceptance/keywords/elements.txt index 0a51bf7b5..10156cbf7 100644 --- a/test/acceptance/keywords/elements.txt +++ b/test/acceptance/keywords/elements.txt @@ -2,13 +2,13 @@ Suite Setup Go To Page "links.html" Resource ../resource.txt -*** Test Cases *** -Assign Id To Element - [Documentation] Tests also Reload Page keyword. - Page Should Not Contain Element my id - Assign ID to Element xpath=//div[@id="first_div"] my id - Page Should Contain Element my id - Reload Page +*** Test Cases *** +Assign Id To Element + [Documentation] Tests also Reload Page keyword. + Page Should Not Contain Element my id + Assign ID to Element xpath=//div[@id="first_div"] my id + Page Should Contain Element my id + Reload Page Page Should Not Contain Element my id Get Element Attribute diff --git a/test/resources/html/mouse/index.html b/test/resources/html/mouse/index.html index bd4972304..529ccb830 100644 --- a/test/resources/html/mouse/index.html +++ b/test/resources/html/mouse/index.html @@ -1,21 +1,21 @@ - - - Mouse Keyword Testbed - - -
- - - + + + Mouse Keyword Testbed + + +
+ + + \ No newline at end of file diff --git a/test/resources/html/tables/tables.html b/test/resources/html/tables/tables.html index 1f4019c76..ca37a6ef0 100644 --- a/test/resources/html/tables/tables.html +++ b/test/resources/html/tables/tables.html @@ -1,226 +1,226 @@ - - - - - -Tables - - -

Simple Table

- - - - - - - - - - - - - - - - -
simpleTable_A1simpleTable_B1simpleTable_C1
simpleTable_A2simpleTable_B2simpleTable_C2
simpleTable_A3simpleTable_B3simpleTable_C3
-

Simple Table by Name

- - - - - - - - - - - - - - - - -
simpleTableName_A1simpleTableName_B1simpleTableName_C1
simpleTableName_A2simpleTableName_B2simpleTableName_C2
simpleTableName_A3simpleTableName_B3simpleTableName_C3
- -

Simple Table With Nested Table

- - - - - - - - - - - - - - - - -
simpleWithNested_A1simpleWithNested_B1simpleWithNested_C1
simpleWithNested_A2 - - - - - - - - - - - - - - - -
nestedTable_A1nestedTable_B1nestedTable_C1
nestedTable_A2nestedTable_B2nestedTable_C2
nestedTable_A3nestedTable_B3nestedTable_C3
simpleWithNested_C2
simpleWithNested_A3simpleWithNested_B3simpleWithNested_C3
- -

Simple Table With Header

- - - - - - - - - - - - - - - - -
tableWithSingleHeader_A1tableWithSingleHeader_B1tableWithSingleHeader_C1
tableWithSingleHeader_A2tableWithSingleHeader_B2tableWithSingleHeader_C2
tableWithSingleHeader_A3tableWithSingleHeader_B3tableWithSingleHeader_C3
- -

Simple Table With Two Header Rows

- - - - - - - - - - - - - - - - - - - - - -
tableWithTwoHeaders_A1tableWithTwoHeaders_B1tableWithTwoHeaders_C1
tableWithTwoHeaders_A2tableWithTwoHeaders_B2tableWithTwoHeaders_C2
tableWithTwoHeaders_A3tableWithTwoHeaders_B3tableWithTwoHeaders_C3
tableWithTwoHeaders_A4tableWithTwoHeaders_B4tableWithTwoHeaders_C4
- -

Table with thead, tfoot and tbody sections

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
withHeadAndFoot_AH1withHeadAndFoot_BH1withHeadAndFoot_CH1
withHeadAndFoot_AH2withHeadAndFoot_BH2withHeadAndFoot_CH2
withHeadAndFoot_AF1withHeadAndFoot_BF1withHeadAndFoot_CF1
withHeadAndFoot_AF2withHeadAndFoot_BF2withHeadAndFoot_CF2
withHeadAndFoot_A1withHeadAndFoot_B1withHeadAndFoot_C1
withHeadAndFoot_A2withHeadAndFoot_B2withHeadAndFoot_C2
withHeadAndFoot_A3withHeadAndFoot_B3withHeadAndFoot_C3
- -

Table With Merged Cells In a Row

- - - - - - - - - - - - - - - -
mergedRows_A1mergedRows_B1mergedRows_C1mergedRows_D1
mergedRows_B2mergedRows_C2
mergedRows_A3mergedRows_C3
- -

Table With Merged Cells In a Column

- - - - - - - - - - - - - - - - - -
mergedCols_A1mergedCols_C1
mergedCols_A2mergedCols_B2
mergedCols_A3mergedCols_B3mergedCols_C3
mergedCols_D1
- -

Table With Formatting and Unicode

-
dummy Table
-
dummy Table
- - - - - - - - - - - - - -
formattedTable_A1formattedTable_B1formattedTable_C1formattedTable_D1

formattedTable_A2

formattedTable_B2formattedTable_ÄÖÜäöüßäöü€&äöü€&
- - + + + + + +Tables + + +

Simple Table

+ + + + + + + + + + + + + + + + +
simpleTable_A1simpleTable_B1simpleTable_C1
simpleTable_A2simpleTable_B2simpleTable_C2
simpleTable_A3simpleTable_B3simpleTable_C3
+

Simple Table by Name

+ + + + + + + + + + + + + + + + +
simpleTableName_A1simpleTableName_B1simpleTableName_C1
simpleTableName_A2simpleTableName_B2simpleTableName_C2
simpleTableName_A3simpleTableName_B3simpleTableName_C3
+ +

Simple Table With Nested Table

+ + + + + + + + + + + + + + + + +
simpleWithNested_A1simpleWithNested_B1simpleWithNested_C1
simpleWithNested_A2 + + + + + + + + + + + + + + + +
nestedTable_A1nestedTable_B1nestedTable_C1
nestedTable_A2nestedTable_B2nestedTable_C2
nestedTable_A3nestedTable_B3nestedTable_C3
simpleWithNested_C2
simpleWithNested_A3simpleWithNested_B3simpleWithNested_C3
+ +

Simple Table With Header

+ + + + + + + + + + + + + + + + +
tableWithSingleHeader_A1tableWithSingleHeader_B1tableWithSingleHeader_C1
tableWithSingleHeader_A2tableWithSingleHeader_B2tableWithSingleHeader_C2
tableWithSingleHeader_A3tableWithSingleHeader_B3tableWithSingleHeader_C3
+ +

Simple Table With Two Header Rows

+ + + + + + + + + + + + + + + + + + + + + +
tableWithTwoHeaders_A1tableWithTwoHeaders_B1tableWithTwoHeaders_C1
tableWithTwoHeaders_A2tableWithTwoHeaders_B2tableWithTwoHeaders_C2
tableWithTwoHeaders_A3tableWithTwoHeaders_B3tableWithTwoHeaders_C3
tableWithTwoHeaders_A4tableWithTwoHeaders_B4tableWithTwoHeaders_C4
+ +

Table with thead, tfoot and tbody sections

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
withHeadAndFoot_AH1withHeadAndFoot_BH1withHeadAndFoot_CH1
withHeadAndFoot_AH2withHeadAndFoot_BH2withHeadAndFoot_CH2
withHeadAndFoot_AF1withHeadAndFoot_BF1withHeadAndFoot_CF1
withHeadAndFoot_AF2withHeadAndFoot_BF2withHeadAndFoot_CF2
withHeadAndFoot_A1withHeadAndFoot_B1withHeadAndFoot_C1
withHeadAndFoot_A2withHeadAndFoot_B2withHeadAndFoot_C2
withHeadAndFoot_A3withHeadAndFoot_B3withHeadAndFoot_C3
+ +

Table With Merged Cells In a Row

+ + + + + + + + + + + + + + + +
mergedRows_A1mergedRows_B1mergedRows_C1mergedRows_D1
mergedRows_B2mergedRows_C2
mergedRows_A3mergedRows_C3
+ +

Table With Merged Cells In a Column

+ + + + + + + + + + + + + + + + + +
mergedCols_A1mergedCols_C1
mergedCols_A2mergedCols_B2
mergedCols_A3mergedCols_B3mergedCols_C3
mergedCols_D1
+ +

Table With Formatting and Unicode

+
dummy Table
+
dummy Table
+ + + + + + + + + + + + + +
formattedTable_A1formattedTable_B1formattedTable_C1formattedTable_D1

formattedTable_A2

formattedTable_B2formattedTable_ÄÖÜäöüßäöü€&äöü€&
+ + \ No newline at end of file diff --git a/test/resources/html/visibility.html b/test/resources/html/visibility.html index d4e15fd3e..7f2efb5b2 100644 --- a/test/resources/html/visibility.html +++ b/test/resources/html/visibility.html @@ -1,9 +1,9 @@ - - - Visibility Keyword Testbed - - -
nothing special
- - + + + Visibility Keyword Testbed + + +
nothing special
+ + \ No newline at end of file diff --git a/test/unit/locators/test_elementfinder.py b/test/unit/locators/test_elementfinder.py index 554c2c6b0..e40f8a5ba 100644 --- a/test/unit/locators/test_elementfinder.py +++ b/test/unit/locators/test_elementfinder.py @@ -1,327 +1,327 @@ -import unittest +import unittest import os -from Selenium2Library.locators import ElementFinder -from mockito import * - -class ElementFinderTests(unittest.TestCase): - - def test_find_with_invalid_prefix(self): - finder = ElementFinder() - browser = mock() - with self.assertRaises(ValueError) as context: - finder.find(browser, "something=test1") - self.assertEqual(context.exception.message, "Element locator with prefix 'something' is not supported") - - def test_find_with_null_browser(self): - finder = ElementFinder() - with self.assertRaises(AssertionError): - finder.find(None, "id=test1") - - def test_find_with_null_locator(self): - finder = ElementFinder() - browser = mock() - with self.assertRaises(AssertionError): - finder.find(browser, None) - - def test_find_with_empty_locator(self): - finder = ElementFinder() - browser = mock() - with self.assertRaises(AssertionError): - finder.find(browser, "") - - def test_find_with_no_tag(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test1") - verify(browser).find_elements_by_xpath("//*[(@id='test1' or @name='test1')]") - - def test_find_with_tag(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test1", tag='div') - verify(browser).find_elements_by_xpath("//div[(@id='test1' or @name='test1')]") - - def test_find_with_locator_with_apos(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test '1'") - verify(browser).find_elements_by_xpath("//*[(@id=\"test '1'\" or @name=\"test '1'\")]") - - def test_find_with_locator_with_quote(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test \"1\"") - verify(browser).find_elements_by_xpath("//*[(@id='test \"1\"' or @name='test \"1\"')]") - - def test_find_with_locator_with_quote_and_apos(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test \"1\" and '2'") - verify(browser).find_elements_by_xpath( - "//*[(@id=concat('test \"1\" and ', \"'\", '2', \"'\", '') or @name=concat('test \"1\" and ', \"'\", '2', \"'\", ''))]") - - def test_find_with_a(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='a') - verify(browser).find_elements_by_xpath( - "//a[(@id='test1' or @name='test1' or @href='test1' or normalize-space(descendant-or-self::text())='test1' or @href='http://localhost/test1')]") - - def test_find_with_link_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='link') - verify(browser).find_elements_by_xpath( - "//a[(@id='test1' or @name='test1' or @href='test1' or normalize-space(descendant-or-self::text())='test1' or @href='http://localhost/test1')]") - - def test_find_with_img(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='img') - verify(browser).find_elements_by_xpath( - "//img[(@id='test1' or @name='test1' or @src='test1' or @alt='test1' or @src='http://localhost/test1')]") - - def test_find_with_image_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='image') - verify(browser).find_elements_by_xpath( - "//img[(@id='test1' or @name='test1' or @src='test1' or @alt='test1' or @src='http://localhost/test1')]") - - def test_find_with_input(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='input') - verify(browser).find_elements_by_xpath( - "//input[(@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") - - def test_find_with_radio_button_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='radio button') - verify(browser).find_elements_by_xpath( - "//input[@type='radio' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") - - def test_find_with_checkbox_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='checkbox') - verify(browser).find_elements_by_xpath( - "//input[@type='checkbox' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") - - def test_find_with_file_upload_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='file upload') - verify(browser).find_elements_by_xpath( - "//input[@type='file' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") - - def test_find_with_text_field_synonym(self): - finder = ElementFinder() - browser = mock() - when(browser).get_current_url().thenReturn("http://localhost/mypage.html") - finder.find(browser, "test1", tag='text field') - verify(browser).find_elements_by_xpath( - "//input[@type='text' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") - - def test_find_with_button(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test1", tag='button') - verify(browser).find_elements_by_xpath( - "//button[(@id='test1' or @name='test1' or @value='test1' or normalize-space(descendant-or-self::text())='test1')]") - - def test_find_with_select(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test1", tag='select') - verify(browser).find_elements_by_xpath( - "//select[(@id='test1' or @name='test1')]") - - def test_find_with_list_synonym(self): - finder = ElementFinder() - browser = mock() - finder.find(browser, "test1", tag='list') - verify(browser).find_elements_by_xpath( - "//select[(@id='test1' or @name='test1')]") - - def test_find_with_implicit_xpath(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_xpath("//*[(@test='1')]").thenReturn(elements) - - result = finder.find(browser, "//*[(@test='1')]") - self.assertEqual(result, elements) - result = finder.find(browser, "//*[(@test='1')]", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_identifier(self): - finder = ElementFinder() - browser = mock() - - id_elements = self._make_mock_elements('div', 'a') - name_elements = self._make_mock_elements('span', 'a') - when(browser).find_elements_by_id("test1").thenReturn(list(id_elements)).thenReturn(list(id_elements)) - when(browser).find_elements_by_name("test1").thenReturn(list(name_elements)).thenReturn(list(name_elements)) - - all_elements = list(id_elements) - all_elements.extend(name_elements) - - result = finder.find(browser, "identifier=test1") - self.assertEqual(result, all_elements) - result = finder.find(browser, "identifier=test1", tag='a') - self.assertEqual(result, [id_elements[1], name_elements[1]]) - - def test_find_by_id(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_id("test1").thenReturn(elements) - - result = finder.find(browser, "id=test1") - self.assertEqual(result, elements) - result = finder.find(browser, "id=test1", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_name(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_name("test1").thenReturn(elements) - - result = finder.find(browser, "name=test1") - self.assertEqual(result, elements) - result = finder.find(browser, "name=test1", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_xpath(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_xpath("//*[(@test='1')]").thenReturn(elements) - - result = finder.find(browser, "xpath=//*[(@test='1')]") - self.assertEqual(result, elements) - result = finder.find(browser, "xpath=//*[(@test='1')]", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_link_text(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_link_text("my link").thenReturn(elements) - - result = finder.find(browser, "link=my link") - self.assertEqual(result, elements) - result = finder.find(browser, "link=my link", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_css_selector(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_css_selector("#test1").thenReturn(elements) - - result = finder.find(browser, "css=#test1") - self.assertEqual(result, elements) - result = finder.find(browser, "css=#test1", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_by_tag_name(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_tag_name("div").thenReturn(elements) - - result = finder.find(browser, "tag=div") - self.assertEqual(result, elements) - result = finder.find(browser, "tag=div", tag='a') - self.assertEqual(result, [elements[1], elements[3]]) - - def test_find_with_sloppy_prefix(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_id("test1").thenReturn(elements) - - result = finder.find(browser, "ID=test1") - self.assertEqual(result, elements) - result = finder.find(browser, "iD=test1") - self.assertEqual(result, elements) - result = finder.find(browser, "id=test1") - self.assertEqual(result, elements) - result = finder.find(browser, " id =test1") - self.assertEqual(result, elements) - - def test_find_with_sloppy_criteria(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'a', 'span', 'a') - when(browser).find_elements_by_id("test1").thenReturn(elements) - - result = finder.find(browser, "id= test1 ") - self.assertEqual(result, elements) - - def test_find_by_id_with_synonym_and_constraints(self): - finder = ElementFinder() - browser = mock() - - elements = self._make_mock_elements('div', 'input', 'span', 'input', 'a', 'input', 'div', 'input') - elements[1].set_attribute('type', 'radio') - elements[3].set_attribute('type', 'checkbox') - elements[5].set_attribute('type', 'text') - elements[7].set_attribute('type', 'file') - when(browser).find_elements_by_id("test1").thenReturn(elements) - - result = finder.find(browser, "id=test1") - self.assertEqual(result, elements) - result = finder.find(browser, "id=test1", tag='input') - self.assertEqual(result, [elements[1], elements[3], elements[5], elements[7]]) - result = finder.find(browser, "id=test1", tag='radio button') - self.assertEqual(result, [elements[1]]) - result = finder.find(browser, "id=test1", tag='checkbox') - self.assertEqual(result, [elements[3]]) - result = finder.find(browser, "id=test1", tag='text field') - self.assertEqual(result, [elements[5]]) - result = finder.find(browser, "id=test1", tag='file upload') - self.assertEqual(result, [elements[7]]) - - def _make_mock_elements(self, *tags): - elements = [] - for tag in tags: - element = self._make_mock_element(tag) - elements.append(element) - return elements - - def _make_mock_element(self, tag): - element = mock() - element.tag_name = tag - element.attributes = {} - - def set_attribute(name, value): - element.attributes[name] = value - element.set_attribute = set_attribute - - def get_attribute(name): - return element.attributes[name] - element.get_attribute = get_attribute - - return element +from Selenium2Library.locators import ElementFinder +from mockito import * + +class ElementFinderTests(unittest.TestCase): + + def test_find_with_invalid_prefix(self): + finder = ElementFinder() + browser = mock() + with self.assertRaises(ValueError) as context: + finder.find(browser, "something=test1") + self.assertEqual(context.exception.message, "Element locator with prefix 'something' is not supported") + + def test_find_with_null_browser(self): + finder = ElementFinder() + with self.assertRaises(AssertionError): + finder.find(None, "id=test1") + + def test_find_with_null_locator(self): + finder = ElementFinder() + browser = mock() + with self.assertRaises(AssertionError): + finder.find(browser, None) + + def test_find_with_empty_locator(self): + finder = ElementFinder() + browser = mock() + with self.assertRaises(AssertionError): + finder.find(browser, "") + + def test_find_with_no_tag(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test1") + verify(browser).find_elements_by_xpath("//*[(@id='test1' or @name='test1')]") + + def test_find_with_tag(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test1", tag='div') + verify(browser).find_elements_by_xpath("//div[(@id='test1' or @name='test1')]") + + def test_find_with_locator_with_apos(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test '1'") + verify(browser).find_elements_by_xpath("//*[(@id=\"test '1'\" or @name=\"test '1'\")]") + + def test_find_with_locator_with_quote(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test \"1\"") + verify(browser).find_elements_by_xpath("//*[(@id='test \"1\"' or @name='test \"1\"')]") + + def test_find_with_locator_with_quote_and_apos(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test \"1\" and '2'") + verify(browser).find_elements_by_xpath( + "//*[(@id=concat('test \"1\" and ', \"'\", '2', \"'\", '') or @name=concat('test \"1\" and ', \"'\", '2', \"'\", ''))]") + + def test_find_with_a(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='a') + verify(browser).find_elements_by_xpath( + "//a[(@id='test1' or @name='test1' or @href='test1' or normalize-space(descendant-or-self::text())='test1' or @href='http://localhost/test1')]") + + def test_find_with_link_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='link') + verify(browser).find_elements_by_xpath( + "//a[(@id='test1' or @name='test1' or @href='test1' or normalize-space(descendant-or-self::text())='test1' or @href='http://localhost/test1')]") + + def test_find_with_img(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='img') + verify(browser).find_elements_by_xpath( + "//img[(@id='test1' or @name='test1' or @src='test1' or @alt='test1' or @src='http://localhost/test1')]") + + def test_find_with_image_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='image') + verify(browser).find_elements_by_xpath( + "//img[(@id='test1' or @name='test1' or @src='test1' or @alt='test1' or @src='http://localhost/test1')]") + + def test_find_with_input(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='input') + verify(browser).find_elements_by_xpath( + "//input[(@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") + + def test_find_with_radio_button_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='radio button') + verify(browser).find_elements_by_xpath( + "//input[@type='radio' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") + + def test_find_with_checkbox_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='checkbox') + verify(browser).find_elements_by_xpath( + "//input[@type='checkbox' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") + + def test_find_with_file_upload_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='file upload') + verify(browser).find_elements_by_xpath( + "//input[@type='file' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") + + def test_find_with_text_field_synonym(self): + finder = ElementFinder() + browser = mock() + when(browser).get_current_url().thenReturn("http://localhost/mypage.html") + finder.find(browser, "test1", tag='text field') + verify(browser).find_elements_by_xpath( + "//input[@type='text' and (@id='test1' or @name='test1' or @value='test1' or @src='test1' or @src='http://localhost/test1')]") + + def test_find_with_button(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test1", tag='button') + verify(browser).find_elements_by_xpath( + "//button[(@id='test1' or @name='test1' or @value='test1' or normalize-space(descendant-or-self::text())='test1')]") + + def test_find_with_select(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test1", tag='select') + verify(browser).find_elements_by_xpath( + "//select[(@id='test1' or @name='test1')]") + + def test_find_with_list_synonym(self): + finder = ElementFinder() + browser = mock() + finder.find(browser, "test1", tag='list') + verify(browser).find_elements_by_xpath( + "//select[(@id='test1' or @name='test1')]") + + def test_find_with_implicit_xpath(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_xpath("//*[(@test='1')]").thenReturn(elements) + + result = finder.find(browser, "//*[(@test='1')]") + self.assertEqual(result, elements) + result = finder.find(browser, "//*[(@test='1')]", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_identifier(self): + finder = ElementFinder() + browser = mock() + + id_elements = self._make_mock_elements('div', 'a') + name_elements = self._make_mock_elements('span', 'a') + when(browser).find_elements_by_id("test1").thenReturn(list(id_elements)).thenReturn(list(id_elements)) + when(browser).find_elements_by_name("test1").thenReturn(list(name_elements)).thenReturn(list(name_elements)) + + all_elements = list(id_elements) + all_elements.extend(name_elements) + + result = finder.find(browser, "identifier=test1") + self.assertEqual(result, all_elements) + result = finder.find(browser, "identifier=test1", tag='a') + self.assertEqual(result, [id_elements[1], name_elements[1]]) + + def test_find_by_id(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_id("test1").thenReturn(elements) + + result = finder.find(browser, "id=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "id=test1", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_name(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_name("test1").thenReturn(elements) + + result = finder.find(browser, "name=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "name=test1", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_xpath(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_xpath("//*[(@test='1')]").thenReturn(elements) + + result = finder.find(browser, "xpath=//*[(@test='1')]") + self.assertEqual(result, elements) + result = finder.find(browser, "xpath=//*[(@test='1')]", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_link_text(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_link_text("my link").thenReturn(elements) + + result = finder.find(browser, "link=my link") + self.assertEqual(result, elements) + result = finder.find(browser, "link=my link", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_css_selector(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_css_selector("#test1").thenReturn(elements) + + result = finder.find(browser, "css=#test1") + self.assertEqual(result, elements) + result = finder.find(browser, "css=#test1", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_by_tag_name(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_tag_name("div").thenReturn(elements) + + result = finder.find(browser, "tag=div") + self.assertEqual(result, elements) + result = finder.find(browser, "tag=div", tag='a') + self.assertEqual(result, [elements[1], elements[3]]) + + def test_find_with_sloppy_prefix(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_id("test1").thenReturn(elements) + + result = finder.find(browser, "ID=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "iD=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "id=test1") + self.assertEqual(result, elements) + result = finder.find(browser, " id =test1") + self.assertEqual(result, elements) + + def test_find_with_sloppy_criteria(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'a', 'span', 'a') + when(browser).find_elements_by_id("test1").thenReturn(elements) + + result = finder.find(browser, "id= test1 ") + self.assertEqual(result, elements) + + def test_find_by_id_with_synonym_and_constraints(self): + finder = ElementFinder() + browser = mock() + + elements = self._make_mock_elements('div', 'input', 'span', 'input', 'a', 'input', 'div', 'input') + elements[1].set_attribute('type', 'radio') + elements[3].set_attribute('type', 'checkbox') + elements[5].set_attribute('type', 'text') + elements[7].set_attribute('type', 'file') + when(browser).find_elements_by_id("test1").thenReturn(elements) + + result = finder.find(browser, "id=test1") + self.assertEqual(result, elements) + result = finder.find(browser, "id=test1", tag='input') + self.assertEqual(result, [elements[1], elements[3], elements[5], elements[7]]) + result = finder.find(browser, "id=test1", tag='radio button') + self.assertEqual(result, [elements[1]]) + result = finder.find(browser, "id=test1", tag='checkbox') + self.assertEqual(result, [elements[3]]) + result = finder.find(browser, "id=test1", tag='text field') + self.assertEqual(result, [elements[5]]) + result = finder.find(browser, "id=test1", tag='file upload') + self.assertEqual(result, [elements[7]]) + + def _make_mock_elements(self, *tags): + elements = [] + for tag in tags: + element = self._make_mock_element(tag) + elements.append(element) + return elements + + def _make_mock_element(self, tag): + element = mock() + element.tag_name = tag + element.attributes = {} + + def set_attribute(name, value): + element.attributes[name] = value + element.set_attribute = set_attribute + + def get_attribute(name): + return element.attributes[name] + element.get_attribute = get_attribute + + return element diff --git a/test/unit/locators/test_tableelementfinder.py b/test/unit/locators/test_tableelementfinder.py index 16801bcf4..649c49fdf 100644 --- a/test/unit/locators/test_tableelementfinder.py +++ b/test/unit/locators/test_tableelementfinder.py @@ -1,179 +1,179 @@ -import unittest -from Selenium2Library.locators import TableElementFinder -from mockito import * - -class ElementFinderTests(unittest.TestCase): - - def test_find_with_implicit_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1").thenReturn([]) - - finder.find(browser, "test1") - - verify(browser).find_elements_by_css_selector("table#test1") - - def test_find_with_css_selector(self): - finder = TableElementFinder() - browser = mock() - elements = self._make_mock_elements('table', 'table', 'table') - when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) - - self.assertEqual( - finder.find(browser, "css=table#test1"), - elements[0]) - - verify(browser).find_elements_by_css_selector("table#test1") - - def test_find_with_xpath_selector(self): - finder = TableElementFinder() - browser = mock() - elements = self._make_mock_elements('table', 'table', 'table') - when(browser).find_elements_by_xpath("//table[@id='test1']").thenReturn(elements) - - self.assertEqual( - finder.find(browser, "xpath=//table[@id='test1']"), - elements[0]) - - verify(browser).find_elements_by_xpath("//table[@id='test1']") - - def test_find_with_content_constraint(self): - finder = TableElementFinder() - browser = mock() - elements = self._make_mock_elements('td', 'td', 'td') - elements[1].text = 'hi' - when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) - - self.assertEqual( - finder.find_by_content(browser, "test1", 'hi'), - elements[1]) - - verify(browser).find_elements_by_css_selector("table#test1") - - def test_find_with_null_content_constraint(self): - finder = TableElementFinder() - browser = mock() - elements = self._make_mock_elements('td', 'td', 'td') - elements[1].text = 'hi' - when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) - - self.assertEqual( - finder.find_by_content(browser, "test1", None), - elements[0]) - - verify(browser).find_elements_by_css_selector("table#test1") - - def test_find_by_content_with_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1").thenReturn([]) - - finder.find_by_content(browser, "css=table#test1", 'hi') - - verify(browser).find_elements_by_css_selector("table#test1") - - def test_find_by_content_with_xpath_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_xpath("//table[@id='test1']//*").thenReturn([]) - - finder.find_by_content(browser, "xpath=//table[@id='test1']", 'hi') - - verify(browser).find_elements_by_xpath("//table[@id='test1']//*") - - def test_find_by_header_with_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1 th").thenReturn([]) - - finder.find_by_header(browser, "css=table#test1", 'hi') - - verify(browser).find_elements_by_css_selector("table#test1 th") - - def test_find_by_header_with_xpath_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_xpath("//table[@id='test1']//th").thenReturn([]) - - finder.find_by_header(browser, "xpath=//table[@id='test1']", 'hi') - - verify(browser).find_elements_by_xpath("//table[@id='test1']//th") - - def test_find_by_footer_with_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1 tfoot td").thenReturn([]) - - finder.find_by_footer(browser, "css=table#test1", 'hi') - - verify(browser).find_elements_by_css_selector("table#test1 tfoot td") - - def test_find_by_footer_with_xpath_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_xpath("//table[@id='test1']//tfoot//td").thenReturn([]) - - finder.find_by_footer(browser, "xpath=//table[@id='test1']", 'hi') - - verify(browser).find_elements_by_xpath("//table[@id='test1']//tfoot//td") - - def test_find_by_row_with_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1 tr:nth-child(2)").thenReturn([]) - - finder.find_by_row(browser, "css=table#test1", 2, 'hi') - - verify(browser).find_elements_by_css_selector("table#test1 tr:nth-child(2)") - - def test_find_by_row_with_xpath_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_xpath("//table[@id='test1']//tr[2]//*").thenReturn([]) - - finder.find_by_row(browser, "xpath=//table[@id='test1']", 2, 'hi') - - verify(browser).find_elements_by_xpath("//table[@id='test1']//tr[2]//*") - - def test_find_by_col_with_css_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_css_selector("table#test1 tr td:nth-child(2)").thenReturn([]) - when(browser).find_elements_by_css_selector("table#test1 tr th:nth-child(2)").thenReturn([]) - - finder.find_by_col(browser, "css=table#test1", 2, 'hi') - - verify(browser).find_elements_by_css_selector("table#test1 tr td:nth-child(2)") - verify(browser).find_elements_by_css_selector("table#test1 tr th:nth-child(2)") - - def test_find_by_col_with_xpath_locator(self): - finder = TableElementFinder() - browser = mock() - when(browser).find_elements_by_xpath("//table[@id='test1']//tr//*[self::td or self::th][2]").thenReturn([]) - - finder.find_by_col(browser, "xpath=//table[@id='test1']", 2, 'hi') - - verify(browser).find_elements_by_xpath("//table[@id='test1']//tr//*[self::td or self::th][2]") - - def _make_mock_elements(self, *tags): - elements = [] - for tag in tags: - element = self._make_mock_element(tag) - elements.append(element) - return elements - - def _make_mock_element(self, tag): - element = mock() - element.tag_name = tag - element.attributes = {} - element.text = None - - def set_attribute(name, value): - element.attributes[name] = value - element.set_attribute = set_attribute - - def get_attribute(name): - return element.attributes[name] - element.get_attribute = get_attribute - - return element +import unittest +from Selenium2Library.locators import TableElementFinder +from mockito import * + +class ElementFinderTests(unittest.TestCase): + + def test_find_with_implicit_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1").thenReturn([]) + + finder.find(browser, "test1") + + verify(browser).find_elements_by_css_selector("table#test1") + + def test_find_with_css_selector(self): + finder = TableElementFinder() + browser = mock() + elements = self._make_mock_elements('table', 'table', 'table') + when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) + + self.assertEqual( + finder.find(browser, "css=table#test1"), + elements[0]) + + verify(browser).find_elements_by_css_selector("table#test1") + + def test_find_with_xpath_selector(self): + finder = TableElementFinder() + browser = mock() + elements = self._make_mock_elements('table', 'table', 'table') + when(browser).find_elements_by_xpath("//table[@id='test1']").thenReturn(elements) + + self.assertEqual( + finder.find(browser, "xpath=//table[@id='test1']"), + elements[0]) + + verify(browser).find_elements_by_xpath("//table[@id='test1']") + + def test_find_with_content_constraint(self): + finder = TableElementFinder() + browser = mock() + elements = self._make_mock_elements('td', 'td', 'td') + elements[1].text = 'hi' + when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) + + self.assertEqual( + finder.find_by_content(browser, "test1", 'hi'), + elements[1]) + + verify(browser).find_elements_by_css_selector("table#test1") + + def test_find_with_null_content_constraint(self): + finder = TableElementFinder() + browser = mock() + elements = self._make_mock_elements('td', 'td', 'td') + elements[1].text = 'hi' + when(browser).find_elements_by_css_selector("table#test1").thenReturn(elements) + + self.assertEqual( + finder.find_by_content(browser, "test1", None), + elements[0]) + + verify(browser).find_elements_by_css_selector("table#test1") + + def test_find_by_content_with_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1").thenReturn([]) + + finder.find_by_content(browser, "css=table#test1", 'hi') + + verify(browser).find_elements_by_css_selector("table#test1") + + def test_find_by_content_with_xpath_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_xpath("//table[@id='test1']//*").thenReturn([]) + + finder.find_by_content(browser, "xpath=//table[@id='test1']", 'hi') + + verify(browser).find_elements_by_xpath("//table[@id='test1']//*") + + def test_find_by_header_with_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1 th").thenReturn([]) + + finder.find_by_header(browser, "css=table#test1", 'hi') + + verify(browser).find_elements_by_css_selector("table#test1 th") + + def test_find_by_header_with_xpath_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_xpath("//table[@id='test1']//th").thenReturn([]) + + finder.find_by_header(browser, "xpath=//table[@id='test1']", 'hi') + + verify(browser).find_elements_by_xpath("//table[@id='test1']//th") + + def test_find_by_footer_with_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1 tfoot td").thenReturn([]) + + finder.find_by_footer(browser, "css=table#test1", 'hi') + + verify(browser).find_elements_by_css_selector("table#test1 tfoot td") + + def test_find_by_footer_with_xpath_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_xpath("//table[@id='test1']//tfoot//td").thenReturn([]) + + finder.find_by_footer(browser, "xpath=//table[@id='test1']", 'hi') + + verify(browser).find_elements_by_xpath("//table[@id='test1']//tfoot//td") + + def test_find_by_row_with_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1 tr:nth-child(2)").thenReturn([]) + + finder.find_by_row(browser, "css=table#test1", 2, 'hi') + + verify(browser).find_elements_by_css_selector("table#test1 tr:nth-child(2)") + + def test_find_by_row_with_xpath_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_xpath("//table[@id='test1']//tr[2]//*").thenReturn([]) + + finder.find_by_row(browser, "xpath=//table[@id='test1']", 2, 'hi') + + verify(browser).find_elements_by_xpath("//table[@id='test1']//tr[2]//*") + + def test_find_by_col_with_css_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_css_selector("table#test1 tr td:nth-child(2)").thenReturn([]) + when(browser).find_elements_by_css_selector("table#test1 tr th:nth-child(2)").thenReturn([]) + + finder.find_by_col(browser, "css=table#test1", 2, 'hi') + + verify(browser).find_elements_by_css_selector("table#test1 tr td:nth-child(2)") + verify(browser).find_elements_by_css_selector("table#test1 tr th:nth-child(2)") + + def test_find_by_col_with_xpath_locator(self): + finder = TableElementFinder() + browser = mock() + when(browser).find_elements_by_xpath("//table[@id='test1']//tr//*[self::td or self::th][2]").thenReturn([]) + + finder.find_by_col(browser, "xpath=//table[@id='test1']", 2, 'hi') + + verify(browser).find_elements_by_xpath("//table[@id='test1']//tr//*[self::td or self::th][2]") + + def _make_mock_elements(self, *tags): + elements = [] + for tag in tags: + element = self._make_mock_element(tag) + elements.append(element) + return elements + + def _make_mock_element(self, tag): + element = mock() + element.tag_name = tag + element.attributes = {} + element.text = None + + def set_attribute(name, value): + element.attributes[name] = value + element.set_attribute = set_attribute + + def get_attribute(name): + return element.attributes[name] + element.get_attribute = get_attribute + + return element diff --git a/test/unit/locators/test_windowmanager.py b/test/unit/locators/test_windowmanager.py index 2b7b6df54..f6491994e 100644 --- a/test/unit/locators/test_windowmanager.py +++ b/test/unit/locators/test_windowmanager.py @@ -1,279 +1,279 @@ -import unittest +import unittest import os -from Selenium2Library.locators import WindowManager -from mockito import * +from Selenium2Library.locators import WindowManager +from mockito import * import uuid -from selenium.common.exceptions import NoSuchWindowException - -class WindowManagerTests(unittest.TestCase): - - def test_select_with_invalid_prefix(self): - manager = WindowManager() - browser = mock() - with self.assertRaises(ValueError) as context: - manager.select(browser, "something=test1") - self.assertEqual(context.exception.message, "Window locator with prefix 'something' is not supported") - - def test_select_with_null_browser(self): - manager = WindowManager() - with self.assertRaises(AssertionError): - manager.select(None, "name=test1") - - def test_select_by_title(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "title=Title 2") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_title_sloppy_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "title= tItLe 2 ") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_title_with_multiple_matches(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2a', 'title': "Title 2", 'url': 'http://localhost/page2a.html' }, - { 'name': 'win2b', 'title': "Title 2", 'url': 'http://localhost/page2b.html' }) - - manager.select(browser, "title=Title 2") - self.assertEqual(browser.current_window.name, 'win2a') - - def test_select_by_title_no_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - with self.assertRaises(ValueError) as context: - manager.select(browser, "title=Title -1") - self.assertEqual(context.exception.message, "Unable to locate window with title 'Title -1'") - - def test_select_by_name(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name=win2") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_name_sloppy_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name= win2 ") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_name_with_bad_case(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - with self.assertRaises(ValueError) as context: - manager.select(browser, "name=Win2") - self.assertEqual(context.exception.message, "Unable to locate window with name 'Win2'") - - def test_select_by_name_no_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - with self.assertRaises(ValueError) as context: - manager.select(browser, "name=win-1") - self.assertEqual(context.exception.message, "Unable to locate window with name 'win-1'") - - def test_select_by_url(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "url=http://localhost/page2.html") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_url_sloppy_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "url= http://LOCALHOST/page2.html ") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_url_with_multiple_matches(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2a', 'title': "Title 2a", 'url': 'http://localhost/page2.html' }, - { 'name': 'win2b', 'title': "Title 2b", 'url': 'http://localhost/page2.html' }) - - manager.select(browser, "url=http://localhost/page2.html") - self.assertEqual(browser.current_window.name, 'win2a') - - def test_select_by_url_no_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - with self.assertRaises(ValueError) as context: - manager.select(browser, "url=http://localhost/page-1.html") - self.assertEqual(context.exception.message, "Unable to locate window with URL 'http://localhost/page-1.html'") - - def test_select_with_null_locator(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name=win2") - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, None) - self.assertEqual(browser.current_window.name, 'win1') - - def test_select_with_null_string_locator(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name=win2") - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, "null") - self.assertEqual(browser.current_window.name, 'win1') - - def test_select_with_empty_locator(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name=win2") - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, "") - self.assertEqual(browser.current_window.name, 'win1') - - def test_select_by_default_with_name(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "win2") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_default_with_title(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "Title 2") - self.assertEqual(browser.current_window.name, 'win2') - - def test_select_by_default_no_match(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - with self.assertRaises(ValueError) as context: - manager.select(browser, "win-1") - self.assertEqual(context.exception.message, "Unable to locate window with name or title 'win-1'") - - def test_select_with_sloppy_prefix(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - manager.select(browser, "name=win2") - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, "nAmE=win2") - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, " name =win2") - self.assertEqual(browser.current_window.name, 'win2') - - def test_get_window_handles(self): - manager = WindowManager() - browser = self._make_mock_browser( - { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, - { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, - { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) - - window_handles = manager.get_window_handles(browser) - self.assertEqual(len(window_handles), 3) - manager.select(browser, window_handles[1]) - self.assertEqual(browser.current_window.name, 'win2') - manager.select(browser, window_handles[2]) - self.assertEqual(browser.current_window.name, 'win3') - manager.select(browser, window_handles[0]) - self.assertEqual(browser.current_window.name, 'win1') - - def _make_mock_browser(self, *window_specs): - browser = mock() - - windows = [] - window_handles = [] - first_window = None - for window_spec in window_specs: - window = mock() - window.handle = uuid.uuid4().hex - window.name = window_spec['name'] - window.title = window_spec['title'] - window.url = window_spec['url'] - - windows.append(window) - window_handles.append(window.handle) - - if first_window is None: - first_window = window - - def switch_to_window(handle_or_name): - if handle_or_name == '': - browser.current_window = first_window - return - for window in windows: - if window.handle == handle_or_name or window.name == handle_or_name: - browser.current_window = window - return - raise NoSuchWindowException(u'Unable to locate window "' + handle_or_name + '"') - - browser.current_window = first_window - browser.get_current_window_handle = lambda: browser.current_window.handle - browser.get_title = lambda: browser.current_window.title - browser.get_current_url = lambda: browser.current_window.url - browser.get_window_handles = lambda: window_handles - browser.switch_to_window = switch_to_window - - return browser +from selenium.common.exceptions import NoSuchWindowException + +class WindowManagerTests(unittest.TestCase): + + def test_select_with_invalid_prefix(self): + manager = WindowManager() + browser = mock() + with self.assertRaises(ValueError) as context: + manager.select(browser, "something=test1") + self.assertEqual(context.exception.message, "Window locator with prefix 'something' is not supported") + + def test_select_with_null_browser(self): + manager = WindowManager() + with self.assertRaises(AssertionError): + manager.select(None, "name=test1") + + def test_select_by_title(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "title=Title 2") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_title_sloppy_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "title= tItLe 2 ") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_title_with_multiple_matches(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2a', 'title': "Title 2", 'url': 'http://localhost/page2a.html' }, + { 'name': 'win2b', 'title': "Title 2", 'url': 'http://localhost/page2b.html' }) + + manager.select(browser, "title=Title 2") + self.assertEqual(browser.current_window.name, 'win2a') + + def test_select_by_title_no_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + with self.assertRaises(ValueError) as context: + manager.select(browser, "title=Title -1") + self.assertEqual(context.exception.message, "Unable to locate window with title 'Title -1'") + + def test_select_by_name(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name=win2") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_name_sloppy_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name= win2 ") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_name_with_bad_case(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + with self.assertRaises(ValueError) as context: + manager.select(browser, "name=Win2") + self.assertEqual(context.exception.message, "Unable to locate window with name 'Win2'") + + def test_select_by_name_no_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + with self.assertRaises(ValueError) as context: + manager.select(browser, "name=win-1") + self.assertEqual(context.exception.message, "Unable to locate window with name 'win-1'") + + def test_select_by_url(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "url=http://localhost/page2.html") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_url_sloppy_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "url= http://LOCALHOST/page2.html ") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_url_with_multiple_matches(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2a', 'title': "Title 2a", 'url': 'http://localhost/page2.html' }, + { 'name': 'win2b', 'title': "Title 2b", 'url': 'http://localhost/page2.html' }) + + manager.select(browser, "url=http://localhost/page2.html") + self.assertEqual(browser.current_window.name, 'win2a') + + def test_select_by_url_no_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + with self.assertRaises(ValueError) as context: + manager.select(browser, "url=http://localhost/page-1.html") + self.assertEqual(context.exception.message, "Unable to locate window with URL 'http://localhost/page-1.html'") + + def test_select_with_null_locator(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name=win2") + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, None) + self.assertEqual(browser.current_window.name, 'win1') + + def test_select_with_null_string_locator(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name=win2") + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, "null") + self.assertEqual(browser.current_window.name, 'win1') + + def test_select_with_empty_locator(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name=win2") + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, "") + self.assertEqual(browser.current_window.name, 'win1') + + def test_select_by_default_with_name(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "win2") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_default_with_title(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "Title 2") + self.assertEqual(browser.current_window.name, 'win2') + + def test_select_by_default_no_match(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + with self.assertRaises(ValueError) as context: + manager.select(browser, "win-1") + self.assertEqual(context.exception.message, "Unable to locate window with name or title 'win-1'") + + def test_select_with_sloppy_prefix(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + manager.select(browser, "name=win2") + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, "nAmE=win2") + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, " name =win2") + self.assertEqual(browser.current_window.name, 'win2') + + def test_get_window_handles(self): + manager = WindowManager() + browser = self._make_mock_browser( + { 'name': 'win1', 'title': "Title 1", 'url': 'http://localhost/page1.html' }, + { 'name': 'win2', 'title': "Title 2", 'url': 'http://localhost/page2.html' }, + { 'name': 'win3', 'title': "Title 3", 'url': 'http://localhost/page3.html' }) + + window_handles = manager.get_window_handles(browser) + self.assertEqual(len(window_handles), 3) + manager.select(browser, window_handles[1]) + self.assertEqual(browser.current_window.name, 'win2') + manager.select(browser, window_handles[2]) + self.assertEqual(browser.current_window.name, 'win3') + manager.select(browser, window_handles[0]) + self.assertEqual(browser.current_window.name, 'win1') + + def _make_mock_browser(self, *window_specs): + browser = mock() + + windows = [] + window_handles = [] + first_window = None + for window_spec in window_specs: + window = mock() + window.handle = uuid.uuid4().hex + window.name = window_spec['name'] + window.title = window_spec['title'] + window.url = window_spec['url'] + + windows.append(window) + window_handles.append(window.handle) + + if first_window is None: + first_window = window + + def switch_to_window(handle_or_name): + if handle_or_name == '': + browser.current_window = first_window + return + for window in windows: + if window.handle == handle_or_name or window.name == handle_or_name: + browser.current_window = window + return + raise NoSuchWindowException(u'Unable to locate window "' + handle_or_name + '"') + + browser.current_window = first_window + browser.get_current_window_handle = lambda: browser.current_window.handle + browser.get_title = lambda: browser.current_window.title + browser.get_current_url = lambda: browser.current_window.url + browser.get_window_handles = lambda: window_handles + browser.switch_to_window = switch_to_window + + return browser diff --git a/test/unit/utils/test_browsercache.py b/test/unit/utils/test_browsercache.py index afa7de511..12ebc50f1 100644 --- a/test/unit/utils/test_browsercache.py +++ b/test/unit/utils/test_browsercache.py @@ -1,79 +1,79 @@ -import unittest +import unittest import os -from Selenium2Library.utils import BrowserCache -from mockito import * - -class BrowserCacheTests(unittest.TestCase): - - def test_no_current_message(self): - cache = BrowserCache() - with self.assertRaises(RuntimeError) as context: - cache.current.anyMember() - self.assertEqual(context.exception.message, "No current browser") - - def test_browsers_property(self): - cache = BrowserCache() - - browser1 = mock() - browser2 = mock() - browser3 = mock() - - cache.register(browser1) - cache.register(browser2) - cache.register(browser3) - - self.assertEqual(len(cache.browsers), 3) - self.assertEqual(cache.browsers[0], browser1) - self.assertEqual(cache.browsers[1], browser2) - self.assertEqual(cache.browsers[2], browser3) - - def test_get_open_browsers(self): - cache = BrowserCache() - - browser1 = mock() - browser2 = mock() - browser3 = mock() - - cache.register(browser1) - cache.register(browser2) - cache.register(browser3) - - browsers = cache.get_open_browsers() - self.assertEqual(len(browsers), 3) - self.assertEqual(browsers[0], browser1) - self.assertEqual(browsers[1], browser2) - self.assertEqual(browsers[2], browser3) - - cache.close() - browsers = cache.get_open_browsers() - self.assertEqual(len(browsers), 2) - self.assertEqual(browsers[0], browser1) - self.assertEqual(browsers[1], browser2) - - def test_close(self): - cache = BrowserCache() - browser = mock() - cache.register(browser) - - verify(browser, times=0).quit() # sanity check - cache.close() - verify(browser, times=1).quit() - - def test_close_only_called_once(self): - cache = BrowserCache() - - browser1 = mock() - browser2 = mock() - browser3 = mock() - - cache.register(browser1) - cache.register(browser2) - cache.register(browser3) - - cache.close() - verify(browser3, times=1).quit() - - cache.close_all() - verify(browser1, times=1).quit() - verify(browser2, times=1).quit() - verify(browser3, times=1).quit() +from Selenium2Library.utils import BrowserCache +from mockito import * + +class BrowserCacheTests(unittest.TestCase): + + def test_no_current_message(self): + cache = BrowserCache() + with self.assertRaises(RuntimeError) as context: + cache.current.anyMember() + self.assertEqual(context.exception.message, "No current browser") + + def test_browsers_property(self): + cache = BrowserCache() + + browser1 = mock() + browser2 = mock() + browser3 = mock() + + cache.register(browser1) + cache.register(browser2) + cache.register(browser3) + + self.assertEqual(len(cache.browsers), 3) + self.assertEqual(cache.browsers[0], browser1) + self.assertEqual(cache.browsers[1], browser2) + self.assertEqual(cache.browsers[2], browser3) + + def test_get_open_browsers(self): + cache = BrowserCache() + + browser1 = mock() + browser2 = mock() + browser3 = mock() + + cache.register(browser1) + cache.register(browser2) + cache.register(browser3) + + browsers = cache.get_open_browsers() + self.assertEqual(len(browsers), 3) + self.assertEqual(browsers[0], browser1) + self.assertEqual(browsers[1], browser2) + self.assertEqual(browsers[2], browser3) + + cache.close() + browsers = cache.get_open_browsers() + self.assertEqual(len(browsers), 2) + self.assertEqual(browsers[0], browser1) + self.assertEqual(browsers[1], browser2) + + def test_close(self): + cache = BrowserCache() + browser = mock() + cache.register(browser) + + verify(browser, times=0).quit() # sanity check + cache.close() + verify(browser, times=1).quit() + + def test_close_only_called_once(self): + cache = BrowserCache() + + browser1 = mock() + browser2 = mock() + browser3 = mock() + + cache.register(browser1) + cache.register(browser2) + cache.register(browser3) + + cache.close() + verify(browser3, times=1).quit() + + cache.close_all() + verify(browser1, times=1).quit() + verify(browser2, times=1).quit() + verify(browser3, times=1).quit() diff --git a/test/unit/utils/test_package.py b/test/unit/utils/test_package.py index 4a4caa673..f3c10e5aa 100644 --- a/test/unit/utils/test_package.py +++ b/test/unit/utils/test_package.py @@ -1,19 +1,19 @@ -import unittest -from Selenium2Library import utils - -class UtilsPackageTests(unittest.TestCase): - - def test_escape_xpath_value_with_apos(self): - self.assertEqual( - utils.escape_xpath_value("test '1'"), - "\"test '1'\"") - - def test_escape_xpath_value_with_quote(self): - self.assertEqual( - utils.escape_xpath_value("test \"1\""), - "'test \"1\"'") - - def test_escape_xpath_value_with_quote_and_apos(self): - self.assertEqual( - utils.escape_xpath_value("test \"1\" and '2'"), - "concat('test \"1\" and ', \"'\", '2', \"'\", '')") +import unittest +from Selenium2Library import utils + +class UtilsPackageTests(unittest.TestCase): + + def test_escape_xpath_value_with_apos(self): + self.assertEqual( + utils.escape_xpath_value("test '1'"), + "\"test '1'\"") + + def test_escape_xpath_value_with_quote(self): + self.assertEqual( + utils.escape_xpath_value("test \"1\""), + "'test \"1\"'") + + def test_escape_xpath_value_with_quote_and_apos(self): + self.assertEqual( + utils.escape_xpath_value("test \"1\" and '2'"), + "concat('test \"1\" and ', \"'\", '2', \"'\", '')") From d17118fedeca532be855828d248f536537c4c2f8 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Sat, 22 Oct 2011 01:40:48 -0700 Subject: [PATCH 004/105] Change .hgignore to .gitingore --- .hgignore => .gitignore | 1 - 1 file changed, 1 deletion(-) rename .hgignore => .gitignore (85%) diff --git a/.hgignore b/.gitignore similarity index 85% rename from .hgignore rename to .gitignore index f94adb660..6dcbf0d1e 100644 --- a/.hgignore +++ b/.gitignore @@ -1,4 +1,3 @@ -syntax:glob .project .pydevproject test/results From d140caa58afdb88572d125766c739c8e220fe337 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Sat, 22 Oct 2011 03:27:14 -0700 Subject: [PATCH 005/105] Update project URL --- src/Selenium2Library/metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Selenium2Library/metadata.py b/src/Selenium2Library/metadata.py index ebe391284..f4be30eda 100644 --- a/src/Selenium2Library/metadata.py +++ b/src/Selenium2Library/metadata.py @@ -16,7 +16,7 @@ AUTHOR = "Robot Framework Developers" AUTHOR_EMAIL = "robotframework@gmail.com" -PROJECT_URL = "http://www.google.com" +PROJECT_URL = "https://github.com/rtomac/robotframework-selenium2library" LICENSE = "Apache License 2.0" KEYWORDS = "robotframework testing testautomation selenium selenium2 webdriver web" From ef76f18610f2c2c36e6695921019e5136328f6ba Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Sat, 22 Oct 2011 03:42:27 -0700 Subject: [PATCH 006/105] Don't build readmes by default --- doc/INSTALL.html | 700 ++++++++++++++++++------------------ doc/README.html | 706 ++++++++++++++++++------------------ doc/Selenium2Library.html | 2 +- doc/generate.py | 28 -- doc/generate_readmes.py | 38 ++ doc/test-README.html | 736 +++++++++++++++++++------------------- 6 files changed, 1110 insertions(+), 1100 deletions(-) create mode 100644 doc/generate_readmes.py diff --git a/doc/INSTALL.html b/doc/INSTALL.html index b760d495d..ea084f249 100644 --- a/doc/INSTALL.html +++ b/doc/INSTALL.html @@ -1,350 +1,350 @@ - - - - - - -Selenium2Library Installation - - - -
-

Selenium2Library Installation

- -

The Selenium2Library distribution contains the Selenium2Library -keywords/code, as well as the Selenium 2 (WebDriver) code -that it depends on.

-
-

Preconditions

-

Selenium2Library itself supports all Python and Jython interpreters that are -supported by Robot Framework.

-
-
-

Installing from source

-

The source code can be got either as a source distribution or as a checkout -from our version control system. The installer requires Python version 2.4 or -newer. Selenium Library is installed from source by typing following command:

-
-python setup.py install
-
-

In most linux systems, you need to have root privileges for installation.

-

Uninstallation is achieved by deleting the installation directory and its -contents from the file system. The default installation directory is -[PythonLibraries]/site-packages/Selenium2Library.

-
-
-

Using Windows installer

-

Currently, Windows installer is the only available binary installer. It is -enough to double-click the installer and follow the instructions.

-

Selenium2Library can be uninstalled using the Programs and Features utility from -Control Panel (Add/Remove Programs on older versions of Windows).

-
-
- - + + + + + + +Selenium2Library Installation + + + +
+

Selenium2Library Installation

+ +

The Selenium2Library distribution contains the Selenium2Library +keywords/code, as well as the Selenium 2 (WebDriver) code +that it depends on.

+
+

Preconditions

+

Selenium2Library itself supports all Python and Jython interpreters that are +supported by Robot Framework.

+
+
+

Installing from source

+

The source code can be got either as a source distribution or as a checkout +from our version control system. The installer requires Python version 2.4 or +newer. Selenium Library is installed from source by typing following command:

+
+python setup.py install
+
+

In most linux systems, you need to have root privileges for installation.

+

Uninstallation is achieved by deleting the installation directory and its +contents from the file system. The default installation directory is +[PythonLibraries]/site-packages/Selenium2Library.

+
+
+

Using Windows installer

+

Currently, Windows installer is the only available binary installer. It is +enough to double-click the installer and follow the instructions.

+

Selenium2Library can be uninstalled using the Programs and Features utility from +Control Panel (Add/Remove Programs on older versions of Windows).

+
+
+ + diff --git a/doc/README.html b/doc/README.html index 1122d4bce..b33ab7ee6 100644 --- a/doc/README.html +++ b/doc/README.html @@ -1,353 +1,353 @@ - - - - - - -Selenium 2 (WebDriver) library for Robot Framework - - - -
-

Selenium 2 (WebDriver) library for Robot Framework

- -
-

Introduction

-

Selenium2Library is a web testing library for Robot Framework -that leverage the Selenium 2 (WebDriver) libraries from the -Selenium project.

-

It is modeled after (and forked from) the SeleniumLibrary library, -but re-implemented to use Selenium 2 and WebDriver technologies.

-
-
-

Usage

-

To write tests with Robot Framework and Selenium2Library, -Selenium2Library must be imported into your Robot test suite. -See Robot Framework User Guide for more information.

-
-
-

Installation

-

See INSTALL.txt for installation and uninstallation instructions.

-
-
-

Directory Layout

-
-
demo/
-
A simple demonstration, with an application running on localhost.
-
doc/
-
Keyword documentation.
-
src/
-
Python source code.
-
test/
-
Unit tests and acceptance tests for Selenium2Library source code.
-
-
-
- - + + + + + + +Selenium 2 (WebDriver) library for Robot Framework + + + +
+

Selenium 2 (WebDriver) library for Robot Framework

+ +
+

Introduction

+

Selenium2Library is a web testing library for Robot Framework +that leverage the Selenium 2 (WebDriver) libraries from the +Selenium project.

+

It is modeled after (and forked from) the SeleniumLibrary library, +but re-implemented to use Selenium 2 and WebDriver technologies.

+
+
+

Usage

+

To write tests with Robot Framework and Selenium2Library, +Selenium2Library must be imported into your Robot test suite. +See Robot Framework User Guide for more information.

+
+
+

Installation

+

See INSTALL.txt for installation and uninstallation instructions.

+
+
+

Directory Layout

+
+
demo/
+
A simple demonstration, with an application running on localhost.
+
doc/
+
Keyword documentation.
+
src/
+
Python source code.
+
test/
+
Unit tests and acceptance tests for Selenium2Library source code.
+
+
+
+ + diff --git a/doc/Selenium2Library.html b/doc/Selenium2Library.html index 8d65838c5..c11a4fbc1 100644 --- a/doc/Selenium2Library.html +++ b/doc/Selenium2Library.html @@ -1733,7 +1733,7 @@

Keywords

diff --git a/doc/generate.py b/doc/generate.py index 8d078048a..b4f209f26 100755 --- a/doc/generate.py +++ b/doc/generate.py @@ -9,41 +9,13 @@ SRC_DIR = os.path.join(ROOT_DIR, "src") LIB_DIR = os.path.join(SRC_DIR, "Selenium2Library") -README_FILES = [ - "README.txt", - "INSTALL.txt", - "test/README.txt" -] - def main(): - build_lib_docs() - build_readmes() - -def build_lib_docs(): outpath = os.path.join(THIS_DIR, 'Selenium2Library.html') lib = LibraryDoc(LIB_DIR) create_html_doc(lib, outpath) print lib.name, lib.version print outpath -def build_readmes(): - try: - import docutils - except: - print "Readme files will not be built into HTML, docutils not installed" - return - for readme_relative_path in README_FILES: - readme_abs_path = os.path.join(ROOT_DIR, readme_relative_path.replace('/', os.sep)) - readme_path_parts = os.path.split(readme_abs_path) - Builder().process_txt(readme_path_parts[0], readme_path_parts[1]) - readme_html_path = os.path.splitext(readme_abs_path)[0] + '.html' - target_html_name = os.path.splitext(readme_relative_path.replace('/', '-'))[0] + '.html' - target_html_path = os.path.join(THIS_DIR, target_html_name) - if os.path.exists(target_html_path): - os.remove(target_html_path) - os.rename(readme_html_path, target_html_path) - print " ::: Saved: %s" % target_html_name - if __name__ == '__main__': main() diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py new file mode 100644 index 000000000..e7970d6dd --- /dev/null +++ b/doc/generate_readmes.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +import os, shutil +from libdoc import LibraryDoc, create_html_doc +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") +LIB_DIR = os.path.join(SRC_DIR, "Selenium2Library") + +README_FILES = [ + "README.txt", + "INSTALL.txt", + "test/README.txt" +] + +def main(): + try: + import docutils + except: + print "Readme files will not be built into HTML, docutils not installed" + return + for readme_relative_path in README_FILES: + readme_abs_path = os.path.join(ROOT_DIR, readme_relative_path.replace('/', os.sep)) + readme_path_parts = os.path.split(readme_abs_path) + Builder().process_txt(readme_path_parts[0], readme_path_parts[1]) + readme_html_path = os.path.splitext(readme_abs_path)[0] + '.html' + target_html_name = os.path.splitext(readme_relative_path.replace('/', '-'))[0] + '.html' + target_html_path = os.path.join(THIS_DIR, target_html_name) + if os.path.exists(target_html_path): + os.remove(target_html_path) + os.rename(readme_html_path, target_html_path) + print " ::: Saved: %s" % target_html_name + + +if __name__ == '__main__': + main() diff --git a/doc/test-README.html b/doc/test-README.html index 3605f836f..293faeb3b 100644 --- a/doc/test-README.html +++ b/doc/test-README.html @@ -1,368 +1,368 @@ - - - - - - -Selenium2Library Tests - - - -
-

Selenium2Library Tests

- -
-

Introduction

-

This directory contains everything needed to run Selenium2Library -tests with Robot Framework. This includes:

-
    -
  • Unit tests under unit directory.
  • -
  • Acceptance tests written with Robot Framework under acceptance -directory
  • -
  • A very simple httpserver.py which is used to serve the html for tests in -resources/testserver
  • -
  • A collection of simple html files under 'resources/html' directory
  • -
  • Start-up scripts for executing the tests
  • -
-
-
-

Running Tests

-

There is a python script for running the tests. It can be -used as follows:

-
-python run_tests.py python|jython ff|ie|chrome [options]
-
-

The first argument to the script defines the interpreter to be used -to run Robot. The second argument defines the browser to be used, -using the same browser tokens that you would use in your Robot -tests.

-

Due to the structure of the tests, the directory containg the test -case files (acceptance) is always given to Robot as test data path. -To run only a subset of test cases, Robot command line arguments ---test, --suite, --include and --exclude may be used.

-

Examples:

-
-# Run all tests with Python and Firefox
-test/run_tests.py python ff
-# Run only test suite `javascript` with Jython and Internet Explorer
-test/run_tests.py jython ie -s javascript
-
-
-
-

Failing Tests

-

When the tests are executed, a number of test cases can be seen to -fail in the console output. This is because these test cases are -designed to test error messages of Selenium2Library. The script -'teststatuschecker.py' is used to check that these test cases failed -with expected error message. After that, report and log files are -generated and these files show the correct status of the test run.

-
-
- - + + + + + + +Selenium2Library Tests + + + +
+

Selenium2Library Tests

+ +
+

Introduction

+

This directory contains everything needed to run Selenium2Library +tests with Robot Framework. This includes:

+
    +
  • Unit tests under unit directory.
  • +
  • Acceptance tests written with Robot Framework under acceptance +directory
  • +
  • A very simple httpserver.py which is used to serve the html for tests in +resources/testserver
  • +
  • A collection of simple html files under 'resources/html' directory
  • +
  • Start-up scripts for executing the tests
  • +
+
+
+

Running Tests

+

There is a python script for running the tests. It can be +used as follows:

+
+python run_tests.py python|jython ff|ie|chrome [options]
+
+

The first argument to the script defines the interpreter to be used +to run Robot. The second argument defines the browser to be used, +using the same browser tokens that you would use in your Robot +tests.

+

Due to the structure of the tests, the directory containg the test +case files (acceptance) is always given to Robot as test data path. +To run only a subset of test cases, Robot command line arguments +--test, --suite, --include and --exclude may be used.

+

Examples:

+
+# Run all tests with Python and Firefox
+test/run_tests.py python ff
+# Run only test suite `javascript` with Jython and Internet Explorer
+test/run_tests.py jython ie -s javascript
+
+
+
+

Failing Tests

+

When the tests are executed, a number of test cases can be seen to +fail in the console output. This is because these test cases are +designed to test error messages of Selenium2Library. The script +'teststatuschecker.py' is used to check that these test cases failed +with expected error message. After that, report and log files are +generated and these files show the correct status of the test run.

+
+
+ + From a9ba0060588e01e3a3aa0cc1b6c0d19d6cb34c83 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:08:59 -0700 Subject: [PATCH 007/105] Remove readme HTML files from source control --- doc/INSTALL.html | 350 ---------------------------------------- doc/README.html | 353 ----------------------------------------- doc/test-README.html | 368 ------------------------------------------- 3 files changed, 1071 deletions(-) delete mode 100644 doc/INSTALL.html delete mode 100644 doc/README.html delete mode 100644 doc/test-README.html diff --git a/doc/INSTALL.html b/doc/INSTALL.html deleted file mode 100644 index ea084f249..000000000 --- a/doc/INSTALL.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - -Selenium2Library Installation - - - -
-

Selenium2Library Installation

- -

The Selenium2Library distribution contains the Selenium2Library -keywords/code, as well as the Selenium 2 (WebDriver) code -that it depends on.

-
-

Preconditions

-

Selenium2Library itself supports all Python and Jython interpreters that are -supported by Robot Framework.

-
-
-

Installing from source

-

The source code can be got either as a source distribution or as a checkout -from our version control system. The installer requires Python version 2.4 or -newer. Selenium Library is installed from source by typing following command:

-
-python setup.py install
-
-

In most linux systems, you need to have root privileges for installation.

-

Uninstallation is achieved by deleting the installation directory and its -contents from the file system. The default installation directory is -[PythonLibraries]/site-packages/Selenium2Library.

-
-
-

Using Windows installer

-

Currently, Windows installer is the only available binary installer. It is -enough to double-click the installer and follow the instructions.

-

Selenium2Library can be uninstalled using the Programs and Features utility from -Control Panel (Add/Remove Programs on older versions of Windows).

-
-
- - diff --git a/doc/README.html b/doc/README.html deleted file mode 100644 index b33ab7ee6..000000000 --- a/doc/README.html +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - -Selenium 2 (WebDriver) library for Robot Framework - - - -
-

Selenium 2 (WebDriver) library for Robot Framework

- -
-

Introduction

-

Selenium2Library is a web testing library for Robot Framework -that leverage the Selenium 2 (WebDriver) libraries from the -Selenium project.

-

It is modeled after (and forked from) the SeleniumLibrary library, -but re-implemented to use Selenium 2 and WebDriver technologies.

-
-
-

Usage

-

To write tests with Robot Framework and Selenium2Library, -Selenium2Library must be imported into your Robot test suite. -See Robot Framework User Guide for more information.

-
-
-

Installation

-

See INSTALL.txt for installation and uninstallation instructions.

-
-
-

Directory Layout

-
-
demo/
-
A simple demonstration, with an application running on localhost.
-
doc/
-
Keyword documentation.
-
src/
-
Python source code.
-
test/
-
Unit tests and acceptance tests for Selenium2Library source code.
-
-
-
- - diff --git a/doc/test-README.html b/doc/test-README.html deleted file mode 100644 index 293faeb3b..000000000 --- a/doc/test-README.html +++ /dev/null @@ -1,368 +0,0 @@ - - - - - - -Selenium2Library Tests - - - -
-

Selenium2Library Tests

- -
-

Introduction

-

This directory contains everything needed to run Selenium2Library -tests with Robot Framework. This includes:

-
    -
  • Unit tests under unit directory.
  • -
  • Acceptance tests written with Robot Framework under acceptance -directory
  • -
  • A very simple httpserver.py which is used to serve the html for tests in -resources/testserver
  • -
  • A collection of simple html files under 'resources/html' directory
  • -
  • Start-up scripts for executing the tests
  • -
-
-
-

Running Tests

-

There is a python script for running the tests. It can be -used as follows:

-
-python run_tests.py python|jython ff|ie|chrome [options]
-
-

The first argument to the script defines the interpreter to be used -to run Robot. The second argument defines the browser to be used, -using the same browser tokens that you would use in your Robot -tests.

-

Due to the structure of the tests, the directory containg the test -case files (acceptance) is always given to Robot as test data path. -To run only a subset of test cases, Robot command line arguments ---test, --suite, --include and --exclude may be used.

-

Examples:

-
-# Run all tests with Python and Firefox
-test/run_tests.py python ff
-# Run only test suite `javascript` with Jython and Internet Explorer
-test/run_tests.py jython ie -s javascript
-
-
-
-

Failing Tests

-

When the tests are executed, a number of test cases can be seen to -fail in the console output. This is because these test cases are -designed to test error messages of Selenium2Library. The script -'teststatuschecker.py' is used to check that these test cases failed -with expected error message. After that, report and log files are -generated and these files show the correct status of the test run.

-
-
- - From 13f3ceb44af93f55344dbd20816ed09171d7504a Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:17:48 -0700 Subject: [PATCH 008/105] Give readme files to .rest so GitHub will render --- INSTALL.txt => INSTALL.rest | 0 README.txt => README.rest | 0 test/{README.txt => README.rest} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename INSTALL.txt => INSTALL.rest (100%) rename README.txt => README.rest (100%) rename test/{README.txt => README.rest} (100%) diff --git a/INSTALL.txt b/INSTALL.rest similarity index 100% rename from INSTALL.txt rename to INSTALL.rest diff --git a/README.txt b/README.rest similarity index 100% rename from README.txt rename to README.rest diff --git a/test/README.txt b/test/README.rest similarity index 100% rename from test/README.txt rename to test/README.rest From cc455b54526278419577626d83823f090c79643d Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:39:36 -0700 Subject: [PATCH 009/105] Support building readme files with .rest extension --- .gitignore | 1 + README.rest | 2 +- doc/generate_readmes.py | 51 ++++++++++++++++++++++++++++++----------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 6dcbf0d1e..6b2bbb917 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ test/results *.pyc *.orig MANIFEST +doc/*.html dist build diff --git a/README.rest b/README.rest index 97e091e64..3d4caaf37 100644 --- a/README.rest +++ b/README.rest @@ -24,7 +24,7 @@ See `Robot Framework User Guide`_ for more information. Installation ------------ -See INSTALL.txt for installation and uninstallation instructions. +See INSTALL.rest for installation and uninstallation instructions. Directory Layout diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index e7970d6dd..6bafc9133 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -10,9 +10,9 @@ LIB_DIR = os.path.join(SRC_DIR, "Selenium2Library") README_FILES = [ - "README.txt", - "INSTALL.txt", - "test/README.txt" + "README.rest", + "INSTALL.rest", + "test/README.rest" ] def main(): @@ -22,16 +22,41 @@ def main(): print "Readme files will not be built into HTML, docutils not installed" return for readme_relative_path in README_FILES: - readme_abs_path = os.path.join(ROOT_DIR, readme_relative_path.replace('/', os.sep)) - readme_path_parts = os.path.split(readme_abs_path) - Builder().process_txt(readme_path_parts[0], readme_path_parts[1]) - readme_html_path = os.path.splitext(readme_abs_path)[0] + '.html' - target_html_name = os.path.splitext(readme_relative_path.replace('/', '-'))[0] + '.html' - target_html_path = os.path.join(THIS_DIR, target_html_name) - if os.path.exists(target_html_path): - os.remove(target_html_path) - os.rename(readme_html_path, target_html_path) - print " ::: Saved: %s" % target_html_name + (readme_dir, readme_name) = _parse_readme_path(readme_relative_path) + readme_txt_name = _make_txt_file(readme_dir, readme_name) + Builder().process_txt(readme_dir, readme_txt_name) + _cleanup_txt_file(readme_dir, readme_txt_name) + + readme_html_name = os.path.splitext(readme_name)[0] + '.html' + readme_html_path = os.path.join(readme_dir, readme_html_name) + target_readme_html_name = os.path.splitext(readme_relative_path.replace('/', '-'))[0] + '.html' + target_readme_html_path = os.path.join(THIS_DIR, target_readme_html_name) + + if os.path.exists(target_readme_html_path): + os.remove(target_readme_html_path) + os.rename(readme_html_path, target_readme_html_path) + + print " ::: Saved: %s" % 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)) + readme_path_parts = os.path.split(readme_abs_path) + readme_dir = readme_path_parts[0] + readme_name = readme_path_parts[1] + return (readme_dir, readme_name) + +def _make_txt_file(readme_dir, readme_name): + readme_txt_name = os.path.splitext(readme_name)[0] + '.txt' + _cleanup_txt_file(readme_dir, readme_txt_name) + shutil.copyfile( + os.path.join(readme_dir, readme_name), + os.path.join(readme_dir, readme_txt_name)) + return readme_txt_name + +def _cleanup_txt_file(readme_dir, readme_txt_name): + readme_txt_abs_path = os.path.join(readme_dir, readme_txt_name) + if os.path.exists(readme_txt_abs_path): + os.remove(readme_txt_abs_path) if __name__ == '__main__': From cfb6ed0a8cb191dfbbd30526cab1cebdeee10f97 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:41:05 -0700 Subject: [PATCH 010/105] Include .rest files in build package --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index df81f0a90..a4929ddc2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,8 @@ include MANIFEST.in include *.txt +include *.rest exclude */*.txt # limit previous command to include *.txt files in root folder +exclude */*.rest # limit previous command to include *.rest files in root folder include selenium.bmp recursive-include demo *.txt *.py *.sh *.bat *.html *.css *.js From b3c52ce3c8e7a126f63d93b25140c3cae8c597d6 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:48:05 -0700 Subject: [PATCH 011/105] Rename demo/README.txt to demo/README.rest --- demo/{README.txt => README.rest} | 0 demo/package.py | 2 +- doc/generate_readmes.py | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) rename demo/{README.txt => README.rest} (100%) diff --git a/demo/README.txt b/demo/README.rest similarity index 100% rename from demo/README.txt rename to demo/README.rest diff --git a/demo/package.py b/demo/package.py index 5b09ab8b2..a9826f441 100755 --- a/demo/package.py +++ b/demo/package.py @@ -10,7 +10,7 @@ import metadata FILES = { - '': ['rundemo.py', 'README.txt'], + '': ['rundemo.py', 'README.rest'], 'login_tests': ['valid_login.txt', 'invalid_login.txt', 'resource.txt'], 'demoapp': ['server.py'], 'demoapp/html': ['index.html', 'welcome.html', 'error.html', 'demo.css'] diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index 6bafc9133..e5ea87189 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -12,6 +12,7 @@ README_FILES = [ "README.rest", "INSTALL.rest", + "demo/README.rest", "test/README.rest" ] From 152b0f7e5f410de51e24d981c2b12f94045f3aaf Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 16:48:25 -0700 Subject: [PATCH 012/105] Make sure .rest files get included in build package --- MANIFEST.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index a4929ddc2..6d95aadf3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,12 +5,12 @@ exclude */*.txt # limit previous command to include *.txt files in root folder exclude */*.rest # limit previous command to include *.rest files in root folder include selenium.bmp -recursive-include demo *.txt *.py *.sh *.bat *.html *.css *.js +recursive-include demo *.txt *.rest *.py *.sh *.bat *.html *.css *.js prune demo/reports prune demo/selenium_log.txt prune demo/output.xml -recursive-include doc *.txt *.html +recursive-include doc Selenium2Library.html recursive-include src/Selenium2Library *.py graft src/Selenium2Library/lib From a417245c84923ebb951a2b59a146208f3bbce27d Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 17:36:46 -0700 Subject: [PATCH 013/105] Clean up readme documentation, including new BUILD.rest file --- BUILD.rest | 137 ++++++++++++++++++++++++++++++++++++++++ README.rest | 46 ++++++++------ demo/README.rest | 6 -- doc/generate_readmes.py | 3 +- test/README.rest | 54 ---------------- 5 files changed, 165 insertions(+), 81 deletions(-) create mode 100644 BUILD.rest delete mode 100644 demo/README.rest delete mode 100644 test/README.rest diff --git a/BUILD.rest b/BUILD.rest new file mode 100644 index 000000000..18467eca5 --- /dev/null +++ b/BUILD.rest @@ -0,0 +1,137 @@ +Selenium2Library Developer Information +====================================== + + +Directory Layout +---------------- + +MANIFEST.in + File that controls what gets included in a distribution + +setup.py + distutils setup script + +demo/ + Demo web app, acceptance tests, and scripts + +doc/ + Scripts to build keyword and readme documentation + +src/ + Library source code + +src/Selenium2Library/metadata.py + All metadata about the library (e.g. version), used by setup + script and library code + +test/ + Unit and acceptance tests for Selenium2Library + + +Unit and Acceptance Tests +------------------------- + +The test directory contains everything needed to run Selenium2Library +tests with Robot Framework. This includes: + +- Unit tests under `unit` directory. +- Acceptance tests written with Robot Framework under `acceptance` + directory +- A very simple httpserver.py which is used to serve the html for tests in + `resources/testserver` +- A collection of simple html files under 'resources/html' directory +- Start-up scripts for executing the tests + +To run unit and acceptance tests, run:: + + python test/run_tests.py python|jython ff|ie|chrome [options] + +The first argument to the script defines the interpreter to be used +to run Robot. The second argument defines the browser to be used, +using the same browser tokens that you would use in your Robot +tests. + +Due to the structure of the tests, the directory containg the test +case files (`acceptance`) is always given to Robot as test data path. +To run only a subset of test cases, Robot command line arguments +--test, --suite, --include and --exclude may be used. + +Examples:: + + # Run all tests with Python and Firefox + test/run_tests.py python ff + # Run only test suite `javascript` with Jython and Internet Explorer + test/run_tests.py jython ie -s javascript + +To run just the unit tests, run:: + + python test/run_unit_tests.py + + +Building a Distribution +----------------------- + +To build a distribution, run:: + + python build_dist.py + +This script will: + +- Generate source distribution packages in .tar.gz and .zip formats +- Generate build distribution packages for Windows x86 and x64 +- Generate a demo distribution package in .zip format. +- Re-generate keyword documentation in doc folder + + +Building Keyword Documentation +------------------------------ + +The keyword documentation will get built automatically by build_dist.py, +but if you need to generate it apart from a distribution build, run:: + + python doc/generate.py + + +Building Readme Files +--------------------- + +The readme files get distributed in reStructuredText format (.rest), +so there isn't any reason to build them except to verify how they +are parsed by the reStructuredText parser. To build them, run:: + + python doc/generate_readmes.py + + +Pushing Code to GitHub +---------------------- + +Assuming the remote has been setup and named `origin` (it is +setup and named `origin` automatically if you cloned the existing +GitHub repo), run:: + + git push origin master + + +Pushing Keyword Documentation +----------------------------- + +The keyword documentation is hosted using GitHub Pages. There is a branch +in the repo called `gh-pages` that contains nothing but the keyword documentation. + +First, switch to the `gh-pages` branch:: + + git checkout gh-pages + +Next, pull the keyword documentation you generated in the master branch and commit it:: + + git checkout doc/Selenium2Library.html + git add . + git commit + +Then, push it to the remote: + + git push origin gh-pages + +Last, you probably want to switch back to the master branch:: + + git checkout master diff --git a/README.rest b/README.rest index 3d4caaf37..86f061613 100644 --- a/README.rest +++ b/README.rest @@ -12,6 +12,23 @@ Selenium_ project. It is modeled after (and forked from) the SeleniumLibrary_ library, but re-implemented to use Selenium 2 and WebDriver technologies. +- More information about this library can be found on the Wiki_ and in the `Keyword Documentation`_. +- Installation information is found in the `INSTALL` file. +- Developer information is found in `BUILD`_ file. + + +Directory Layout +---------------- + +demo/ + A simple demonstration, with an application running on localhost + +doc/ + Keyword documentation + +src/ + Python source code + Usage ----- @@ -21,29 +38,20 @@ Selenium2Library must be imported into your Robot test suite. See `Robot Framework User Guide`_ for more information. -Installation ------------- - -See INSTALL.rest for installation and uninstallation instructions. +Running the Demo +---------------- +The demo directory contains an easily executable demo for Robot Framework +using Selenium2Library. The tests can be executed by running:: -Directory Layout ------------------ - -demo/ - A simple demonstration, with an application running on localhost. - -doc/ - Keyword documentation. - -src/ - Python source code. + python demo/rundemo.py -test/ - Unit tests and acceptance tests for Selenium2Library source code. - .. _Selenium: http://selenium.openqa.org .. _Selenium 2 (WebDriver): http://seleniumhq.org/docs/03_webdriver.html .. _SeleniumLibrary: http://code.google.com/p/robotframework-seleniumlibrary/ -.. _Robot Framework User Guide: http://code.google.com/p/robotframework/wiki/UserGuide \ No newline at end of file +.. _Wiki: https://github.com/rtomac/robotframework-selenium2library/wiki +.. _Keyword Documentation: http://rtomac.github.com/robotframework-selenium2library/doc/Selenium2Library.html +.. _INSTALL: https://github.com/rtomac/robotframework-selenium2library/blob/master/INSTALL.rest +.. _BUILD: https://github.com/rtomac/robotframework-selenium2library/blob/master/BUILD.rest +.. _Robot Framework User Guide: http://code.google.com/p/robotframework/wiki/UserGuide diff --git a/demo/README.rest b/demo/README.rest deleted file mode 100644 index ede49f03c..000000000 --- a/demo/README.rest +++ /dev/null @@ -1,6 +0,0 @@ -Robot Framework Selenium2Library Demo -===================================== - -This directory contains an easily executable demo for Robot Framework -using Selenium2Library. The tests can be executed using the `rundemo.py` -script. diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index e5ea87189..d1e168597 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -12,8 +12,7 @@ README_FILES = [ "README.rest", "INSTALL.rest", - "demo/README.rest", - "test/README.rest" + "BUILD.rest" ] def main(): diff --git a/test/README.rest b/test/README.rest deleted file mode 100644 index 8b1b938a5..000000000 --- a/test/README.rest +++ /dev/null @@ -1,54 +0,0 @@ -Selenium2Library Tests -====================== - - -Introduction ------------- - -This directory contains everything needed to run Selenium2Library -tests with Robot Framework. This includes: - -- Unit tests under `unit` directory. -- Acceptance tests written with Robot Framework under `acceptance` - directory -- A very simple httpserver.py which is used to serve the html for tests in - `resources/testserver` -- A collection of simple html files under 'resources/html' directory -- Start-up scripts for executing the tests - - -Running Tests -------------- - -There is a python script for running the tests. It can be -used as follows:: - - python run_tests.py python|jython ff|ie|chrome [options] - -The first argument to the script defines the interpreter to be used -to run Robot. The second argument defines the browser to be used, -using the same browser tokens that you would use in your Robot -tests. - -Due to the structure of the tests, the directory containg the test -case files (`acceptance`) is always given to Robot as test data path. -To run only a subset of test cases, Robot command line arguments ---test, --suite, --include and --exclude may be used. - -Examples:: - - # Run all tests with Python and Firefox - test/run_tests.py python ff - # Run only test suite `javascript` with Jython and Internet Explorer - test/run_tests.py jython ie -s javascript - - -Failing Tests -------------- - -When the tests are executed, a number of test cases can be seen to -fail in the console output. This is because these test cases are -designed to test error messages of Selenium2Library. The script -'teststatuschecker.py' is used to check that these test cases failed -with expected error message. After that, report and log files are -generated and these files show the correct status of the test run. From 1c795f554fd9ce8148f093ea25e3a7fad803f67f Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 17:39:07 -0700 Subject: [PATCH 014/105] Minor documentation cleanups --- BUILD.rest | 2 +- README.rest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.rest b/BUILD.rest index 18467eca5..3101d3b23 100644 --- a/BUILD.rest +++ b/BUILD.rest @@ -128,7 +128,7 @@ Next, pull the keyword documentation you generated in the master branch and comm git add . git commit -Then, push it to the remote: +Then, push it to the remote:: git push origin gh-pages diff --git a/README.rest b/README.rest index 86f061613..321bb80eb 100644 --- a/README.rest +++ b/README.rest @@ -13,7 +13,7 @@ It is modeled after (and forked from) the SeleniumLibrary_ library, but re-implemented to use Selenium 2 and WebDriver technologies. - More information about this library can be found on the Wiki_ and in the `Keyword Documentation`_. -- Installation information is found in the `INSTALL` file. +- Installation information is found in the `INSTALL`_ file. - Developer information is found in `BUILD`_ file. From e60ba8efd1fdf897154cd0c14bfc31593e464743 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 23:07:23 -0700 Subject: [PATCH 015/105] Minor update to readme --- README.rest | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.rest b/README.rest index 321bb80eb..193d7a061 100644 --- a/README.rest +++ b/README.rest @@ -13,8 +13,8 @@ It is modeled after (and forked from) the SeleniumLibrary_ library, but re-implemented to use Selenium 2 and WebDriver technologies. - More information about this library can be found on the Wiki_ and in the `Keyword Documentation`_. -- Installation information is found in the `INSTALL`_ file. -- Developer information is found in `BUILD`_ file. +- Installation information is found in the `INSTALL.rest` file. +- Developer information is found in `BUILD.rest` file. Directory Layout @@ -52,6 +52,4 @@ using Selenium2Library. The tests can be executed by running:: .. _SeleniumLibrary: http://code.google.com/p/robotframework-seleniumlibrary/ .. _Wiki: https://github.com/rtomac/robotframework-selenium2library/wiki .. _Keyword Documentation: http://rtomac.github.com/robotframework-selenium2library/doc/Selenium2Library.html -.. _INSTALL: https://github.com/rtomac/robotframework-selenium2library/blob/master/INSTALL.rest -.. _BUILD: https://github.com/rtomac/robotframework-selenium2library/blob/master/BUILD.rest .. _Robot Framework User Guide: http://code.google.com/p/robotframework/wiki/UserGuide From 2eec8bdea887c0abd3958cdfeeec079faa497dbc Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 23:24:45 -0700 Subject: [PATCH 016/105] Fix issues with dist build, increment version to 0.5.1 --- MANIFEST.in | 2 +- demo/package.py | 2 +- doc/Selenium2Library.html | 4 ++-- src/Selenium2Library/metadata.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 6d95aadf3..4be939bd4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -10,7 +10,7 @@ prune demo/reports prune demo/selenium_log.txt prune demo/output.xml -recursive-include doc Selenium2Library.html +include doc/Selenium2Library.html recursive-include src/Selenium2Library *.py graft src/Selenium2Library/lib diff --git a/demo/package.py b/demo/package.py index a9826f441..724923dbd 100755 --- a/demo/package.py +++ b/demo/package.py @@ -10,7 +10,7 @@ import metadata FILES = { - '': ['rundemo.py', 'README.rest'], + '': ['rundemo.py'], 'login_tests': ['valid_login.txt', 'invalid_login.txt', 'resource.txt'], 'demoapp': ['server.py'], 'demoapp/html': ['index.html', 'welcome.html', 'error.html', 'demo.css'] diff --git a/doc/Selenium2Library.html b/doc/Selenium2Library.html index c11a4fbc1..ae061d930 100644 --- a/doc/Selenium2Library.html +++ b/doc/Selenium2Library.html @@ -89,7 +89,7 @@

Selenium2Library

-Version: 0.5
+Version: 0.5.1
Scope: global
Named arguments: supported @@ -1733,7 +1733,7 @@

Keywords

diff --git a/src/Selenium2Library/metadata.py b/src/Selenium2Library/metadata.py index f4be30eda..d88f82a50 100644 --- a/src/Selenium2Library/metadata.py +++ b/src/Selenium2Library/metadata.py @@ -4,7 +4,7 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_DIRS = [ 'lib', 'resources' ] -VERSION = '0.5' +VERSION = '0.5.1' NAME = "robotframework-selenium2library" PACKAGE_NAME = "Selenium2Library" From 7d444a5c21e9974caa3d934fc773504901cfe290 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Mon, 24 Oct 2011 23:34:25 -0700 Subject: [PATCH 017/105] Update BUILD readme --- BUILD.rest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.rest b/BUILD.rest index 3101d3b23..22660d04f 100644 --- a/BUILD.rest +++ b/BUILD.rest @@ -124,7 +124,7 @@ First, switch to the `gh-pages` branch:: Next, pull the keyword documentation you generated in the master branch and commit it:: - git checkout doc/Selenium2Library.html + git checkout master doc/Selenium2Library.html git add . git commit From c1cd0c0a2e5e25e3bfafd70489b7e3f8581a77cd Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Tue, 25 Oct 2011 16:10:28 -0700 Subject: [PATCH 018/105] Increment maintenance version --- src/Selenium2Library/metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Selenium2Library/metadata.py b/src/Selenium2Library/metadata.py index d88f82a50..a5be509dc 100644 --- a/src/Selenium2Library/metadata.py +++ b/src/Selenium2Library/metadata.py @@ -4,7 +4,7 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) DATA_DIRS = [ 'lib', 'resources' ] -VERSION = '0.5.1' +VERSION = '0.5.2' NAME = "robotframework-selenium2library" PACKAGE_NAME = "Selenium2Library" From 56e8b35bd2b11f42baf0e673e2745fee47a49e9e Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Tue, 25 Oct 2011 16:17:54 -0700 Subject: [PATCH 019/105] Change keywords Get Url => Get Location and Log Url => Log Location --- .../keywords/_browsermanagement.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 7b2ffbc18..a45b28ea2 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -176,6 +176,10 @@ def unselect_frame(self): # Public, browser/current page properties + def get_location(self): + """Returns the current location.""" + return self._current_browser().get_current_url() + def get_source(self): """Returns the entire html source of the current page or frame.""" return self._current_browser().get_page_source() @@ -184,13 +188,9 @@ def get_title(self): """Returns title of current page.""" return self._current_browser().get_title() - def get_url(self): - """Returns URL of current page.""" - return self._current_browser().get_current_url() - def location_should_be(self, url): """Verifies that current URL is exactly `url`.""" - actual = self.get_url() + actual = self.get_location() if actual != url: raise AssertionError("Location should have been '%s' but was '%s'" % (url, actual)) @@ -198,12 +198,18 @@ def location_should_be(self, url): def location_should_contain(self, expected): """Verifies that current URL contains `expected`.""" - actual = self.get_url() + actual = self.get_location() if not expected in actual: raise AssertionError("Location should have contained '%s' " "but it was '%s'." % (expected, actual)) self._info("Current location contains '%s'." % expected) + def log_location(self): + """Logs and returns the current location.""" + url = self.get_location() + self._info(url) + return url + def log_source(self, loglevel='INFO'): """Logs and returns the entire html source of the current page or frame. @@ -220,12 +226,6 @@ def log_title(self): self._info(title) return title - def log_url(self): - """Logs and returns the URL of current page.""" - url = self.get_url() - self._info(url) - return url - def title_should_be(self, title): """Verifies that current page title equals `title`.""" actual = self.get_title() From 1b35ec7548a457349e4bf0a08f2e10fc37b02633 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Tue, 25 Oct 2011 16:45:30 -0700 Subject: [PATCH 020/105] Add Focus keyword --- src/Selenium2Library/keywords/_element.py | 5 +++++ test/acceptance/keywords/mouse.txt | 23 +++++++++++------------ test/resources/html/mouse/index.html | 12 +++++------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/Selenium2Library/keywords/_element.py b/src/Selenium2Library/keywords/_element.py index 5ec38e968..a5d307fb9 100644 --- a/src/Selenium2Library/keywords/_element.py +++ b/src/Selenium2Library/keywords/_element.py @@ -263,6 +263,11 @@ def double_click_element(self, locator): element = self._element_find(locator, True, True) ActionChains(self._current_browser()).double_click(element).perform() + def focus(self, locator): + """Sets focus to element identified by `locator`.""" + element = self._element_find(locator, True, True) + self._current_browser().execute_script("arguments[0].focus();", element) + def mouse_down(self, locator): """Simulates pressing the left mouse button on the element specified by `locator`. diff --git a/test/acceptance/keywords/mouse.txt b/test/acceptance/keywords/mouse.txt index 53ebbcc04..94ce6ec22 100644 --- a/test/acceptance/keywords/mouse.txt +++ b/test/acceptance/keywords/mouse.txt @@ -4,26 +4,25 @@ Resource ../resource.txt *** Test Cases *** Mouse Over - Mouse Over test_element - Textfield Value Should Be test_element mouseover test_element - Textfield Value Should Be secondary_element ${EMPTY} + Mouse Over el_for_mouseover + Textfield Value Should Be el_for_mouseover mouseover el_for_mouseover Run Keyword And Expect Error ERROR: Element not_there not found. Mouse Over not_there Mouse Out - Mouse Out test_element - Textfield Value Should Be test_element mouseout test_element - Textfield Value Should Be secondary_element ${EMPTY} + Mouse Out el_for_mouseout + Textfield Value Should Be el_for_mouseout mouseout el_for_mouseout Run Keyword And Expect Error ERROR: Element not_there not found. Mouse Out not_there Mouse Down - Mouse Down test_element - Textfield Value Should Be test_element mousedown test_element - Textfield Value Should Be secondary_element ${EMPTY} + Mouse Down el_for_mousedown + Textfield Value Should Be el_for_mousedown mousedown el_for_mousedown Run Keyword And Expect Error ERROR: Element not_there not found. Mouse Down not_there Mouse Up - Mouse Up test_element - Textfield Value Should Be test_element mouseup test_element - Textfield Value Should Be secondary_element ${EMPTY} + Mouse Up el_for_mouseup + Textfield Value Should Be el_for_mouseup mouseup el_for_mouseup Run Keyword And Expect Error ERROR: Element not_there not found. Mouse Up not_there +Focus + Focus el_for_focus + Textfield Value Should Be el_for_focus focus el_for_focus diff --git a/test/resources/html/mouse/index.html b/test/resources/html/mouse/index.html index 529ccb830..949fcc588 100644 --- a/test/resources/html/mouse/index.html +++ b/test/resources/html/mouse/index.html @@ -3,13 +3,11 @@ Mouse Keyword Testbed -
- +
+
+
+
+
+ + + -

Selenium2Library

-Version: 1.0.0
-Scope: global
-Named arguments: -supported - -

Introduction

-
Selenium2Library is a web testing library for Robot Framework. - -It 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. - -Selenium2Library runs tests in a real browser instance. It should work in most modern browsers and can be used with both Python and Jython interpreters. - -Before running tests - -Prior to running test cases using Selenium2Library, Selenium2Library must be imported into your Robot test suite (see importing section), and the Open Browser keyword must be used to open a browser to the desired location. - -Locating elements - -All keywords in Selenium2Library that need to find an element on the page take an argument, locator. By default, when a locator value is provided, it is matched against the key attributes of the particular element type. For example, id and name are key attributes to all elements, and locating elements is easy using just the id as a locator. For example:: - -Click Element my_element - -It is also possible to specify the approach Selenium2Library should take to find an element by specifying a lookup strategy with a locator prefix. Supported strategies are: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StrategyExampleDescription
identifierClick Element | identifier=my_elementMatches by @id or @name attribute
idClick Element | id=my_elementMatches by @id attribute
nameClick Element | name=my_elementMatches by @name attribute
xpathClick Element | xpath=//div[@id='my_element']Matches with arbitrary XPath expression
domClick Element | dom=document.images[56]Matches with arbitrary DOM express
linkClick Element | link=My LinkMatches anchor elements by their link text
cssClick Element | css=div.my_classMatches by CSS selector
tagClick Element | tag=divMatches by HTML tag name
-Table related keywords, such as Table Should Contain, work differently. By default, when a table locator value is provided, it will search for a table with the specified id attribute. For example: - -Table Should Contain my_table text - -More complex table lookup strategies are also supported: - - - - - - - - - - - - - - - - - -
StrategyExampleDescription
cssTable Should Contain | css=table.my_class | textMatches by @id or @name attribute
xpathTable Should Contain | xpath=//table/[@name="my_table"] | textMatches by @id or @name attribute
-Timeouts - -There are several Wait ... keywords that take timeout as an argument. All of these timeout arguments are optional. The timeout used by all of them can be set globally using the Set Selenium Timeout keyword. - -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.
- -

Importing

- - - - - - - - - -
ArgumentsDocumentation
timeout=5.0, implicit_wait=0.0, run_on_failure=Capture Page ScreenshotSelenium2Library can be imported with optional arguments. - -timeout is the default timeout used to wait for all waiting actions. It can be later set with Set Selenium Timeout. - -'implicit_wait' is the implicit timeout that Selenium waits when looking for elements. It can be later set with 'Set Selenium Implicit Wait'. -run_on_failure specifies the name of a keyword (from any available libraries) to execute when a Selenium2Library keyword fails. By default Capture Page Screenshot will be used to take a screenshot of the current page. Using the value "Nothing" will disable this feature altogether. See Register Keyword To Run On Failure keyword for more information about this functionality. - -Examples: - - - - - - - - - - - - - -
Library | Selenium2Library | 15# Sets default timeout to 15 seconds
Library | Selenium2Library | 5 | Log Source# Sets default timeout to 5 seconds and runs Log Source on failure
Library | Selenium2Library | timeout=10 | run_on_failure=Nothing# Sets default timeout to 10 seconds and does nothing on failure
- -

Shortcuts

-
-Alert Should Be Present - ·  -Assign Id To Element - ·  -Capture Page Screenshot - ·  -Checkbox Should Be Selected - ·  -Checkbox Should Not Be Selected - ·  -Choose Cancel On Next Confirmation - ·  -Choose File - ·  -Choose Ok On Next Confirmation - ·  -Click Button - ·  -Click Element - ·  -Click Image - ·  -Click Link - ·  -Close All Browsers - ·  -Close Browser - ·  -Close Window - ·  -Confirm Action - ·  -Current Frame Contains - ·  -Delete All Cookies - ·  -Delete Cookie - ·  -Double Click Element - ·  -Element Should Be Disabled - ·  -Element Should Be Enabled - ·  -Element Should Be Visible - ·  -Element Should Contain - ·  -Element Should Not Be Visible - ·  -Element Text Should Be - ·  -Execute Async Javascript - ·  -Execute Javascript - ·  -Focus - ·  -Frame Should Contain - ·  -Get Alert Message - ·  -Get All Links - ·  -Get Cookie Value - ·  -Get Cookies - ·  -Get Element Attribute - ·  -Get Horizontal Position - ·  -Get List Items - ·  -Get Location - ·  -Get Matching Xpath Count - ·  -Get Selected List Label - ·  -Get Selected List Labels - ·  -Get Selected List Value - ·  -Get Selected List Values - ·  -Get Selenium Implicit Wait - ·  -Get Selenium Speed - ·  -Get Selenium Timeout - ·  -Get Source - ·  -Get Table Cell - ·  -Get Title - ·  -Get Value - ·  -Get Vertical Position - ·  -Get Window Identifiers - ·  -Get Window Names - ·  -Get Window Titles - ·  -Go Back - ·  -Go To - ·  -Input Password - ·  -Input Text - ·  -List Selection Should Be - ·  -List Should Have No Selections - ·  -Location Should Be - ·  -Location Should Contain - ·  -Log Location - ·  -Log Source - ·  -Log Title - ·  -Maximize Browser Window - ·  -Mouse Down - ·  -Mouse Down On Image - ·  -Mouse Down On Link - ·  -Mouse Out - ·  -Mouse Over - ·  -Mouse Up - ·  -Open Browser - ·  -Open Context Menu - ·  -Page Should Contain - ·  -Page Should Contain Button - ·  -Page Should Contain Checkbox - ·  -Page Should Contain Element - ·  -Page Should Contain Image - ·  -Page Should Contain Link - ·  -Page Should Contain List - ·  -Page Should Contain Radio Button - ·  -Page Should Contain Textfield - ·  -Page Should Not Contain - ·  -Page Should Not Contain Button - ·  -Page Should Not Contain Checkbox - ·  -Page Should Not Contain Element - ·  -Page Should Not Contain Image - ·  -Page Should Not Contain Link - ·  -Page Should Not Contain List - ·  -Page Should Not Contain Radio Button - ·  -Page Should Not Contain Textfield - ·  -Press Key - ·  -Radio Button Should Be Set To - ·  -Radio Button Should Not Be Selected - ·  -Register Keyword To Run On Failure - ·  -Reload Page - ·  -Select All From List - ·  -Select Checkbox - ·  -Select Frame - ·  -Select From List - ·  -Select Radio Button - ·  -Select Window - ·  -Set Browser Implicit Wait - ·  -Set Selenium Implicit Wait - ·  -Set Selenium Speed - ·  -Set Selenium Timeout - ·  -Simulate - ·  -Submit Form - ·  -Switch Browser - ·  -Table Cell Should Contain - ·  -Table Column Should Contain - ·  -Table Footer Should Contain - ·  -Table Header Should Contain - ·  -Table Row Should Contain - ·  -Table Should Contain - ·  -Textfield Should Contain - ·  -Textfield Value Should Be - ·  -Title Should Be - ·  -Unselect Checkbox - ·  -Unselect Frame - ·  -Unselect From List - ·  -Wait For Condition - ·  -Wait Until Page Contains - ·  -Wait Until Page Contains Element - ·  -Xpath Should Match X Times +
+

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.
  • +
-

Keywords

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeywordArgumentsDocumentation
Alert Should Be Presenttext=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.
Assign Id To Elementlocator, idAssigns a temporary identifier to element specified by locator. - -This is mainly useful if the locator is complicated/slow XPath expression. Identifier expires when the page is reloaded. - -Example: - - - - - - - - - - - -
Assign ID to Elementxpath=//div[@id="first_div"]my id
Page Should Contain Elementmy id
Capture Page Screenshotfilename=NoneTakes a screenshot of the current page and embeds it into the log. - -filename argument specifies the name of the file to write the screenshot into. If no filename is given, the screenshot is saved into file selenium-screenshot-<counter>.png under the directory where the Robot Framework log file is written into. The filename is also considered relative to the same directory, if it is not given in absolute format. - -css can be used to modify how the screenshot is taken. By default the bakground color is changed to avoid possible problems with background leaking when the page layout is somehow broken.
Checkbox Should Be SelectedlocatorVerifies checkbox identified by locator is selected/checked. - -Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Checkbox Should Not Be SelectedlocatorVerifies checkbox identified by locator is not selected/checked. - -Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Choose Cancel On Next ConfirmationCancel will be selected the next time Confirm Action is used.
Choose Filelocator, file_pathInputs the file_path into file input field found by identifier. - -This keyword is most often used to input files into upload forms. The file specified with file_path must be available on the same host where the Selenium Server is running. - -Example: - - - - - - -
Choose Filemy_upload_field/home/user/files/trades.csv
Choose Ok On Next ConfirmationUndo 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.
Click ButtonlocatorClicks a button identified by locator. - -Key attributes for buttons are id, name and value. See introduction for details about locating elements.
Click ElementlocatorClick element identified by locator. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Click ImagelocatorClicks an image found by locator. - -Key attributes for images are id, src and alt. See introduction for details about locating elements.
Click LinklocatorClicks a link identified by locator. - -Key attributes for links are id, name, href and link text. See introduction for details about locating elements.
Close All BrowsersCloses all open browsers and resets the browser cache. - -After this keyword new indexes returned from Open Browser keyword are reset to 1. - -This keyword should be used in test or suite teardown to make sure all browsers are closed.
Close BrowserCloses the current browser.
Close WindowCloses currently opened pop-up window.
Confirm ActionDismisses 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 ButtonSend# Shows a confirmation dialog
${message}=Confirm Action# Chooses Ok
Should Be Equal${message}Are your sure?
Choose Cancel On Next Confirmation
Click ButtonSend# Shows a confirmation dialog
Confirm Action# Chooses Cancel
Current Frame Containstext, logLevel=INFOVerifies that current frame contains text. - -See Page Should Contain for explanation about loglevel argument.
Delete All CookiesDeletes all cookies.
Delete CookienameDeletes cookie matching name. - -If the cookie is not found, nothing happens.
Double Click ElementlocatorDouble click element identified by locator. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Should Be DisabledlocatorVerifies that element identified with locator is disabled. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Should Be EnabledlocatorVerifies that element identified with locator is enabled. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Should Be Visiblelocator, message=Verifies that the element identified by locator is visible. - -Herein, visible means that the element is logically visible, not optically visible in the current browser viewport. For example, an element that carries display:none is not logically visible, so using this keyword on that element would fail. - -message can be used to override the default error message. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Should Containlocator, expected, message=Verifies element identified by locator contains text expected. - -If you wish to assert an exact (not a substring) match on the text of the element, use Element Text Should Be. - -message can be used to override the default error message. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Should Not Be Visiblelocator, message=Verifies that the element identified by locator is NOT visible. - -This is the opposite of Element Should Be Visible. - -message can be used to override the default error message. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Element Text Should Belocator, expected, message=Verifies element identified by locator exactly contains text expected. - -In contrast to Element Should Contain, this keyword does not try a substring match but an exact match on the element identified by locator. - -message can be used to override the default error message. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Execute Async Javascript*codeExecutes asynchronous JavaScript code. - -code may contain multiple lines of code but must contain a return statement (with the value to be returned) at the end. - -code may be divided into multiple cells in the test data. In that case, the parts are catenated together without adding spaces. - -If code is an absolute path to an existing file, the JavaScript to execute will be read from that file. Forward slashes work as a path separator on all operating systems. - -Note that, by default, the code will be executed in the context of the Selenium object itself, so this will refer to the Selenium object. Use window to refer to the window of your application, e.g. window.document.getElementById('foo'). - -Example: - - - - - - - - - -
Execute Async JavaScriptwindow.my_js_function('arg1', 'arg2')
Execute Async JavaScript${CURDIR}/js_to_execute.js
Execute Javascript*codeExecutes the given JavaScript code. - -code may contain multiple lines of code but must contain a return statement (with the value to be returned) at the end. - -code may be divided into multiple cells in the test data. In that case, the parts are catenated together without adding spaces. - -If code is an absolute path to an existing file, the JavaScript to execute will be read from that file. Forward slashes work as a path separator on all operating systems. - -Note that, by default, the code will be executed in the context of the Selenium object itself, so this will refer to the Selenium object. Use window to refer to the window of your application, e.g. window.document.getElementById('foo'). - -Example: - - - - - - - - - -
Execute JavaScriptwindow.my_js_function('arg1', 'arg2')
Execute JavaScript${CURDIR}/js_to_execute.js
FocuslocatorSets focus to element identified by locator.
Frame Should Containlocator, text, loglevel=INFOVerifies frame identified by locator contains text. - -See Page Should Contain for explanation about loglevel argument. - -Key attributes for frames are id and name. See introduction for details about locating elements.
Get Alert MessageReturns the text of current JavaScript alert. - -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.
Get All LinksReturns a list containing ids of all links found in current page. - -If a link has no id, an empty string will be in the list instead.
Get Cookie ValuenameReturns value of cookie found with name. - -If no cookie is found with name, this keyword fails.
Get CookiesReturns all cookies of the current page.
Get Element Attributeattribute_locatorReturn value of element attribute. - -attribute_locator consists of element locator followed by an @ sign and attribute name, for example "element_id@class".
Get Horizontal PositionlocatorReturns horizontal position of element identified by locator. - -The position is returned in pixels off the left side of the page, as an integer. Fails if a matching element is not found. - -See also Get Vertical Position.
Get List ItemslocatorReturns the values in the select list identified by locator. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Get LocationReturns the current location.
Get Matching Xpath CountxpathReturns number of elements matching xpath - -If you wish to assert the number of matching elements, use Xpath Should Match X Times.
Get Selected List LabellocatorReturns the visible label of the selected element from the select list identified by locator. - -Fails if there are zero or more than one selection. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Get Selected List LabelslocatorReturns the visible labels of selected elements (as a list) from the select list identified by locator. - -Fails if there is no selection. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Get Selected List ValuelocatorReturns the value of the selected element from the select list identified by locator. - -Return value is read from value attribute of the selected element. Fails if there are zero or more than one selection. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Get Selected List ValueslocatorReturns the values of selected elements (as a list) from the select list identified by locator. - -Fails if there is no selection. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Get Selenium Implicit WaitGets the wait in seconds that is waited by Selenium. - -See Set Selenium Implicit Wait for an explanation.
Get Selenium SpeedGets the delay in seconds that is waited after each Selenium command. - -See Set Selenium Speed for an explanation.
Get Selenium TimeoutGets the timeout in seconds that is used by various keywords. - -See Set Selenium Timeout for an explanation.
Get SourceReturns the entire html source of the current page or frame.
Get Table Celltable_locator, row, column, loglevel=INFOReturns the content from a table cell. - -Row and column number start from 1. Header and footer rows are included in the count. This means that also cell content from header or footer rows can be obtained with this keyword. To understand how tables are identified, please take a look at the introduction.
Get TitleReturns title of current page.
Get ValuelocatorReturns the value attribute of element identified by locator. - -See introduction for details about locating elements.
Get Vertical PositionlocatorReturns vertical position of element identified by locator. - -The position is returned in pixels off the top of the page, as an integer. Fails if a matching element is not found. - -See also Get Horizontal Position.
Get Window IdentifiersReturns and logs id attributes of all windows known to the browser.
Get Window NamesReturns and logs names of all windows known to the browser.
Get Window TitlesReturns and logs titles of all windows known to the browser.
Go BackSimulates the user clicking the "back" button on their browser.
Go TourlNavigates the active browser instance to the provided URL.
Input Passwordlocator, textTypes the given password into text field identified by locator. - -Difference between this keyword and Input Text is that this keyword does not log the given password. See introduction for details about locating elements.
Input Textlocator, textTypes the given text into text field identified by locator. - -See introduction for details about locating elements.
List Selection Should Belocator, *itemsVerifies the selection of select list identified by locator is exactly *items. - -If you want to test that no option is selected, simply give no items. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
List Should Have No SelectionslocatorVerifies select list identified by locator has no selections. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Location Should BeurlVerifies that current URL is exactly url.
Location Should ContainexpectedVerifies that current URL contains expected.
Log LocationLogs and returns the current location.
Log Sourceloglevel=INFOLogs and returns the entire html source of the current page or frame. - -The loglevel argument defines the used log level. Valid log levels are WARN, INFO (default), DEBUG, TRACE and NONE (no logging).
Log TitleLogs and returns the title of current page.
Maximize Browser WindowMaximizes current browser window.
Mouse DownlocatorSimulates pressing the left mouse button on the element specified by locator. - -The element is pressed without releasing the mouse button. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements. - -See also the more specific keywords Mouse Down On Image and Mouse Down On Link.
Mouse Down On ImagelocatorSimulates a mouse down event on an image. - -Key attributes for images are id, src and alt. See introduction for details about locating elements.
Mouse Down On LinklocatorSimulates a mouse down event on a link. - -Key attributes for links are id, name, href and link text. See introduction for details about locating elements.
Mouse OutlocatorSimulates moving mouse away from the element specified by locator. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Mouse OverlocatorSimulates hovering mouse over the element specified by locator. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Mouse UplocatorSimulates releasing the left mouse button on the element specified by locator. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Open Browserurl, browser=firefox, alias=None, remote_url=False, desired_capabilities=None, ff_profile_dir=NoneOpens a new browser instance to given URL. - -Returns the index of this browser instance which can be used later to switch back to it. Index starts from 1 and is reset back to it when Close All Browsers keyword is used. See Switch Browser for example. - -Optional alias is an alias for the browser instance and it can be used for switching between browsers (just as index can be used). See Switch Browser for more details. - -Possible values for browser are as follows: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
firefoxFireFox
ffFireFox
internetexplorerInternet Explorer
ieInternet Explorer
googlechromeGoogle Chrome
gcGoogle Chrome
chromeGoogle Chrome
operaOpera
-Note, that you will encounter strange behavior, if you open multiple Internet Explorer browser instances. That is also why Switch Browser only works with one IE browser at most. For more information see: http://selenium-grid.seleniumhq.org/faq.html#i_get_some_strange_errors_when_i_run_multiple_internet_explorer_instances_on_the_same_machine - -Optional 'remote_url' is the url for a remote selenium server for example http://127.0.0.1/wd/hub. If you specify a value for remote you can also specify 'desired_capabilities' which is a string in the form key1:val1,key2:val2 that will be used to specify desired_capabilities to the remote server. This is useful for doing things like specify a proxy server for internet explorer or for specify browser and os if your using saucelabs.com. - -Optional 'ff_profile_dir' is the path to the firefox profile dir if you wish to overwrite the default.
Open Context MenulocatorOpens context menu on element identified by locator.
Page Should Containtext, loglevel=INFOVerifies that current page contains text. - -If this keyword fails, it automatically logs the page source using the log level specified with the optional loglevel argument. Giving NONE as level disables logging.
Page Should Contain Buttonlocator, message=, loglevel=INFOVerifies button identified by locator is found from current page. - -This keyword searches for buttons created with either input or button tag. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for buttons are id, name and value. See introduction for details about locating elements.
Page Should Contain Checkboxlocator, message=, loglevel=INFOVerifies checkbox identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Page Should Contain Elementlocator, message=, loglevel=INFOVerifies element identified by locator is found on the current page. - -message can be used to override default error message. - -See Page Should Contain for explanation about loglevel argument. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Page Should Contain Imagelocator, message=, loglevel=INFOVerifies image identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for images are id, src and alt. See introduction for details about locating elements.
Page Should Contain Linklocator, message=, loglevel=INFOVerifies link identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for links are id, name, href and link text. See introduction for details about locating elements.
Page Should Contain Listlocator, message=, loglevel=INFOVerifies select list identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for lists are id and name. See introduction for details about locating elements.
Page Should Contain Radio Buttonlocator, message=, loglevel=INFOVerifies radio button identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for radio buttons are id, name and value. See introduction for details about locating elements.
Page Should Contain Textfieldlocator, message=, loglevel=INFOVerifies text field identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for text fields are id and name. See introduction for details about locating elements.
Page Should Not Containtext, loglevel=INFOVerifies the current page does not contain text. - -See Page Should Contain for explanation about loglevel argument.
Page Should Not Contain Buttonlocator, message=, loglevel=INFOVerifies button identified by locator is not found from current page. - -This keyword searches for buttons created with either input or button tag. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for buttons are id, name and value. See introduction for details about locating elements.
Page Should Not Contain Checkboxlocator, message=, loglevel=INFOVerifies checkbox identified by locator is not found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Page Should Not Contain Elementlocator, message=, loglevel=INFOVerifies element identified by locator is not found on the current page. - -message can be used to override the default error message. - -See Page Should Contain for explanation about loglevel argument. - -Key attributes for arbitrary elements are id and name. See introduction for details about locating elements.
Page Should Not Contain Imagelocator, message=, loglevel=INFOVerifies image identified by locator is found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for images are id, src and alt. See introduction for details about locating elements.
Page Should Not Contain Linklocator, message=, loglevel=INFOVerifies image identified by locator is not found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for images are id, src and alt. See introduction for details about locating elements.
Page Should Not Contain Listlocator, message=, loglevel=INFOVerifies select list identified by locator is not found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for lists are id and name. See introduction for details about locating elements.
Page Should Not Contain Radio Buttonlocator, message=, loglevel=INFOVerifies radio button identified by locator is not found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for radio buttons are id, name and value. See introduction for details about locating elements.
Page Should Not Contain Textfieldlocator, message=, loglevel=INFOVerifies text field identified by locator is not found from current page. - -See Page Should Contain Element for explanation about message and loglevel arguments. - -Key attributes for text fields are id and name. See introduction for details about locating elements.
Press Keylocator, keySimulates user pressing key on element identified by locator. - -key is either a single character, or a numerical ASCII code of the key lead by '\'. - -Examples: - - - - - - - - - - - - - -
Press Keytext_fieldq
Press Keylogin_button\13# ASCII code for enter key
Radio Button Should Be Set Togroup_name, valueVerifies radio button group identified by group_name has its selection set to value. - -See Select Radio Button for information about how radio buttons are located.
Radio Button Should Not Be Selectedgroup_nameVerifies radio button group identified by group_name has no selection. - -See Select Radio Button for information about how radio buttons are located.
Register Keyword To Run On FailurekeywordSets the keyword to execute when a Selenium2Library keyword fails. - -keyword_name is the name of a keyword (from any available libraries) that will be executed if a Selenium2Library keyword fails. It is not possible to use a keyword that requires arguments. Using the value "Nothing" will disable this feature altogether. - -The initial keyword to use is set in importing, and the keyword that is used by default is Capture Page Screenshot. Taking a screenshot when something failed is a very useful feature, but notice that it can slow down the execution. - -This keyword returns the name of the previously registered failure keyword. It can be used to restore the original value later. - -Example: - - - - - - - - - - - - - - - - - - - -
Register Keyword To Run On FailureLog Source# Run Log Source on failure.
${previous kw}=Register Keyword To Run On FailureNothing# Disables run-on-failure functionality and stores the previous kw name in a variable.
Register Keyword To Run On Failure${previous kw}# Restore to the previous keyword.
-This run-on-failure functionality only works when running tests on Python/Jython 2.4 or newer and it does not work on IronPython at all.
Reload PageSimulates user reloading page.
Select All From ListlocatorSelects all values from multi-select list identified by id. - -Key attributes for lists are id and name. See introduction for details about locating elements.
Select CheckboxlocatorSelects checkbox identified by locator. - -Does nothing if checkbox is already selected. Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Select FramelocatorSets frame identified by locator as current frame. - -Key attributes for frames are id and name. See introduction for details about locating elements.
Select From Listlocator, *itemsSelects *items from list identified by locator - -If more than one value is given for a single-selection list, the last value will be selected. If the target list is a multi-selection list, and *items is an empty list, all values of the list will be selected. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Select Radio Buttongroup_name, valueSets selection of radio button group identified by group_name to value. - -The radio button to be selected is located by two arguments: -- group_name is used as the name of the radio input -- value is used for the value attribute or for the id attribute - -The XPath used to locate the correct radio button then looks like this: //input[@type='radio' and @name='group_name' and (@value='value' or @id='value')] - -Examples: - - - - - - - - - - - - - -
Select Radio ButtonsizeXL# Matches HTML like <input type="radio" name="size" value="XL">XL</input>
Select Radio ButtonsizesizeXL# Matches HTML like <input type="radio" name="size" value="XL" id="sizeXL">XL</input>
Select Windowlocator=NoneSelects the window found with locator as the context of actions. - -If the window is found, all subsequent commands use that window, until this keyword is used again. If the window is not found, this keyword fails. - -By default, when a locator value is provided, it is matched against the title of the window and the javascript name of the window. If multiple windows with same identifier are found, the first one is selected. - -Special locator main (default) can be used to select the main window. - -It is also possible to specify the approach Selenium2Library should take to find a window by specifying a locator strategy: - - - - - - - - - - - - - - - - - - - - - - -
StrategyExampleDescription
titleSelect Window | title=My DocumentMatches by window title
nameSelect Window | name=${name}Matches by window javascript name
urlSelect Window | url=http://google.comMatches by window's current URL
-Example: - - - - - - - - - - - - - - - - - - - - - - - - - -
Click Linkpopup_link# opens new window
Select WindowpopupName
Title Should BePopup Title
Select Window# Chooses the main window again
Set Browser Implicit WaitsecondsSets current browser's implicit wait in seconds. - -From selenium 2 function 'Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session.' - -Example: - - - - - -
Set Browser Implicit Wait10 seconds
-See also Set Selenium Implicit Wait.
Set Selenium Implicit WaitsecondsSets Selenium 2's default implicit wait in seconds and sets the implicit wait for all open browsers. - -From selenium 2 function 'Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete. This method only needs to be called one time per session.' - -Example: - - - - - - - - - - - - - - - - -
${orig wait} =Set Selenium Implicit Wait10 seconds
Perform AJAX call that is slow
Set Selenium Implicit Wait${orig wait}
Set Selenium SpeedsecondsSets the delay in seconds that is waited after each Selenium command. - -This is useful mainly in slowing down the test execution to be able to view the execution. seconds may be given in Robot Framework time format. Returns the previous speed value. - -Example: - - - - - -
Set Selenium Speed.5 seconds
Set Selenium TimeoutsecondsSets the timeout in seconds used by various keywords. - -There are several Wait ... keywords that take timeout as an argument. All of these timeout arguments are optional. The timeout used by all of them can be set globally using this keyword. See introduction for more information about timeouts. - -The previous timeout value is returned by this keyword and can be used to set the old value back later. The default timeout is 5 seconds, but it can be altered in importing. - -Example: - - - - - - - - - - - - - - - - -
${orig timeout} =Set Selenium Timeout15 seconds
Open page that loads slowly
Set Selenium Timeout${orig timeout}
Simulatelocator, eventSimulates event on element identified by locator. - -This keyword is useful if element has OnEvent handler that needs to be explicitly invoked. - -See introduction for details about locating elements.
Submit Formlocator=NoneSubmits a form identified by locator. - -If locator is empty, first form in the page will be submitted. Key attributes for forms are id and name. See introduction for details about locating elements.
Switch Browserindex_or_aliasSwitches between active browsers using index or alias. - -Index is returned from Open Browser and alias can be given to it. - -Example: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Open Browserhttp://google.comff
Location Should Behttp://google.com
Open Browserhttp://yahoo.comie2nd conn
Location Should Behttp://yahoo.com
Switch Browser1# index
Page Should ContainI'm feeling lucky
Switch Browser2nd conn# alias
Page Should ContainMore Yahoo!
Close All Browsers
-Above example expects that there was no other open browsers when opening the first one because it used index '1' when switching to it later. If you aren't sure about that you can store the index into a variable as below. - - - - - - - - - - - - - - - - - - - - -
${id} =Open Browserhttp://google.com*firefox
# Do something ...
Switch Browser${id}
Table Cell Should Containtable_locator, row, column, expected, loglevel=INFOVerifies that a certain cell in a table contains expected. - -Row and column number start from 1. This keyword passes if the specified cell contains the given content. If you want to test that the cell content matches exactly, or that it e.g. starts with some text, use Get Table Cell keyword in combination with built-in keywords such as Should Be Equal or Should Start With. - -To understand how tables are identified, please take a look at the introduction.
Table Column Should Containtable_locator, col, expected, loglevel=INFOVerifies that a specific column contains expected. - -The first leftmost column is column number 1. If the table contains cells that span multiple columns, those merged cells count as a single column. For example both tests below work, if in one row columns A and B are merged with colspan="2", and the logical third column contains "C". - -Example: - - - - - - - - - - - - - -
Table Column Should ContaintableId3C
Table Column Should ContaintableId2C
-To understand how tables are identified, please take a look at the introduction. - -See Page Should Contain Element for explanation about loglevel argument.
Table Footer Should Containtable_locator, expected, loglevel=INFOVerifies that the table footer contains expected. - -With table footer can be described as any <td>-element that is child of a <tfoot>-element. To understand how tables are identified, please take a look at the introduction. - -See Page Should Contain Element for explanation about loglevel argument.
Table Header Should Containtable_locator, expected, loglevel=INFOVerifies that the table header, i.e. any <th>...</th> element, contains expected. - -To understand how tables are identified, please take a look at the introduction. - -See Page Should Contain Element for explanation about loglevel argument.
Table Row Should Containtable_locator, row, expected, loglevel=INFOVerifies that a specific table row contains expected. - -The uppermost row is row number 1. For tables that are structured with thead, tbody and tfoot, only the tbody section is searched. Please use Table Header Should Contain or Table Footer Should Contain for tests against the header or footer content. - -If the table contains cells that span multiple rows, a match only occurs for the uppermost row of those merged cells. To understand how tables are identified, please take a look at the introduction. - -See Page Should Contain Element for explanation about loglevel argument.
Table Should Containtable_locator, expected, loglevel=INFOVerifies that expected can be found somewhere in the table. - -To understand how tables are identified, please take a look at the introduction. - -See Page Should Contain Element for explanation about loglevel argument.
Textfield Should Containlocator, expected, message=Verifies text field identified by locator contains text expected. - -message can be used to override default error message. - -Key attributes for text fields are id and name. See introduction for details about locating elements.
Textfield Value Should Belocator, expected, message=Verifies the value in text field identified by locator is exactly expected. - -message can be used to override default error message. - -Key attributes for text fields are id and name. See introduction for details about locating elements.
Title Should BetitleVerifies that current page title equals title.
Unselect CheckboxlocatorRemoves selection of checkbox identified by locator. - -Does nothing if the checkbox is not checked. Key attributes for checkboxes are id and name. See introduction for details about locating elements.
Unselect FrameSets the top frame as the current frame.
Unselect From Listlocator, *itemsUnselects given values from select list identified by locator. - -As a special case, giving empty list as *items will remove all selections. - -Select list keywords work on both lists and combo boxes. Key attributes for select lists are id and name. See introduction for details about locating elements.
Wait For Conditioncondition, timeout=None, error=NoneWaits until the given condition is true or timeout expires. - -code may contain multiple lines of code but must contain a return statement (with the value to be returned) at the end - -The condition can be arbitrary JavaScript expression but must contain a return statement (with the value to be returned) at the end. See Execute JavaScript for information about accessing the actual contents of the window through JavaScript. - -error can be used to override the default error message. - -See introduction for more information about timeout and its default value. - -See also Wait Until Page Contains, Wait Until Page Contains Element and BuiltIn keyword Wait Until Keyword Succeeds.
Wait Until Page Containstext, timeout=None, error=NoneWaits until text appears on current page. - -Fails if timeout expires before the text appears. See introduction for more information about timeout and its default value. - -error can be used to override the default error message. - -See also Wait Until Page Contains Element, Wait For Condition and BuiltIn keyword Wait Until Keyword Succeeds.
Wait Until Page Contains Elementlocator, timeout=None, error=NoneWaits until element specified with locator appears on current page. - -Fails if timeout expires before the element appears. See introduction for more information about timeout and its default value. - -error can be used to override the default error message. - -See also Wait Until Page Contains, Wait For Condition and BuiltIn keyword Wait Until Keyword Succeeds.
Xpath Should Match X Timesxpath, expected_xpath_count, message=, loglevel=INFOVerifies that the page contains the given number of elements located by the given xpath. + + + + + + + + + + + + -See Page Should Contain Element for explanation about message and loglevel arguments.
- From f5c31aa2aa38ae0943a2604f7c76032ab8ab18eb Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 07:48:24 -0700 Subject: [PATCH 082/105] Deal more directly with building of windows installers --- BUILD.rst | 9 ++++++++- build_dist.py | 20 +++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/BUILD.rst b/BUILD.rst index 8c2731f70..08fd81d0a 100644 --- a/BUILD.rst +++ b/BUILD.rst @@ -85,10 +85,17 @@ This script will: - Generate source distribution packages in .tar.gz and .zip formats - Generate Python eggs for Python 2.6 and 2.7 -- Generate binary installers for Windows x86 and x64 +- Generate binary installers for Windows x86 and x64 (if run on Windows) - Generate a demo distribution package in .zip format. - Re-generate keyword documentation in doc folder +Note: The Windows installers will only be built if the script is run on +a Windows machine. If the rest of the distribution has been built on +a non-Windows machine and you want to build just the Windows installers, +use the --winonly flag:: + + python build_dist.py --winonly + Publishing a New Release ------------------------ diff --git a/build_dist.py b/build_dist.py index dab36e865..f0b5d5239 100644 --- a/build_dist.py +++ b/build_dist.py @@ -13,8 +13,13 @@ def main(): 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.add_argument('--release', action='store_true') + parser.add_argument('--winonly', action='store_true') args = parser.parse_args() + if args.winonly: + run_builds(args) + return + clear_dist_folder() run_register(args) run_builds(args) @@ -37,11 +42,16 @@ def run_register(args): def run_builds(args): print - _run_setup(args.py_27_path, "sdist", [ "--formats=gztar,zip" ], args.release) - _run_setup(args.py_26_path, "bdist_egg", [], args.release) - _run_setup(args.py_27_path, "bdist_egg", [], args.release) - _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) + 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) + _run_setup(args.py_27_path, "bdist_egg", [], args.release) + if os.name == 'nt': + _run_setup(args.py_27_path, "bdist_msi", [ "--plat-name=win32" ], args.release) + _run_setup(args.py_27_path, "bdist_msi", [ "--plat-name=win-amd64" ], args.release) + else: + print + print("Windows binary installers cannot be built on this platform!") def run_demo_packaging(): import package From 6304786f8359c7d813614794cb6a92a63dd29b4e Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 07:55:28 -0700 Subject: [PATCH 083/105] Keep building .exe installers for Windows, not MSI --- build_dist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_dist.py b/build_dist.py index f0b5d5239..6b5dd3530 100644 --- a/build_dist.py +++ b/build_dist.py @@ -47,8 +47,8 @@ def run_builds(args): _run_setup(args.py_26_path, "bdist_egg", [], args.release) _run_setup(args.py_27_path, "bdist_egg", [], args.release) if os.name == 'nt': - _run_setup(args.py_27_path, "bdist_msi", [ "--plat-name=win32" ], args.release) - _run_setup(args.py_27_path, "bdist_msi", [ "--plat-name=win-amd64" ], args.release) + _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("Windows binary installers cannot be built on this platform!") From d4daaf2d489535964a4b566a0fca298f3112eed5 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 08:16:08 -0700 Subject: [PATCH 084/105] Minor update to build doc --- BUILD.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/BUILD.rst b/BUILD.rst index 08fd81d0a..a4ea6d6fb 100644 --- a/BUILD.rst +++ b/BUILD.rst @@ -111,7 +111,8 @@ In addition to building the distribution, this will: After building and releasing to PyPI: -- Upload dist packages to the `downloads section on GitHub`_ +- Upload dist packages to the `downloads section on GitHub`_ (all dist +packages except the eggs) - Publish the keyword documentation (see `Pushing Keyword Documentation`_) Note: To publish a release, you will need to: @@ -130,10 +131,15 @@ First, switch to the `gh-pages` branch:: git checkout gh-pages +If you get an error like "pathspec 'gh-pages' did not match any file(s) known to git", +run the following to setup the upstream configuration for the gh-pages branch:: + + git checkout -t origin/gh-pages + Next, pull the keyword documentation you generated in the master branch and commit it:: git checkout master doc/Selenium2Library.html - git add . + git add doc/Selenium2Library.html git commit Then, push it to the remote:: From e63cc31790a64efdab6558580a3f84375c161e26 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 08:17:06 -0700 Subject: [PATCH 085/105] Minor update to build doc --- BUILD.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/BUILD.rst b/BUILD.rst index a4ea6d6fb..500dc2c5e 100644 --- a/BUILD.rst +++ b/BUILD.rst @@ -111,8 +111,7 @@ In addition to building the distribution, this will: After building and releasing to PyPI: -- Upload dist packages to the `downloads section on GitHub`_ (all dist -packages except the eggs) +- Upload dist packages to the `downloads section on GitHub`_ (all dist packages except the eggs) - Publish the keyword documentation (see `Pushing Keyword Documentation`_) Note: To publish a release, you will need to: From 0ee8ee41fd6af112280d7b71bf93146b49c7c75f Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 08:28:16 -0700 Subject: [PATCH 086/105] Add CHANGES file --- CHANGES.rst | 7 +++++++ doc/generate_readmes.py | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 CHANGES.rst diff --git a/CHANGES.rst b/CHANGES.rst new file mode 100644 index 000000000..4adc20930 --- /dev/null +++ b/CHANGES.rst @@ -0,0 +1,7 @@ +Release Notes +============= + +1.0.1 +----- +- Support for Robot Framework 2.7 +- Improvements to distribution build script and improved documentation diff --git a/doc/generate_readmes.py b/doc/generate_readmes.py index 29bcf9181..be6828b74 100644 --- a/doc/generate_readmes.py +++ b/doc/generate_readmes.py @@ -11,7 +11,8 @@ README_FILES = [ "README.rst", "INSTALL.rst", - "BUILD.rst" + "BUILD.rst", + "CHANGES.rst" ] def main(): From 32b42726cdf05cd3c7bf4df623d48a9ebc50b596 Mon Sep 17 00:00:00 2001 From: Ryan Tomac Date: Fri, 1 Jun 2012 09:43:49 -0700 Subject: [PATCH 087/105] Add note in docs on tagging release --- BUILD.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/BUILD.rst b/BUILD.rst index 500dc2c5e..545beb6d3 100644 --- a/BUILD.rst +++ b/BUILD.rst @@ -113,6 +113,7 @@ After building and releasing to PyPI: - Upload dist packages to the `downloads section on GitHub`_ (all dist packages except the eggs) - Publish the keyword documentation (see `Pushing Keyword Documentation`_) +- Tag the release (see `Tagging a Release`_) Note: To publish a release, you will need to: @@ -120,6 +121,20 @@ Note: To publish a release, you will need to: - Setup your `.pypirc file`_ (goes in the root of your home directory) +Tagging a Release +----------------- + +It's our policy to tag each release. To do so, run:: + + git tag -a v -m " release" + git push --tags + +E.g.:: + + git tag -a v1.0.0 -m "1.0.0 release" + git push --tags + + Pushing Keyword Documentation ----------------------------- From 9a1bd973848f5c342474b520e2be76ab5a76cc82 Mon Sep 17 00:00:00 2001 From: jollychang Date: Mon, 2 Jul 2012 11:17:37 +0800 Subject: [PATCH 088/105] fix get text --- src/Selenium2Library/keywords/_element.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Selenium2Library/keywords/_element.py b/src/Selenium2Library/keywords/_element.py index e107d526c..fa8aec79f 100644 --- a/src/Selenium2Library/keywords/_element.py +++ b/src/Selenium2Library/keywords/_element.py @@ -229,6 +229,13 @@ def get_value(self, locator): """ return self._get_value(locator) + def get_text(self, locator): + """Returns the text of element identified by `locator`. + + See `introduction` for details about locating elements. + """ + return self._get_text(locator) + def get_vertical_position(self, locator): """Returns vertical position of element identified by `locator`. From 45f26f22b307c08077d24096e4a2c0ec261343e5 Mon Sep 17 00:00:00 2001 From: Ilmari Kontulainen Date: Sat, 9 Jun 2012 17:06:26 -0500 Subject: [PATCH 089/105] acceptance test cases for iframes --- test/acceptance/keywords/frames.txt | 15 +++++++++++++++ test/resources/html/frames/iframes.html | 4 ++++ 2 files changed, 19 insertions(+) create mode 100644 test/resources/html/frames/iframes.html diff --git a/test/acceptance/keywords/frames.txt b/test/acceptance/keywords/frames.txt index 94e5bd8e3..6bcda908b 100644 --- a/test/acceptance/keywords/frames.txt +++ b/test/acceptance/keywords/frames.txt @@ -10,6 +10,12 @@ Frame Should Contain Frame Should contain right You're looking at right. Frame Should Contain left Links +Frame Should Contain should also work with iframes + [setup] Go To Page "frames/iframes.html" + Frame Should contain right You're looking at right. + Frame Should Contain left Links + + Select And Unselect Frame [Documentation] LOG 2 Selecting frame 'left'. Select Frame left @@ -17,3 +23,12 @@ Select And Unselect Frame Unselect Frame Select Frame right Current Frame Contains You're looking at foo. + +Select And Unselect Frame should also work with iframes + [Documentation] LOG 2 Selecting frame 'leftiframe'. + [setup] Go To Page "frames/iframes.html" + Select Frame left + Click Link foo + Unselect Frame + Select Frame right + Current Frame Contains You're looking at foo. \ No newline at end of file diff --git a/test/resources/html/frames/iframes.html b/test/resources/html/frames/iframes.html new file mode 100644 index 000000000..445ed72c2 --- /dev/null +++ b/test/resources/html/frames/iframes.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 3328a68e6f2255d6bea358a264a8bfcecaab521a Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Thu, 28 Jun 2012 12:26:08 -0400 Subject: [PATCH 090/105] Removed 'frame' tag when searching for frames, either or + + From 8f83976ec12485d52bd58d4362a4a53653719cef Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Thu, 28 Jun 2012 15:40:46 -0400 Subject: [PATCH 092/105] Applied fix which allows the internal function _page_conatains to search both and ':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='
',m="";if(f||!i)m+=''+g[b]+"";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+=''+c+"";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="
",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&bd?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.21",window["DP_jQuery_"+dpuuid]=$}(jQuery),function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},f=a.attrFn||{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0,click:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||" ",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("
")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){return b.close(a),!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a("")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a("").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;return a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle),a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1===c._trigger("beforeClose",b))return;return c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d),c},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;return e.modal&&!b||!e.stack&&!e.modal?d._trigger("focus",c):(e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c),d)},open:function(){if(this._isOpen)return;var b=this,c=b.options,d=b.uiDialog;return b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode!==a.ui.keyCode.TAB)return;var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey)return d.focus(1),!1;if(b.target===d[0]&&b.shiftKey)return e.focus(1),!1}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open"),b},_createButtons:function(b){var c=this,d=!1,e=a("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=a("
").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a('').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(g);a.each(d,function(a,b){if(a==="click")return;a in f?e[a](b):e.attr(a,b)}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||" "))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.21",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");return b||(this.uuid+=1,b=this.uuid),"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()
").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});return a.fn.bgiframe&&c.bgiframe(),this.instances.push(c),c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;return a.browser.msie&&a.browser.version<7?(b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),b0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()}(jQuery),function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.21"})}(jQuery),function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("
").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;ic&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i),j===!1?!1:(this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0,!0))},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);return this._slide(a,this._handleIndex,c),!1},_mouseStop:function(a){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;return this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e,this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};return this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c1){this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);return}if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;return Math.abs(c)*2>=b&&(d+=c>0?b:-b),parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.21"})}(jQuery),function(a,b){function e(){return++c}function f(){return++d}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
  • #{label}
  • "},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash)return e.selected=a,!1}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1)return this.blur(),!1;e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected"))return e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur(),!1;if(!f.length)return e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur(),!1}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){return typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$='"+a+"']"))),a},destroy:function(){var b=this.options;return this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie),this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);return j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e])),this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();return d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0])),this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)==-1)return;return this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b])),this},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;return a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a]))),this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;return this.anchors.eq(a).trigger(this.options.event+".tabs"),this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}return this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs"),this},abort:function(){return this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup(),this},url:function(a,b){return this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b),this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.21"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a Date: Sat, 30 Jun 2012 07:45:48 -0700 Subject: [PATCH 100/105] Add HTMLUnit remote driver support --- .../keywords/_browsermanagement.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index 8b1cba50c..dc10d2b2d 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -16,7 +16,9 @@ 'googlechrome': "_make_chrome", 'gc': "_make_chrome", 'chrome': "_make_chrome", - 'opera' : "_make_opera" + 'opera' : "_make_opera", + 'htmlunit' : "_make_htmlunit", + 'htmlunitwithjs' : "_make_htmlunitwithjs" } class _BrowserManagementKeywords(KeywordGroup): @@ -72,6 +74,8 @@ def open_browser(self, url, browser='firefox', alias=None,remote_url=False, | gc | Google Chrome | | chrome | Google Chrome | | opera | Opera | + | htmlunit | HTMLUnit | + | htmlunitwithjs | HTMLUnit with Javascipt support | Note, that you will encounter strange behavior, if you open @@ -92,7 +96,7 @@ def open_browser(self, url, browser='firefox', alias=None,remote_url=False, wish to overwrite the default. """ if remote_url: - self._info("Opening broser '%s' to base url '%s' through remote server at '%s'" + self._info("Opening browser '%s' to base url '%s' through remote server at '%s'" % (browser, url, remote_url)) else: self._info("Opening browser '%s' to base url '%s'" % (browser, url)) @@ -431,6 +435,14 @@ def _make_opera(self , remote , desired_capabilities , profile_dir): return self._generic_make_browser(webdriver.Opera, webdriver.DesiredCapabilities.OPERA, remote, desired_capabilities) + def _make_htmlunit(self , remote , desired_capabilities , profile_dir): + return self._generic_make_browser(webdriver.Remote, + webdriver.DesiredCapabilities.HTMLUNIT, remote, desired_capabilities) + + def _make_htmlunitwithjs(self , remote , desired_capabilities , profile_dir): + return self._generic_make_browser(webdriver.Remote, + webdriver.DesiredCapabilities.HTMLUNITWITHJS, remote, desired_capabilities) + def _generic_make_browser(self, webdriver_type , desired_cap_type, remote_url, desired_caps): '''most of the make browser functions just call this function which creates the From cd1733689c5c78e47979ddea52319840e11be720 Mon Sep 17 00:00:00 2001 From: Jeremy Johnson Date: Sun, 1 Jul 2012 08:12:52 +0800 Subject: [PATCH 101/105] added Change notes for HTMLUnit support --- CHANGES.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index ad3f564a3..ab61c8cbc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,6 +14,10 @@ Release Notes target` and `drag and drop by offset source xoffset yoffset` [mamathanag] and [j1z0] +- Added HTMLUnit and HTMLUnitWithJS support. Just use a line like: + `Open Browser [initial page url] remote_url=[the selenium-server url] browser=htmlunit` + [SoCalLongboard] + 1.0.1 ----- - Support for Robot Framework 2.7 From 1aa168298857d580e74df78bf5a5db89bd1ed24a Mon Sep 17 00:00:00 2001 From: Jeremy Johnson Date: Sun, 1 Jul 2012 08:24:17 +0800 Subject: [PATCH 102/105] added unit tests for HTMLUnit browser creation --- test/unit/keywords/test_browsermanagement.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/keywords/test_browsermanagement.py b/test/unit/keywords/test_browsermanagement.py index 88bccab30..6d83ad074 100644 --- a/test/unit/keywords/test_browsermanagement.py +++ b/test/unit/keywords/test_browsermanagement.py @@ -34,6 +34,12 @@ def test_create_opera_browser(self): def test_create_remote_browser(self): self.verify_browser(webdriver.Remote, "chrome", remote="http://127.0.0.1/wd/hub") + def test_create_htmlunit_browser(self): + self.verify_browser(webdriver.Remote, "htmlunit") + + def test_create_htmlunitwihtjs_browser(self): + self.verify_browser(webdriver.Remote, "htmlunitwithjs") + def test_create_desired_capabilities(self): bm = _BrowserManagementKeywords() expected_caps = "key1:val1,key2:val2" From 53d6e233f93ece21e4fe59add5cbb8963391f0bd Mon Sep 17 00:00:00 2001 From: Mika Petteri Korhonen Date: Wed, 21 Dec 2011 12:24:56 +0200 Subject: [PATCH 103/105] added the get_text back. --- src/Selenium2Library/keywords/_element.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Selenium2Library/keywords/_element.py b/src/Selenium2Library/keywords/_element.py index 652f6ed6b..5f5d7d797 100644 --- a/src/Selenium2Library/keywords/_element.py +++ b/src/Selenium2Library/keywords/_element.py @@ -228,6 +228,13 @@ def get_value(self, locator): See `introduction` for details about locating elements. """ return self._get_value(locator) + + def get_text(self, locator): + """Returns the text value of element identified by `locator`. + + See `introduction` for details about locating elements. + """ + return self._get_text(locator) def get_text(self, locator): """Returns the text value of element identified by `locator`. From 91a4a78a5adb72f5c78582a2209c2ebc809df25f Mon Sep 17 00:00:00 2001 From: William Zhang Date: Wed, 1 Aug 2012 10:22:37 +0800 Subject: [PATCH 104/105] maximizes browser for mutiple tab window --- src/Selenium2Library/keywords/_browsermanagement.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Selenium2Library/keywords/_browsermanagement.py b/src/Selenium2Library/keywords/_browsermanagement.py index dc10d2b2d..5919f1f9d 100644 --- a/src/Selenium2Library/keywords/_browsermanagement.py +++ b/src/Selenium2Library/keywords/_browsermanagement.py @@ -167,8 +167,7 @@ def get_window_titles(self): def maximize_browser_window(self): """Maximizes current browser window.""" - self._current_browser().execute_script( - "if (window.screen) { window.moveTo(0, 0); window.resizeTo(window.screen.availWidth, window.screen.availHeight); }") + self._current_browser().maximize_window() def select_frame(self, locator): """Sets frame identified by `locator` as current frame. From af9ebd0c231281f28a983c8b72338a77438de84d Mon Sep 17 00:00:00 2001 From: William Zhang Date: Wed, 1 Aug 2012 11:00:49 +0800 Subject: [PATCH 105/105] revert