Commit 23be9c48 authored by Sascha Girrulat's avatar Sascha Girrulat

New upstream version 3.14.1+dfsg1

parent fcf0bf42
Selenium 3.14.1
* Fix ability to set timeout for urllib3 (#6286)
* get_cookie uses w3c endpoint when compliant
* Remove body from GET requests (#6250)
* Fix actions pause for fraction of a second (#6300)
* Fixed input pausing for some actions methods
* Capabilities can be set on Options classes
* WebElement rect method is now forward compatible for OSS endpoints (#6355)
* Deprecation warnings now have a stacklevel of 2
* keep_alive can now be set on Webdriver init (#6316)
* isDisplayed atom is now used for all w3c compliant browser, fixing issue with Safari 12
Selenium 3.14.0
* Fix doc of URL-related ExpectedCondition (#6236)
* Added ExpectedCondition invisibility_of_element
* Swap out httplib for urllib3
* Be consistent with webdriver init kwarg service_log_path (#5725)
Selenium 3.13.0
* Add executing Chrome devtools command (#5989)
* fix incorrect w3c action encoding in python client (#6014)
* Implement context manager for WebDriver
* Stop sending "windowHandle" param in maximize_window command for w3c
Selenium 3.12.0
* Add desired_capabilities keyword to IE and Firefox drivers for driver consitency
* Fix bug with creating Safari webdriver instance (#5578)
* Add support for Safari extension command
* Deprecate Options `set_headless` methods in favor of property setter
* Only set --disable-gpu for Chrome headless when on Windows
* Add selenium User-Agent header (#5696)
* Remote webdriver can now be started when passing options
* All Options.to_capabilities now start with default DesiredCapabilities
* Improve the error message that is raised when safaridriver cannot be found (#5739)
* IeOptions class is now imported to selenium.webdriver
* Remove the beta `authenticate` methods from `Alert`
Selenium 3.11.0
No changes just keeping python version in step with the rest of the project.
Selenium 3.10.0
* make tests to check clicking on disabled element work for w3c compliant drivers (#5561)
* add docstring for InvalidElementStateException. Fixes #5520
* Deleting unused imports
* Making python specification in IDEA project more generic
* It should be possible to use a custom safaridriver executable to run Selenium's test suite.
Selenium 3.9.0
* Add docstrings to WebElement find methods (#5384)
* Additional data in unexpected alert error is now handled for w3c drivers (#5416)
* Allow service_args to be passed into Firefox WebDriver (#5421)
* Fix bug introduced with response logging in 3.8.1 (#5362)
Selenium 3.8.1
* Fix bug when creating an Opera driver (#5266)
* Stop sending sessionId in w3c payload. (#4620)
* Fix issue with w3c actions releasing on element (#5180)
* A more descriptive log message is displayed if the port cannot be connected (#2913)
* Initialize Alert object by calling alert.text (#1863)
* PhantomJS is now deprecated, please use either Chrome or Firefox in headless mode
* Legacy Firefox driver: ensuring copy of profile dir, its 'extensions' subdir and 'user.js' file are writable. (#1466)
Selenium 3.8.0
* Firefox options can now be imported from selenium.webdriver as FirefoxOptions (#5120)
......
This diff is collapsed.
Metadata-Version: 1.1
Name: selenium
Version: 3.8.0
Version: 3.14.1
Summary: Python bindings for Selenium
Home-page: https://github.com/SeleniumHQ/selenium/
Author: UNKNOWN
......@@ -25,12 +25,12 @@ Description: ======================
+-----------+--------------------------------------------------------------------------------------+
| **Dev**: | https://github.com/SeleniumHQ/Selenium |
+-----------+--------------------------------------------------------------------------------------+
| **PyPI**: | https://pypi.python.org/pypi/selenium |
| **PyPI**: | https://pypi.org/project/selenium/ |
+-----------+--------------------------------------------------------------------------------------+
| **IRC**: | **#selenium** channel on freenode |
+-----------+--------------------------------------------------------------------------------------+
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer, PhantomJS), as well as the Remote protocol.
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer), as well as the Remote protocol.
Supported Python Versions
=========================
......@@ -44,7 +44,7 @@ Description: ======================
pip install -U selenium
Alternately, you can download the source distribution from `PyPI <http://pypi.python.org/pypi/selenium>`_ (e.g. selenium-3.8.0.tar.gz), unarchive it, and run::
Alternately, you can download the source distribution from `PyPI <https://pypi.org/project/selenium/#files>`_ (e.g. selenium-3.14.0.tar.gz), unarchive it, and run::
python setup.py install
......@@ -109,7 +109,7 @@ Description: ======================
Example 2:
==========
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example uisng Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example using Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
.. code-block:: python
......@@ -136,11 +136,11 @@ Description: ======================
However, to use Selenium Webdriver Remote or the legacy Selenium API (Selenium-RC), you need to also run the Selenium server. The server requires a Java Runtime Environment (JRE).
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.8/selenium-server-standalone-3.8.0.jar
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.14/selenium-server-standalone-3.14.0.jar
Run the server from the command line::
java -jar selenium-server-standalone-3.8.0.jar
java -jar selenium-server-standalone-3.14.0.jar
Then run your Python client scripts.
......
......@@ -16,12 +16,12 @@ The `selenium` package is used to automate web browser interaction from Python.
+-----------+--------------------------------------------------------------------------------------+
| **Dev**: | https://github.com/SeleniumHQ/Selenium |
+-----------+--------------------------------------------------------------------------------------+
| **PyPI**: | https://pypi.python.org/pypi/selenium |
| **PyPI**: | https://pypi.org/project/selenium/ |
+-----------+--------------------------------------------------------------------------------------+
| **IRC**: | **#selenium** channel on freenode |
+-----------+--------------------------------------------------------------------------------------+
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer, PhantomJS), as well as the Remote protocol.
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer), as well as the Remote protocol.
Supported Python Versions
=========================
......@@ -35,7 +35,7 @@ If you have `pip <https://pip.pypa.io/>`_ on your system, you can simply install
pip install -U selenium
Alternately, you can download the source distribution from `PyPI <http://pypi.python.org/pypi/selenium>`_ (e.g. selenium-3.8.0.tar.gz), unarchive it, and run::
Alternately, you can download the source distribution from `PyPI <https://pypi.org/project/selenium/#files>`_ (e.g. selenium-3.14.0.tar.gz), unarchive it, and run::
python setup.py install
......@@ -100,7 +100,7 @@ Example 1:
Example 2:
==========
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example uisng Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example using Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
.. code-block:: python
......@@ -127,11 +127,11 @@ For normal WebDriver scripts (non-Remote), the Java server is not needed.
However, to use Selenium Webdriver Remote or the legacy Selenium API (Selenium-RC), you need to also run the Selenium server. The server requires a Java Runtime Environment (JRE).
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.8/selenium-server-standalone-3.8.0.jar
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.14/selenium-server-standalone-3.14.0.jar
Run the server from the command line::
java -jar selenium-server-standalone-3.8.0.jar
java -jar selenium-server-standalone-3.14.0.jar
Then run your Python client scripts.
......
Metadata-Version: 1.1
Name: selenium
Version: 3.8.0
Version: 3.14.1
Summary: Python bindings for Selenium
Home-page: https://github.com/SeleniumHQ/selenium/
Author: UNKNOWN
......@@ -25,12 +25,12 @@ Description: ======================
+-----------+--------------------------------------------------------------------------------------+
| **Dev**: | https://github.com/SeleniumHQ/Selenium |
+-----------+--------------------------------------------------------------------------------------+
| **PyPI**: | https://pypi.python.org/pypi/selenium |
| **PyPI**: | https://pypi.org/project/selenium/ |
+-----------+--------------------------------------------------------------------------------------+
| **IRC**: | **#selenium** channel on freenode |
+-----------+--------------------------------------------------------------------------------------+
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer, PhantomJS), as well as the Remote protocol.
Several browsers/drivers are supported (Firefox, Chrome, Internet Explorer), as well as the Remote protocol.
Supported Python Versions
=========================
......@@ -44,7 +44,7 @@ Description: ======================
pip install -U selenium
Alternately, you can download the source distribution from `PyPI <http://pypi.python.org/pypi/selenium>`_ (e.g. selenium-3.8.0.tar.gz), unarchive it, and run::
Alternately, you can download the source distribution from `PyPI <https://pypi.org/project/selenium/#files>`_ (e.g. selenium-3.14.0.tar.gz), unarchive it, and run::
python setup.py install
......@@ -109,7 +109,7 @@ Description: ======================
Example 2:
==========
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example uisng Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
Selenium WebDriver is often used as a basis for testing web applications. Here is a simple example using Python's standard `unittest <http://docs.python.org/3/library/unittest.html>`_ library:
.. code-block:: python
......@@ -136,11 +136,11 @@ Description: ======================
However, to use Selenium Webdriver Remote or the legacy Selenium API (Selenium-RC), you need to also run the Selenium server. The server requires a Java Runtime Environment (JRE).
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.8/selenium-server-standalone-3.8.0.jar
Download the server separately, from: http://selenium-release.storage.googleapis.com/3.14/selenium-server-standalone-3.14.0.jar
Run the server from the command line::
java -jar selenium-server-standalone-3.8.0.jar
java -jar selenium-server-standalone-3.14.0.jar
Then run your Python client scripts.
......
CHANGES
LICENSE
MANIFEST.in
README.rst
setup.cfg
......@@ -8,6 +9,7 @@ selenium.egg-info/PKG-INFO
selenium.egg-info/SOURCES.txt
selenium.egg-info/dependency_links.txt
selenium.egg-info/not-zip-safe
selenium.egg-info/requires.txt
selenium.egg-info/top_level.txt
selenium/common/__init__.py
selenium/common/exceptions.py
......@@ -82,6 +84,8 @@ selenium/webdriver/remote/utils.py
selenium/webdriver/remote/webdriver.py
selenium/webdriver/remote/webelement.py
selenium/webdriver/safari/__init__.py
selenium/webdriver/safari/permissions.py
selenium/webdriver/safari/remote_connection.py
selenium/webdriver/safari/service.py
selenium/webdriver/safari/webdriver.py
selenium/webdriver/support/__init__.py
......
......@@ -16,4 +16,4 @@
# under the License.
__version__ = "3.8.0"
__version__ = "3.14.1"
......@@ -124,6 +124,9 @@ class StaleElementReferenceException(WebDriverException):
class InvalidElementStateException(WebDriverException):
"""
Thrown when a command could not be completed because the element is in an invalid state.
This can be caused by attempting to clear an element that isn't both editable and resettable.
"""
pass
......
......@@ -21,6 +21,7 @@ from .firefox.options import Options as FirefoxOptions # noqa
from .chrome.webdriver import WebDriver as Chrome # noqa
from .chrome.options import Options as ChromeOptions # noqa
from .ie.webdriver import WebDriver as Ie # noqa
from .ie.options import Options as IeOptions # noqa
from .edge.webdriver import WebDriver as Edge # noqa
from .opera.webdriver import WebDriver as Opera # noqa
from .safari.webdriver import WebDriver as Safari # noqa
......@@ -35,4 +36,4 @@ from .common.action_chains import ActionChains # noqa
from .common.touch_actions import TouchActions # noqa
from .common.proxy import Proxy # noqa
__version__ = '3.8.0'
__version__ = '3.14.1'
......@@ -17,6 +17,8 @@
import base64
import os
import platform
import warnings
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
......@@ -31,6 +33,7 @@ class Options(object):
self._extensions = []
self._experimental_options = {}
self._debugger_address = None
self._caps = DesiredCapabilities.CHROME.copy()
@property
def binary_location(self):
......@@ -49,6 +52,14 @@ class Options(object):
"""
self._binary_location = value
@property
def capabilities(self):
return self._caps
def set_capability(self, name, value):
"""Sets a capability."""
self._caps[name] = value
@property
def debugger_address(self):
"""
......@@ -158,27 +169,35 @@ class Options(object):
"""
return '--headless' in self._arguments
def set_headless(self, headless=True):
@headless.setter
def headless(self, value):
"""
Sets the headless argument
Args:
headless: boolean value indicating to set the headless option
value: boolean value indicating to set the headless option
"""
args = {'--headless', '--disable-gpu'}
if headless:
args = {'--headless'}
if platform.system().lower() == 'windows':
args.add('--disable-gpu')
if value is True:
self._arguments.extend(args)
else:
self._arguments = list(set(self._arguments) - args)
def set_headless(self, headless=True):
""" Deprecated, options.headless = True """
warnings.warn('use setter for headless property instead of set_headless',
DeprecationWarning, stacklevel=2)
self.headless = headless
def to_capabilities(self):
"""
Creates a capabilities with all the options that have been set and
returns a dictionary with everything
"""
chrome = DesiredCapabilities.CHROME.copy()
caps = self._caps
chrome_options = self.experimental_options.copy()
chrome_options["extensions"] = self.extensions
if self.binary_location:
......@@ -187,6 +206,6 @@ class Options(object):
if self.debugger_address:
chrome_options["debuggerAddress"] = self.debugger_address
chrome[self.KEY] = chrome_options
caps[self.KEY] = chrome_options
return chrome
return caps
......@@ -25,3 +25,4 @@ class ChromeRemoteConnection(RemoteConnection):
self._commands["launchApp"] = ('POST', '/session/$sessionId/chromium/launch_app')
self._commands["setNetworkConditions"] = ('POST', '/session/$sessionId/chromium/network_conditions')
self._commands["getNetworkConditions"] = ('GET', '/session/$sessionId/chromium/network_conditions')
self._commands['executeCdpCommand'] = ('POST', '/session/$sessionId/goog/cdp/execute')
......@@ -33,7 +33,7 @@ class WebDriver(RemoteWebDriver):
def __init__(self, executable_path="chromedriver", port=0,
options=None, service_args=None,
desired_capabilities=None, service_log_path=None,
chrome_options=None):
chrome_options=None, keep_alive=True):
"""
Creates a new instance of the chrome driver.
......@@ -42,12 +42,17 @@ class WebDriver(RemoteWebDriver):
:Args:
- executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH
- port - port you would like the service to run, if left as 0, a free port will be found.
- desired_capabilities: Dictionary object with non-browser specific
- options - this takes an instance of ChromeOptions
- service_args - List of args to pass to the driver service
- desired_capabilities - Dictionary object with non-browser specific
capabilities only, such as "proxy" or "loggingPref".
- options: this takes an instance of ChromeOptions
- service_log_path - Where to log information from the driver.
- chrome_options - Deprecated argument for options
- keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
"""
if chrome_options:
warnings.warn('use options instead of chrome_options', DeprecationWarning)
warnings.warn('use options instead of chrome_options',
DeprecationWarning, stacklevel=2)
options = chrome_options
if options is None:
......@@ -71,7 +76,8 @@ class WebDriver(RemoteWebDriver):
RemoteWebDriver.__init__(
self,
command_executor=ChromeRemoteConnection(
remote_server_addr=self.service.service_url),
remote_server_addr=self.service.service_url,
keep_alive=keep_alive),
desired_capabilities=desired_capabilities)
except Exception:
self.quit()
......@@ -115,6 +121,29 @@ class WebDriver(RemoteWebDriver):
'network_conditions': network_conditions
})
def execute_cdp_cmd(self, cmd, cmd_args):
"""
Execute Chrome Devtools Protocol command and get returned result
The command and command args should follow chrome devtools protocol domains/commands, refer to link
https://chromedevtools.github.io/devtools-protocol/
:Args:
- cmd: A str, command name
- cmd_args: A dict, command args. empty dict {} if there is no command args
:Usage:
driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': requestId})
:Returns:
A dict, empty dict {} if there is no result to return.
For example to getResponseBody:
{'base64Encoded': False, 'body': 'response body string'}
"""
return self.execute("executeCdpCommand", {'cmd': cmd, 'params': cmd_args})['value']
def quit(self):
"""
Closes the browser and shuts down the ChromeDriver executable
......
......@@ -84,12 +84,11 @@ class ActionChains(object):
def reset_actions(self):
"""
Clears actions that are already stored on the remote end.
Clears actions that are already stored locally and on the remote end
"""
if self._driver.w3c:
self._driver.execute(Command.W3C_CLEAR_ACTIONS)
else:
self._actions = []
self.w3c_actions.clear_actions()
self._actions = []
def click(self, on_element=None):
"""
......@@ -99,13 +98,13 @@ class ActionChains(object):
- on_element: The element to click.
If None, clicks on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.click(on_element)
self.w3c_actions.pointer_action.click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
else:
if on_element:
self.move_to_element(on_element)
self._actions.append(lambda: self._driver.execute(
Command.CLICK, {'button': 0}))
return self
......@@ -118,14 +117,12 @@ class ActionChains(object):
- on_element: The element to mouse down.
If None, clicks on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.click_and_hold(on_element)
self.w3c_actions.pointer_action.click_and_hold()
self.w3c_actions.key_action.pause()
if on_element:
self.w3c_actions.key_action.pause()
else:
if on_element:
self.move_to_element(on_element)
self._actions.append(lambda: self._driver.execute(
Command.MOUSE_DOWN, {}))
return self
......@@ -138,12 +135,13 @@ class ActionChains(object):
- on_element: The element to context-click.
If None, clicks on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.context_click(on_element)
self.w3c_actions.pointer_action.context_click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
else:
if on_element:
self.move_to_element(on_element)
self._actions.append(lambda: self._driver.execute(
Command.CLICK, {'button': 2}))
return self
......@@ -156,13 +154,13 @@ class ActionChains(object):
- on_element: The element to double-click.
If None, clicks on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.double_click(on_element)
self.w3c_actions.pointer_action.double_click()
for _ in range(4):
self.w3c_actions.key_action.pause()
else:
if on_element:
self.move_to_element(on_element)
self._actions.append(lambda: self._driver.execute(
Command.DOUBLE_CLICK, {}))
return self
......@@ -176,15 +174,8 @@ class ActionChains(object):
- source: The element to mouse down.
- target: The element to mouse up.
"""
if self._driver.w3c:
self.w3c_actions.pointer_action.click_and_hold(source) \
.move_to(target) \
.release()
for _ in range(3):
self.w3c_actions.key_action.pause()
else:
self.click_and_hold(source)
self.release(target)
self.click_and_hold(source)
self.release(target)
return self
def drag_and_drop_by_offset(self, source, xoffset, yoffset):
......@@ -197,16 +188,9 @@ class ActionChains(object):
- xoffset: X offset to move to.
- yoffset: Y offset to move to.
"""
if self._driver.w3c:
self.w3c_actions.pointer_action.click_and_hold(source) \
.move_to_location(xoffset, yoffset) \
.release()
for _ in range(3):
self.w3c_actions.key_action.pause()
else:
self.click_and_hold(source)
self.move_by_offset(xoffset, yoffset)
self.release()
self.click_and_hold(source)
self.move_by_offset(xoffset, yoffset)
self.release()
return self
def key_down(self, value, element=None):
......@@ -331,12 +315,12 @@ class ActionChains(object):
- on_element: The element to mouse up.
If None, releases on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.release()
self.w3c_actions.key_action.pause()
else:
if on_element:
self.move_to_element(on_element)
self._actions.append(lambda: self._driver.execute(Command.MOUSE_UP, {}))
return self
......@@ -348,11 +332,14 @@ class ActionChains(object):
- keys_to_send: The keys to send. Modifier keys constants can be found in the
'Keys' class.
"""
typing = keys_to_typing(keys_to_send)
if self._driver.w3c:
self.w3c_actions.key_action.send_keys(keys_to_send)
for key in typing:
self.key_down(key)
self.key_up(key)
else:
self._actions.append(lambda: self._driver.execute(
Command.SEND_KEYS_TO_ACTIVE_ELEMENT, {'value': keys_to_typing(keys_to_send)}))
Command.SEND_KEYS_TO_ACTIVE_ELEMENT, {'value': typing}))
return self
def send_keys_to_element(self, element, *keys_to_send):
......@@ -364,10 +351,8 @@ class ActionChains(object):
- keys_to_send: The keys to send. Modifier keys constants can be found in the
'Keys' class.
"""
if self._driver.w3c:
self.w3c_actions.key_action.send_keys(keys_to_send, element=element)
else:
self._actions.append(lambda: element.send_keys(*keys_to_send))
self.click(element)
self.send_keys(*keys_to_send)
return self
# Context manager so ActionChains can be used in a 'with .. as' statements.
......
......@@ -26,7 +26,7 @@ from .pointer_input import PointerInput
class ActionBuilder(object):
def __init__(self, driver, mouse=None, keyboard=None):
if mouse is None:
mouse = PointerInput(interaction.POINTER, "mouse")
mouse = PointerInput(interaction.POINTER_MOUSE, "mouse")
if keyboard is None:
keyboard = KeyInput(interaction.KEY)
self.devices = [mouse, keyboard]
......@@ -62,8 +62,8 @@ class ActionBuilder(object):
self._add_input(new_input)
return new_input
def add_pointer_input(self, type_, name):
new_input = PointerInput(type_, name)
def add_pointer_input(self, kind, name):
new_input = PointerInput(kind, name)
self._add_input(new_input)
return new_input
......@@ -76,6 +76,9 @@ class ActionBuilder(object):
self.driver.execute(Command.W3C_ACTIONS, enc)
def clear_actions(self):
"""
Clears actions that are already stored on the remote end
"""
self.driver.execute(Command.W3C_CLEAR_ACTIONS)
def _add_input(self, input):
......
......@@ -21,6 +21,12 @@ POINTER = "pointer"
NONE = "none"
SOURCE_TYPES = set([KEY, POINTER, NONE])
POINTER_MOUSE = "mouse"
POINTER_TOUCH = "touch"
POINTER_PEN = "pen"
POINTER_KINDS = set([POINTER_MOUSE, POINTER_TOUCH, POINTER_PEN])
class Interaction(object):
......@@ -38,6 +44,7 @@ class Pause(Interaction):
self.duration = duration
def encode(self):
output = {"type": self.PAUSE}
output["duration"] = self.duration * 1000
return output
return {
"type": self.PAUSE,
"duration": int(self.duration * 1000)
}
......@@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from .interaction import Interaction
from .interaction import Interaction, KEY
from .key_input import KeyInput
from ..utils import keys_to_typing
......@@ -23,30 +23,28 @@ class KeyActions(Interaction):
def __init__(self, source=None):
if source is None:
source = KeyInput()
source = KeyInput(KEY)
self.source = source
super(KeyActions, self).__init__(source)
def key_down(self, letter, element=None):
return self._key_action("create_key_down",
letter, element)
def key_down(self, letter):
return self._key_action("create_key_down", letter)
def key_up(self, letter, element=None):
return self._key_action("create_key_up",
letter, element)
def key_up(self, letter):
return self._key_action("create_key_up", letter)
def pause(self, duration=0):
return self._key_action("create_pause", duration)
def send_keys(self, text, element=None):
def send_keys(self, text):
if not isinstance(text, list):
text = keys_to_typing(text)
for letter in text:
self.key_down(letter, element)
self.key_up(letter, element)
self.key_down(letter)
self.key_up(letter)
return self
def _key_action(self, action, letter, element=None):
def _key_action(self, action, letter):
meth = getattr(self.source, action)
meth(letter)
return self
......@@ -27,7 +27,7 @@ class PointerActions(Interaction):
def __init__(self, source=None):
if source is None:
source = PointerInput(interaction.POINTER, "mouse")
source = PointerInput(interaction.POINTER_MOUSE, "mouse")
self.source = source
super(PointerActions, self).__init__(source)
......
......@@ -15,7 +15,9 @@
# specific language governing permissions and limitations
# under the License.
from .input_device import InputDevice
from .interaction import POINTER, POINTER_KINDS
from selenium.common.exceptions import InvalidArgumentException
from selenium.webdriver.remote.webelement import WebElement
......@@ -23,9 +25,12 @@ class PointerInput(InputDevice):
DEFAULT_MOVE_DURATION = 250
def __init__(self, type_, name):