Skip to content

Commit

Permalink
[py] Fix input pausing in ActionChains and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
lmtierney committed Aug 22, 2018
1 parent 3b5e720 commit 69e57f1
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 52 deletions.
66 changes: 26 additions & 40 deletions py/selenium/webdriver/common/action_chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ def click(self, on_element=None):
- 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
Expand All @@ -117,14 +117,12 @@ def click_and_hold(self, on_element=None):
- 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
Expand All @@ -137,12 +135,13 @@ def context_click(self, on_element=None):
- 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
Expand All @@ -155,13 +154,13 @@ def double_click(self, on_element=None):
- 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
Expand All @@ -175,15 +174,8 @@ def drag_and_drop(self, source, target):
- 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):
Expand All @@ -196,16 +188,9 @@ def drag_and_drop_by_offset(self, source, xoffset, yoffset):
- 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_by(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):
Expand Down Expand Up @@ -331,7 +316,7 @@ def release(self, on_element=None):
If None, releases on current mouse position.
"""
if on_element:
self.move_to_element(on_element)
self.move_to_element(on_element)
if self._driver.w3c:
self.w3c_actions.pointer_action.release()
self.w3c_actions.key_action.pause()
Expand All @@ -347,11 +332,14 @@ def send_keys(self, *keys_to_send):
- 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):
Expand All @@ -363,10 +351,8 @@ def send_keys_to_element(self, element, *keys_to_send):
- 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.
Expand Down
22 changes: 10 additions & 12 deletions py/selenium/webdriver/common/actions/key_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
22 changes: 22 additions & 0 deletions py/test/selenium/webdriver/common/interactions_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,28 @@ def testSendingKeysToActiveElementWithModifier(driver, pages):
assert "ABC" == e.get_attribute('value')


def testSendingKeysToElement(driver, pages):
pages.load("formPage.html")
e = driver.find_element_by_id("working")

ActionChains(driver).send_keys_to_element(e, 'abc').perform()

assert "abc" == e.get_attribute('value')


def testCanSendKeysBetweenClicks(driver, pages):
"""
For W3C, ensures that the correct number of pauses are given to the other
input device.
"""
pages.load('javascriptPage.html')
keyup = driver.find_element_by_id("keyUp")
keydown = driver.find_element_by_id("keyDown")
ActionChains(driver).click(keyup).send_keys('foobar').click(keydown).perform()

assert 'foobar' == keyup.get_attribute('value')


def test_can_reset_interactions(driver, pages):
ActionChains(driver).reset_actions()

Expand Down

0 comments on commit 69e57f1

Please sign in to comment.