/wire.py
Python | 1912 lines | 1803 code | 64 blank | 45 comment | 77 complexity | 3afaf039ba0db3a62eea6e22057e3ff4 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-1.0, MIT, Apache-2.0, BSD-3-Clause, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- # Copyright 2008-2010 WebDriver committers
- # Copyright 2008-2010 Google Inc. All Rights Reserved.
- #
- # 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.
- """Script for generating the wire protocol wiki documentation.
- This script is probably overkill, but it ensures commands are documented with
- consistent formatting.
- Usage:
- python trunk/wire.py --help
- """
- import logging
- import optparse
- import os
- import re
- import sys
- DEFAULT_WIKI_PATH = os.path.join('..', 'wiki', 'JsonWireProtocol.wiki')
- class Resource(object):
- def __init__(self, path):
- self.path = path
- self.methods = []
- def __getattribute__(self, attr):
- try:
- return super(Resource, self).__getattribute__(attr)
- except AttributeError, e:
- if self.methods:
- return self.methods[len(self.methods) - 1].__getattribute__(attr)
- raise e
- def Post(self, summary):
- return self.AddMethod(Method(self, 'POST', summary))
- def Get(self, summary):
- return self.AddMethod(Method(self, 'GET', summary))
- def Delete(self, summary):
- return self.AddMethod(Method(self, 'DELETE', summary))
- def AddMethod(self, method):
- self.methods.append(method)
- return self
- def ToWikiString(self):
- str = '=== %s ===\n' % self.path
- for method in self.methods:
- str = '%s%s' % (str, method.ToWikiString(self.path))
- return str
- def ToWikiTableString(self):
- return ''.join(m.ToWikiTableString() for m in self.methods)
- class SessionResource(Resource):
- def AddMethod(self, method):
- return (Resource.AddMethod(self, method).
- AddUrlParameter(':sessionId',
- 'ID of the session to route the command to.'))
- class ElementResource(SessionResource):
- def AddMethod(self, method):
- return (SessionResource.AddMethod(self, method).
- AddUrlParameter(':id',
- 'ID of the element to route the command to.').
- AddError('StaleElementReference',
- 'If the element referenced by `:id` is no longer attached '
- 'to the page\'s DOM.'))
- def RequiresVisibility(self):
- return self.AddError('ElementNotVisible',
- 'If the referenced element is not visible on the page '
- '(either is hidden by CSS, has 0-width, or has 0-height)')
- def RequiresEnabledState(self):
- return self.AddError('InvalidElementState',
- 'If the referenced element is disabled.')
- class Method(object):
- def __init__(self, parent, method, summary):
- self.parent = parent
- self.method = method
- self.summary = summary
- self.url_parameters = []
- self.json_parameters = []
- self.return_type = None
- self.errors = {}
- def AddUrlParameter(self, name, description):
- self.url_parameters.append({
- 'name': name,
- 'desc': description})
- return self.parent
- def AddJsonParameter(self, name, type, description):
- self.json_parameters.append({
- 'name': name,
- 'type': type,
- 'desc': description})
- return self.parent
- def AddError(self, type, summary):
- self.errors[type] = {'type': type, 'summary': summary}
- return self.parent
- def SetReturnType(self, type, description):
- self.return_type = {
- 'type': type,
- 'desc': description}
- return self.parent
- def _GetUrlParametersWikiString(self):
- if not self.url_parameters:
- return ''
- return '''
- <dd>
- <dl>
- <dt>*URL Parameters:*</dt>
- %s
- </dl>
- </dd>''' % '\n'.join('<dd>`%s` - %s</dd>' %
- (param['name'], param['desc'])
- for param in self.url_parameters)
- def _GetJsonParametersWikiString(self):
- if not self.json_parameters:
- return ''
- return '''
- <dd>
- <dl>
- <dt>*JSON Parameters:*</dt>
- %s
- </dl>
- </dd>''' % '\n'.join('<dd>`%s` - `%s` %s</dd>' %
- (param['name'], param['type'], param['desc'])
- for param in self.json_parameters)
- def _GetReturnTypeWikiString(self):
- if not self.return_type:
- return ''
- type = ''
- if self.return_type['type']:
- type = '`%s` ' % self.return_type['type']
- return '''
- <dd>
- <dl>
- <dt>*Returns:*</dt>
- <dd>%s%s</dd>
- </dl>
- </dd>''' % (type, self.return_type['desc'])
- def _GetErrorWikiString(self):
- if not self.errors.values():
- return ''
- return '''
- <dd>
- <dl>
- <dt>*Potential Errors:*</dt>
- %s
- </dl>
- </dd>''' % '\n'.join('<dd>`%s` - %s</dd>' %
- (error['type'], error['summary'])
- for error in self.errors.values())
- def ToWikiString(self, path):
- return '''
- <dl>
- <dd>
- ==== %s %s ====
- </dd>
- <dd>
- <dl>
- <dd>%s</dd>%s%s%s%s
- </dl>
- </dd>
- </dl>
- ''' % (self.method, path, self.summary,
- self._GetUrlParametersWikiString(),
- self._GetJsonParametersWikiString(),
- self._GetReturnTypeWikiString(),
- self._GetErrorWikiString())
- def ToWikiTableString(self):
- return '|| %s || [#%s_%s %s] || %s ||\n' % (
- self.method, self.method, self.parent.path, self.parent.path,
- self.summary[:self.summary.find('.') + 1].replace('\n', '').strip())
- class ErrorCode(object):
- def __init__(self, code, summary, detail):
- self.code = code
- self.summary = summary
- self.detail = detail
- def ToWikiTableString(self):
- return '|| %d || `%s` || %s ||' % (self.code, self.summary, self.detail)
- class AbstractErrorCodeGatherer(object):
- def __init__(self, name, path_to_error_codes, regex):
- self.name = name
- self.path_to_error_codes = path_to_error_codes
- self.regex = regex
- def __str__(self):
- return self.name
- def get_error_codes(self):
- error_codes = {}
- error_codes_file = open(self.path_to_error_codes, 'r')
- try:
- for line in error_codes_file:
- match = self.regex.match(line)
- if match is not None:
- name, code = self.extract_from_match(match)
- error_codes[code] = name
- finally:
- error_codes_file.close()
- return error_codes
- def extract_from_match(self, match):
- raise NotImplementedError
- class JavaErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes):
- super(JavaErrorCodeGatherer, self).__init__( \
- 'Java',
- path_to_error_codes, \
- re.compile('^\s*public static final int ([A-Z_]+) = (\d+);$'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(2))
- class JavascriptErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes, name):
- super(JavascriptErrorCodeGatherer, self).__init__( \
- name,
- path_to_error_codes, \
- re.compile('^\s*([A-Z_]+): (\d+)'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(2))
- class RubyErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes):
- super(RubyErrorCodeGatherer, self).__init__( \
- 'Ruby',
- path_to_error_codes, \
- re.compile('^\s*(([A-Z][a-z]*)+),?\s*# (\d+)$'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(len(match.groups())))
- class PythonErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes):
- super(PythonErrorCodeGatherer, self).__init__( \
- 'Python',
- path_to_error_codes, \
- re.compile('^\s*([A-Z_]+) = (\d+)$'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(2))
- class CErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes):
- super(CErrorCodeGatherer, self).__init__( \
- 'C',
- path_to_error_codes, \
- re.compile('^#define ([A-Z]+)\s+(\d+)$'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(2))
- class CSharpErrorCodeGatherer(AbstractErrorCodeGatherer):
- def __init__(self, path_to_error_codes):
- super(CSharpErrorCodeGatherer, self).__init__( \
- 'C#',
- path_to_error_codes, \
- re.compile('^\s*(([A-Z][a-z]*)+) = (\d+)'))
- def extract_from_match(self, match):
- return match.group(1), int(match.group(len(match.groups())))
- class ErrorCodeChecker(object):
- def __init__(self):
- self.gatherers = []
- self.inconsistencies = {}
- def using(self, gatherer):
- self.gatherers.append(gatherer)
- return self
- def check_error_codes_are_consistent(self, json_error_codes):
- logging.info('Checking error codes are consistent across languages and \
- browsers')
- num_missing = 0
- for gatherer in self.gatherers:
- if not os.path.exists(gatherer.path_to_error_codes):
- logging.warn(' Unable to locate error codes for %s (//%s)',
- gatherer, gatherer.path_to_error_codes)
- num_missing += 1
- else:
- self.compare(gatherer, json_error_codes)
- if not num_missing and not self.inconsistencies:
- logging.info('All error codes are consistent')
- return False
- for code,(present,missing) in self.inconsistencies.items():
- logging.error('Error code %d was present in %s but not %s',
- code, present, missing)
- return True
- def add_inconsistency(self, code, present_in, missing_from):
- if self.inconsistencies.has_key(code):
- already_present, already_missing = self.inconsistencies[code]
- already_present.add(present_in)
- already_missing.add(missing_from)
- else:
- self.inconsistencies[code] = (set([present_in]), set([missing_from]))
- def compare(self, gatherer, raw_json_error_codes):
- logging.info('Checking %s (%s)' % (gatherer, gatherer.path_to_error_codes))
- gathered_error_codes = gatherer.get_error_codes()
- json_error_codes = map(lambda code: code.code, raw_json_error_codes)
- for json_error_code in json_error_codes:
- if not gathered_error_codes.has_key(json_error_code):
- self.add_inconsistency(json_error_code, 'JSON', str(gatherer))
- for gathered_code,_ in gathered_error_codes.items():
- if not gathered_code in json_error_codes:
- self.add_inconsistency(gathered_code, str(gatherer), 'JSON')
- def GetDefaultWikiPath():
- dirname = os.path.dirname(__file__)
- if not dirname:
- return DEFAULT_WIKI_PATH
- return os.path.join('.', dirname, DEFAULT_WIKI_PATH)
- def ChangeToTrunk():
- dirname = os.path.dirname(__file__)
- if dirname:
- logging.info('Changing to %s', os.path.abspath(dirname))
- os.chdir(dirname)
- def main():
- logging.basicConfig(format='[ %(filename)s ] %(message)s',
- level=logging.INFO)
- default_path = GetDefaultWikiPath()
- parser = optparse.OptionParser('Usage: %prog [options]')
- parser.add_option('-c', '--check_error_codes', dest='check_errors',
- default=False,
- help='Whether to abort if error codes are inconsistent.')
- parser.add_option('-w', '--wiki', dest='wiki', metavar='FILE',
- default=default_path,
- help='Which file to write to. Defaults to %default')
- (options, args) = parser.parse_args()
- wiki_path = options.wiki
- if wiki_path is not default_path:
- wiki_path = os.path.abspath(wiki_path)
- if not os.path.exists(wiki_path):
- logging.error('Unable to locate wiki file: %s', wiki_path)
- parser.print_help()
- sys.exit(2)
- wiki_path = os.path.abspath(wiki_path)
- ChangeToTrunk()
- error_codes = [
- ErrorCode(0, 'Success', 'The command executed successfully.'),
- # ErrorCode(1, 'IndexOutOfBounds', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- # ErrorCode(2, 'NoCollection', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- # ErrorCode(3, 'NoString', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- # ErrorCode(4, 'NoStringLength', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- # ErrorCode(5, 'NoStringWrapper', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(6, 'NoSuchDriver', 'A session is either terminated or not started'),
- ErrorCode(7, 'NoSuchElement', 'An element could not be located on the \
- page using the given search parameters.'),
- ErrorCode(8, 'NoSuchFrame', 'A request to switch to a frame could not be \
- satisfied because the frame could not be found.'),
- ErrorCode(9, 'UnknownCommand', 'The requested resource could not be \
- found, or a request was received using an HTTP method that is not supported \
- by the mapped resource.'),
- ErrorCode(10, 'StaleElementReference', 'An element command failed \
- because the referenced element is no longer attached to the DOM.'),
- ErrorCode(11, 'ElementNotVisible', 'An element command could not \
- be completed because the element is not visible on the page.'),
- ErrorCode(12, 'InvalidElementState', 'An element command could not be \
- completed because the element is in an invalid state (e.g. attempting to \
- click a disabled element).'),
- ErrorCode(13, 'UnknownError', 'An unknown server-side error occurred \
- while processing the command.'),
- # ErrorCode(14, 'ExpectedError', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(15, 'ElementIsNotSelectable', 'An attempt was made to select \
- an element that cannot be selected.'),
- # ErrorCode(16, 'NoSuchDocument', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(17, 'JavaScriptError', 'An error occurred while executing user \
- supplied !JavaScript.'),
- # ErrorCode(18, 'NoScriptResult', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(19, 'XPathLookupError', 'An error occurred while searching for \
- an element by XPath.'),
- # ErrorCode(20, 'NoSuchCollection', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(21, 'Timeout', 'An operation did not complete before its \
- timeout expired.'),
- # ErrorCode(22, 'NullPointer', 'This is probably an unused \
- #implementation detail of an old version of the IEDriver.'),
- ErrorCode(23, 'NoSuchWindow', 'A request to switch to a different window \
- could not be satisfied because the window could not be found.'),
- ErrorCode(24, 'InvalidCookieDomain', 'An illegal attempt was made to set \
- a cookie under a different domain than the current page.'),
- ErrorCode(25, 'UnableToSetCookie', 'A request to set a cookie\'s value \
- could not be satisfied.'),
- ErrorCode(26, 'UnexpectedAlertOpen', 'A modal dialog was open, blocking \
- this operation'),
- ErrorCode(27, 'NoAlertOpenError', 'An attempt was made to operate on a \
- modal dialog when one was not open.'),
- ErrorCode(28, 'ScriptTimeout', 'A script did not complete before its \
- timeout expired.'),
- ErrorCode(29, 'InvalidElementCoordinates', 'The coordinates provided to \
- an interactions operation are invalid.'),
- ErrorCode(30, 'IMENotAvailable', 'IME was not available.'),
- ErrorCode(31, 'IMEEngineActivationFailed', 'An IME engine could not be \
- started.'),
- ErrorCode(32, 'InvalidSelector', 'Argument was an invalid selector \
- (e.g. XPath/CSS).'),
- ErrorCode(33, 'SessionNotCreatedException', 'A new session could not be created.'),
- ErrorCode(34, 'MoveTargetOutOfBounds', 'Target provided for a move action is out of bounds.')
- ]
- error_checker = ErrorCodeChecker() \
- .using(JavaErrorCodeGatherer('java/client/src/org/openqa/selenium/remote/ErrorCodes.java')) \
- .using(JavascriptErrorCodeGatherer('javascript/atoms/error.js', 'Javascript atoms')) \
- .using(JavascriptErrorCodeGatherer('javascript/firefox-driver/js/errorcode.js', 'Javascript firefox driver')) \
- .using(RubyErrorCodeGatherer('rb/lib/selenium/webdriver/common/error.rb')) \
- .using(PythonErrorCodeGatherer('py/selenium/webdriver/remote/errorhandler.py')) \
- .using(CErrorCodeGatherer('cpp/webdriver-interactions/errorcodes.h')) \
- .using(CSharpErrorCodeGatherer('dotnet/src/WebDriver/WebDriverResult.cs'))
- if (not error_checker.check_error_codes_are_consistent(error_codes)
- and options.check_errors):
- sys.exit(1)
- resources = []
- resources.append(Resource('/status').
- Get('''
- Query the server\'s current status. The server should respond with a general \
- "HTTP 200 OK" response if it is alive and accepting commands. The response \
- body should be a JSON object describing the state of the server. All server \
- implementations should return two basic objects describing the server's \
- current platform and when the server was built. All fields are optional; \
- if omitted, the client should assume the value is uknown. Furthermore, \
- server implementations may include additional fields not listed here.
- || *Key* || *Type* || *Description* ||
- || build || object || ||
- || build.version || string || A generic release label (i.e. "2.0rc3") ||
- || build.revision || string || The revision of the local source control client \
- from which the server was built ||
- || build.time || string || A timestamp from when the server was built. ||
- || os || object || ||
- || os.arch || string || The current system architecture. ||
- || os.name || string || The name of the operating system the server is \
- currently running on: "windows", "linux", etc. ||
- || os.version || string || The operating system version. ||
- ''').
- SetReturnType('{object}',
- 'An object describing the general status of the server.'))
- resources.append(
- Resource('/session').
- Post('''
- Create a new session. The server should attempt to create a session that most \
- closely matches the desired and required capabilities. Required capabilities \
- have higher priority than desired capabilities and must be set for the session \
- to be created.''').
- AddJsonParameter('desiredCapabilities',
- '{object}',
- 'An object describing the session\'s '
- '[#Desired_Capabilities desired capabilities].').
- AddJsonParameter('requiredCapabilities',
- '{object}',
- 'An object describing the session\'s '
- '[#Desired_Capabilities required capabilities] (Optional).').
- SetReturnType(None,
- 'A `303 See Other` redirect to `/session/:sessionId`, where'
- ' `:sessionId` is the ID of the newly created session.').
- AddError('SessionNotCreatedException', 'If a required capability could not be set.'))
- resources.append(
- Resource('/sessions').
- Get('''
- Returns a list of the currently active sessions. Each session will be \
- returned as a list of JSON objects with the following keys:
- || *Key* || *Type* || *Description ||
- || id || string || The session ID. ||
- || capabilities || object || An object describing the session's \
- [#Actual_Capabilities capabilities]. ||
- ''').
- SetReturnType('{Array.<Object>}',
- 'A list of the currently active sessions.'))
- resources.append(
- SessionResource('/session/:sessionId').
- Get('Retrieve the capabilities of the specified session.').
- SetReturnType('{object}',
- 'An object describing the session\'s '
- '[#Actual_Capabilities capabilities].').
- Delete('Delete the session.'))
- resources.append(
- SessionResource('/session/:sessionId/timeouts').
- Post('''
- Configure the amount of time that a particular type of operation can execute \
- for before they are aborted and a |Timeout| error is returned to the \
- client.''').
- AddJsonParameter('type', '{string}',
- 'The type of operation to set the timeout for. Valid \
- values are: "script" for script timeouts, "implicit" for modifying the \
- implicit wait timeout and "page load" for setting a page load timeout.').
- AddJsonParameter('ms', '{number}',
- 'The amount of time, in milliseconds, that time-limited'
- ' commands are permitted to run.'))
- resources.append(
- SessionResource('/session/:sessionId/timeouts/async_script').
- Post('''Set the amount of time, in milliseconds, that asynchronous \
- scripts executed by `/session/:sessionId/execute_async` are permitted to run \
- before they are aborted and a |Timeout| error is returned to the client.''').
- AddJsonParameter('ms', '{number}',
- 'The amount of time, in milliseconds, that time-limited'
- ' commands are permitted to run.'))
- resources.append(
- SessionResource('/session/:sessionId/timeouts/implicit_wait').
- Post('''Set the amount of time the driver should wait when searching for \
- elements. When
- searching for a single element, the driver should poll the page until an \
- element is found or
- the timeout expires, whichever occurs first. When searching for multiple \
- elements, the driver
- should poll the page until at least one element is found or the timeout \
- expires, at which point
- it should return an empty list.
- If this command is never sent, the driver should default to an implicit wait of\
- 0ms.''').
- AddJsonParameter('ms', '{number}',
- 'The amount of time to wait, in milliseconds. This value'
- ' has a lower bound of 0.'))
- resources.append(
- SessionResource('/session/:sessionId/window_handle').
- Get('Retrieve the current window handle.').
- SetReturnType('{string}', 'The current window handle.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/window_handles').
- Get('Retrieve the list of all window handles available to the session.').
- SetReturnType('{Array.<string>}', 'A list of window handles.'))
- resources.append(
- SessionResource('/session/:sessionId/url').
- Get('Retrieve the URL of the current page.').
- SetReturnType('{string}', 'The current URL.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- Post('Navigate to a new URL.').
- AddJsonParameter('url', '{string}', 'The URL to navigate to.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/forward').
- Post('Navigate forwards in the browser history, if possible.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/back').
- Post('Navigate backwards in the browser history, if possible.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/refresh').
- Post('Refresh the current page.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/execute').
- Post('''
- Inject a snippet of !JavaScript into the page for execution in the context of \
- the currently selected frame. The executed script is assumed to be \
- synchronous and the result of evaluating the script is returned to the client.
- The `script` argument defines the script to execute in the form of a \
- function body. The value returned by that function will be returned to the \
- client. The function will be invoked with the provided `args` array and the \
- values may be accessed via the `arguments` object in the order specified.
- Arguments may be any JSON-primitive, array, or JSON object. JSON objects that \
- define a [#WebElement_JSON_Object WebElement reference] will be converted to \
- the corresponding DOM element. Likewise, any !WebElements in the script result \
- will be returned to the client as [#WebElement_JSON_Object WebElement \
- JSON objects].''').
- AddJsonParameter('script', '{string}', 'The script to execute.').
- AddJsonParameter('args', '{Array.<*>}', 'The script arguments.').
- AddError('JavaScriptError', 'If the script throws an Error.').
- AddError('StaleElementReference',
- 'If one of the script arguments is a !WebElement that is not '
- 'attached to the page\'s DOM.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- SetReturnType('{*}', 'The script result.'))
- resources.append(
- SessionResource('/session/:sessionId/execute_async').
- Post('''
- Inject a snippet of !JavaScript into the page for execution in the context of \
- the currently selected frame. The executed script is assumed to be \
- asynchronous and must signal that is done by invoking the provided callback, \
- which is always provided as the final argument to the function. The value \
- to this callback will be returned to the client.
- Asynchronous script commands may not span page loads. If an `unload` event is \
- fired while waiting for a script result, an error should be returned to the \
- client.
- The `script` argument defines the script to execute in teh form of a function \
- body. The function will be invoked with the provided `args` array and the \
- values may be accessed via the `arguments` object in the order specified. The \
- final argument will always be a callback function that must be invoked to \
- signal that the script has finished.
- Arguments may be any JSON-primitive, array, or JSON object. JSON objects that \
- define a [#WebElement_JSON_Object WebElement reference] will be converted to \
- the corresponding DOM element. Likewise, any !WebElements in the script result \
- will be returned to the client as [#WebElement_JSON_Object WebElement \
- JSON objects].''').
- AddJsonParameter('script', '{string}', 'The script to execute.').
- AddJsonParameter('args', '{Array.<*>}', 'The script arguments.').
- AddError('JavaScriptError',
- 'If the script throws an Error or if an `unload` event is '
- 'fired while waiting for the script to finish.').
- AddError('StaleElementReference',
- 'If one of the script arguments is a !WebElement that is not '
- 'attached to the page\'s DOM.').
- AddError('Timeout',
- 'If the script callback is not invoked before the timout '
- 'expires. Timeouts are controlled by the '
- '`/session/:sessionId/timeout/async_script` command.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- SetReturnType('{*}', 'The script result.'))
- resources.append(
- SessionResource('/session/:sessionId/screenshot').
- Get('Take a screenshot of the current page.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- SetReturnType('{string}', 'The screenshot as a base64 encoded PNG.'))
- resources.append(
- SessionResource('/session/:sessionId/ime/available_engines').
- Get('List all available engines on the machine. To use an engine, it has to be present in this list.').
- AddError('ImeNotAvailableException', 'If the host does not support IME').
- SetReturnType('{Array.<string>}', 'A list of available engines'))
- resources.append(
- SessionResource('/session/:sessionId/ime/active_engine').
- Get('Get the name of the active IME engine. The name string is platform specific.').
- AddError('ImeNotAvailableException', 'If the host does not support IME').
- SetReturnType('{string}', 'The name of the active IME engine.'))
- resources.append(
- SessionResource('/session/:sessionId/ime/activated').
- Get('Indicates whether IME input is active at the moment (not if it\'s available.').
- AddError('ImeNotAvailableException', 'If the host does not support IME').
- SetReturnType('{boolean}',
- 'true if IME input is available and currently active, false otherwise'))
- resources.append(
- SessionResource('/session/:sessionId/ime/deactivate').
- Post('De-activates the currently-active IME engine.').
- AddError('ImeNotAvailableException', 'If the host does not support IME'))
- resources.append(
- SessionResource('/session/:sessionId/ime/activate').
- Post('''Make an engines that is available (appears on the list
- returned by getAvailableEngines) active. After this call, the engine will
- be added to the list of engines loaded in the IME daemon and the input sent
- using sendKeys will be converted by the active engine.
- Note that this is a platform-independent method of activating IME
- (the platform-specific way being using keyboard shortcuts''').
- AddJsonParameter('engine', '{string}',
- 'Name of the engine to activate.').
- AddError('ImeActivationFailedException',
- 'If the engine is not available or if the activation fails for other reasons.').
- AddError('ImeNotAvailableException', 'If the host does not support IME'))
- resources.append(
- SessionResource('/session/:sessionId/frame').
- Post('''Change focus to another frame on the page. If the frame `id` is \
- `null`, the server
- should switch to the page's default content.''').
- AddJsonParameter('id', '{string|number|null|WebElement JSON Object}',
- 'Identifier for the frame to change focus to.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- AddError('NoSuchFrame', 'If the frame specified by `id` cannot be found.'))
- resources.append(
- SessionResource('/session/:sessionId/window').
- Post('''Change focus to another window. The window to change focus to \
- may be specified by its
- server assigned window handle, or by the value of its `name` attribute.''').
- AddJsonParameter('name', '{string}', 'The window to change focus to.').
- AddError('NoSuchWindow', 'If the window specified by `name` cannot be found.').
- Delete('''Close the current window.''').
- AddError('NoSuchWindow', 'If the currently selected window is already closed'))
- resources.append(
- SessionResource('/session/:sessionId/window/:windowHandle/size').
- Post('''Change the size of the specified window. If the :windowHandle URL \
- parameter is "current", the currently active window will be resized.''').
- AddJsonParameter('width', '{number}', 'The new window width.').
- AddJsonParameter('height', '{number}', 'The new window height.').
- Get('''Get the size of the specified window. If the :windowHandle URL \
- parameter is "current", the size of the currently active window will be returned.''').
- SetReturnType('{width: number, height: number}', 'The size of the window.').
- AddError('NoSuchWindow', 'If the specified window cannot be found.'))
- resources.append(
- SessionResource('/session/:sessionId/window/:windowHandle/position').
- Post('''Change the position of the specified window. If the :windowHandle URL \
- parameter is "current", the currently active window will be moved.''').
- AddJsonParameter('x', '{number}', 'The X coordinate to position the window at, \
- relative to the upper left corner of the screen.').
- AddJsonParameter('y', '{number}', 'The Y coordinate to position the window at, \
- relative to the upper left corner of the screen.') .
- AddError('NoSuchWindow', 'If the specified window cannot be found.').
- Get('''Get the position of the specified window. If the :windowHandle URL \
- parameter is "current", the position of the currently active window will be returned.''').
- SetReturnType('{x: number, y: number}', 'The X and Y coordinates for the window, \
- relative to the upper left corner of the screen.').
- AddError('NoSuchWindow', 'If the specified window cannot be found.'))
-
- resources.append(
- SessionResource('/session/:sessionId/window/:windowHandle/maximize').
- Post('''Maximize the specified window if not already maximized. If the \
- :windowHandle URL parameter is "current", the currently active window will be \
- maximized.''').
- AddError('NoSuchWindow', 'If the specified window cannot be found.'))
- resources.append(
- SessionResource('/session/:sessionId/cookie').
- Get('Retrieve all cookies visible to the current page.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- SetReturnType('{Array.<object>}', 'A list of [#Cookie_JSON_Object cookies].').
- Post('''Set a cookie. If the [#Cookie_JSON_Object cookie] path is not \
- specified, it should be set to `"/"`. Likewise, if the domain is omitted, it \
- should default to the current page's domain.''').
- AddJsonParameter('cookie', '{object}',
- 'A [#Cookie_JSON_Object JSON object] defining the '
- 'cookie to add.').
- Delete('''Delete all cookies visible to the current page.''').
- AddError('InvalidCookieDomain',
- 'If the cookie\'s `domain` is not visible from the current page.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.').
- AddError('UnableToSetCookie',
- 'If attempting to set a cookie on a page that does not support '
- 'cookies (e.g. pages with mime-type `text/plain`).'))
- resources.append(
- SessionResource('/session/:sessionId/cookie/:name').
- Delete('''Delete the cookie with the given name. This command should be \
- a no-op if there is no
- such cookie visible to the current page.''').
- AddUrlParameter(':name', 'The name of the cookie to delete.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/source').
- Get('Get the current page source.').
- SetReturnType('{string}', 'The current page source.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/title').
- Get('Get the current page title.').
- SetReturnType('{string}', 'The current page title.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/element').
- Post('''Search for an element on the page, starting from the document \
- root. The located element will be returned as a WebElement JSON object. \
- The table below lists the locator strategies that each server should support. \
- Each locator must return the first matching element located in the DOM.
- || *Strategy* || *Description* ||
- || class name || Returns an element whose class name contains the search \
- value; compound class names are not permitted. ||
- || css selector || Returns an element matching a CSS selector. ||
- || id || Returns an element whose ID attribute matches the search value. ||
- || name || Returns an element whose NAME attribute matches the search value. ||
- || link text || Returns an anchor element whose visible text matches the \
- search value. ||
- || partial link text || Returns an anchor element whose visible text \
- partially matches the search value. ||
- || tag name || Returns an element whose tag name matches the search value. ||
- || xpath || Returns an element matching an XPath expression. ||
- ''').
- AddJsonParameter('using', '{string}', 'The locator strategy to use.').
- AddJsonParameter('value', '{string}', 'The The search target.').
- SetReturnType('{ELEMENT:string}',
- 'A WebElement JSON object for the located element.').
- AddError('XPathLookupError', 'If using XPath and the input expression is invalid.').
- AddError('NoSuchElement', 'If the element cannot be found.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/elements').
- Post('''Search for multiple elements on the page, starting from the \
- document root. The located elements will be returned as a WebElement JSON \
- objects. The table below lists the locator strategies that each server should \
- support. Elements should be returned in the order located in the DOM.
- || *Strategy* || *Description* ||
- || class name || Returns all elements whose class name contains the search \
- value; compound class names are not permitted. ||
- || css selector || Returns all elements matching a CSS selector. ||
- || id || Returns all elements whose ID attribute matches the search value. ||
- || name || Returns all elements whose NAME attribute matches the search value. ||
- || link text || Returns all anchor elements whose visible text matches the \
- search value. ||
- || partial link text || Returns all anchor elements whose visible text \
- partially matches the search value. ||
- || tag name || Returns all elements whose tag name matches the search value. ||
- || xpath || Returns all elements matching an XPath expression. ||
- ''').
- AddJsonParameter('using', '{string}', 'The locator strategy to use.').
- AddJsonParameter('value', '{string}', 'The The search target.').
- SetReturnType('{Array.<{ELEMENT:string}>}',
- 'A list of WebElement JSON objects for the located elements.').
- AddError('XPathLookupError', 'If using XPath and the input expression is invalid.') .
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/element/active').
- Post('Get the element on the page that currently has focus. The element will be returned as '
- 'a WebElement JSON object.').
- SetReturnType('{ELEMENT:string}', 'A WebElement JSON object for the active element.') .
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id').
- Get('''Describe the identified element.
- *Note:* This command is reserved for future use; its return type is currently \
- undefined.''').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/element').
- Post('''Search for an element on the page, starting from the identified \
- element. The located element will be returned as a WebElement JSON object. \
- The table below lists the locator strategies that each server should support. \
- Each locator must return the first matching element located in the DOM.
- || *Strategy* || *Description* ||
- || class name || Returns an element whose class name contains the search \
- value; compound class names are not permitted. ||
- || css selector || Returns an element matching a CSS selector. ||
- || id || Returns an element whose ID attribute matches the search value. ||
- || name || Returns an element whose NAME attribute matches the search value. ||
- || link text || Returns an anchor element whose visible text matches the \
- search value. ||
- || partial link text || Returns an anchor element whose visible text \
- partially matches the search value. ||
- || tag name || Returns an element whose tag name matches the search value. ||
- || xpath || Returns an element matching an XPath expression. The provided \
- XPath expression must be applied to the server "as is"; if the expression is \
- not relative to the element root, the server should not modify it. \
- Consequently, an XPath query may return elements not contained in the root \
- element's subtree. ||
- ''').
- AddJsonParameter('using', '{string}', 'The locator strategy to use.').
- AddJsonParameter('value', '{string}', 'The The search target.').
- SetReturnType('{ELEMENT:string}',
- 'A WebElement JSON object for the located element.').
- AddError('NoSuchElement', 'If the element cannot be found.').
- AddError('XPathLookupError', 'If using XPath and the input expression is invalid.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/elements').
- Post('''Search for multiple elements on the page, starting from the \
- identified element. The located elements will be returned as a WebElement \
- JSON objects. The table below lists the locator strategies that each server \
- should support. Elements should be returned in the order located in the DOM.
- || *Strategy* || *Description* ||
- || class name || Returns all elements whose class name contains the search \
- value; compound class names are not permitted. ||
- || css selector || Returns all elements matching a CSS selector. ||
- || id || Returns all elements whose ID attribute matches the search value. ||
- || name || Returns all elements whose NAME attribute matches the search value. ||
- || link text || Returns all anchor elements whose visible text matches the \
- search value. ||
- || partial link text || Returns all anchor elements whose visible text \
- partially matches the search value. ||
- || tag name || Returns all elements whose tag name matches the search value. ||
- || xpath || Returns all elements matching an XPath expression. The provided \
- XPath expression must be applied to the server "as is"; if the expression is \
- not relative to the element root, the server should not modify it. \
- Consequently, an XPath query may return elements not contained in the root \
- element's subtree. ||
- ''').
- AddJsonParameter('using', '{string}', 'The locator strategy to use.').
- AddJsonParameter('value', '{string}', 'The The search target.').
- SetReturnType('{Array.<{ELEMENT:string}>}',
- 'A list of WebElement JSON objects for the located elements.').
- AddError('XPathLookupError', 'If using XPath and the input expression is invalid.') .
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/click').
- Post('Click on an element.').
- RequiresVisibility().
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/submit').
- Post('Submit a `FORM` element. The submit command may also be applied to any element that is '
- 'a descendant of a `FORM` element.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/text').
- Get('Returns the visible text for the element.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/value').
- Post('''Send a sequence of key strokes to an element.
- Any UTF-8 character may be specified, however, if the server does not support \
- native key events, it should simulate key strokes for a standard US keyboard \
- layout. The Unicode [http://unicode.org/faq/casemap_charprop.html#8 Private Use\
- Area] code points, 0xE000-0xF8FF, are used to represent pressable, non-text \
- keys (see table below).
- <table cellspacing=5 cellpadding=5>
- <tbody><tr><td valign=top>
- || *Key* || *Code* ||
- || NULL || U+E000 ||
- || Cancel || U+E001 ||
- || Help || U+E002 ||
- || Back space || U+E003 ||
- || Tab || U+E004 ||
- || Clear || U+E005 ||
- || Return^1^ || U+E006 ||
- || Enter^1^ || U+E007 ||
- || Shift || U+E008 ||
- || Control || U+E009 ||
- || Alt || U+E00A ||
- || Pause || U+E00B ||
- || Escape || U+E00C ||
- </td><td valign=top>
- || *Key* || *Code* ||
- || Space || U+E00D ||
- || Pageup || U+E00E ||
- || Pagedown || U+E00F ||
- || End || U+E010 ||
- || Home || U+E011 ||
- || Left arrow || U+E012 ||
- || Up arrow || U+E013 ||
- || Right arrow || U+E014 ||
- || Down arrow || U+E015 ||
- || Insert || U+E016 ||
- || Delete || U+E017 ||
- || Semicolon || U+E018 ||
- || Equals || U+E019 ||
- </td><td valign=top>
- || *Key* || *Code* ||
- || Numpad 0 || U+E01A ||
- || Numpad 1 || U+E01B ||
- || Numpad 2 || U+E01C ||
- || Numpad 3 || U+E01D ||
- || Numpad 4 || U+E01E ||
- || Numpad 5 || U+E01F ||
- || Numpad 6 || U+E020 ||
- || Numpad 7 || U+E021 ||
- || Numpad 8 || U+E022 ||
- || Numpad 9 || U+E023 ||
- </td><td valign=top>
- || *Key* || *Code* ||
- || Multiply || U+E024 ||
- || Add || U+E025 ||
- || Separator || U+E026 ||
- || Subtract || U+E027 ||
- || Decimal || U+E028 ||
- || Divide || U+E029 ||
- </td><td valign=top>
- || *Key* || *Code* ||
- || F1 || U+E031 ||
- || F2 || U+E032 ||
- || F3 || U+E033 ||
- || F4 || U+E034 ||
- || F5 || U+E035 ||
- || F6 || U+E036 ||
- || F7 || U+E037 ||
- || F8 || U+E038 ||
- || F9 || U+E039 ||
- || F10 || U+E03A ||
- || F11 || U+E03B ||
- || F12 || U+E03C ||
- || Command/Meta || U+E03D ||
- </td></tr>
- <tr><td colspan=5>^1^ The return key is _not the same_ as the \
- [http://en.wikipedia.org/wiki/Enter_key enter key].</td></tr></tbody></table>
- The server must process the key sequence as follows:
- * Each key that appears on the keyboard without requiring modifiers are sent \
- as a keydown followed by a key up.
- * If the server does not support native events and must simulate key strokes \
- with !JavaScript, it must generate keydown, keypress, and keyup events, in that\
- order. The keypress event should only be fired when the corresponding key is \
- for a printable character.
- * If a key requires a modifier key (e.g. "!" on a standard US keyboard), the \
- sequence is: <var>modifier</var> down, <var>key</var> down, <var>key</var> up, \
- <var>modifier</var> up, where <var>key</var> is the ideal unmodified key value \
- (using the previous example, a "1").
- * Modifier keys (Ctrl, Shift, Alt, and Command/Meta) are assumed to be \
- "sticky"; each modifier should be held down (e.g. only a keydown event) until \
- either the modifier is encountered again in the sequence, or the `NULL` \
- (U+E000) key is encountered.
- * Each key sequence is terminated with an implicit `NULL` key. Subsequently, \
- all depressed modifier keys must be released (with corresponding keyup events) \
- at the end of the sequence.
- ''').
- RequiresVisibility().
- AddJsonParameter('value', '{Array.<string>}',
- 'The sequence of keys to type. An array must be provided. '
- 'The server should flatten the array items to a single '
- 'string to be typed.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- SessionResource('/session/:sessionId/keys').
- Post('Send a sequence of key strokes to the active element. This '
- 'command is similar to the '
- '[JsonWireProtocol#/session/:sessionId/element/:id/value'
- ' send keys] command in every aspect except the implicit '
- 'termination: The modifiers are *not* released at the end of the '
- 'call. Rather, the state of the modifier keys is kept between '
- 'calls, so mouse interactions can be performed while modifier '
- 'keys are depressed.').
- AddJsonParameter('value', '{Array.<string>}',
- 'The keys sequence to be sent. The sequence is defined '
- 'in the'
- '[JsonWireProtocol#/session/:sessionId/element/:id/value'
- ' send keys] command.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/name').
- Get('Query for an element\'s tag name.').
- SetReturnType('{string}', 'The element\'s tag name, as a lowercase string.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/clear').
- Post('Clear a `TEXTAREA` or `text INPUT` element\'s value.').
- RequiresVisibility().
- RequiresEnabledState().
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/selected').
- Get('Determine if an `OPTION` element, or an `INPUT` element of type `checkbox` or '
- '`radiobutton` is currently selected.').
- SetReturnType('{boolean}', 'Whether the element is selected.') .
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/enabled').
- Get('Determine if an element is currently enabled.').
- SetReturnType('{boolean}', 'Whether the element is enabled.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- ElementResource('/session/:sessionId/element/:id/attribute/:name').
- Get('Get the value of an element\'s attribute.').
- SetReturnType('{string|null}',
- 'The value of the attribute, or null if it is not set on the element.').
- AddError('NoSuchWindow',
- 'If the currently selected window has been closed.'))
- resources.append(
- …
Large files files are truncated, but you can click here to view the full file