Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[py] support wheel also to build sync actions #13619

Open
wants to merge 3 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 18 additions & 14 deletions py/selenium/webdriver/common/action_chains.py
Expand Up @@ -111,8 +111,7 @@ def click(self, on_element: WebElement | None = None) -> ActionChains:
self.move_to_element(on_element)

self.w3c_actions.pointer_action.click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer', 2)

return self

Expand All @@ -127,7 +126,7 @@ def click_and_hold(self, on_element: WebElement | None = None) -> ActionChains:
self.move_to_element(on_element)

self.w3c_actions.pointer_action.click_and_hold()
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer')

return self

Expand All @@ -142,8 +141,7 @@ def context_click(self, on_element: WebElement | None = None) -> ActionChains:
self.move_to_element(on_element)

self.w3c_actions.pointer_action.context_click()
self.w3c_actions.key_action.pause()
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer', 2)

return self

Expand All @@ -158,8 +156,7 @@ def double_click(self, on_element: WebElement | None = None) -> ActionChains:
self.move_to_element(on_element)

self.w3c_actions.pointer_action.double_click()
for _ in range(4):
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer', 4)

return self

Expand Down Expand Up @@ -206,7 +203,7 @@ def key_down(self, value: str, element: WebElement | None = None) -> ActionChain
self.click(element)

self.w3c_actions.key_action.key_down(value)
self.w3c_actions.pointer_action.pause()
self.w3c_actions.fill_pause_except('key')

return self

Expand All @@ -226,7 +223,7 @@ def key_up(self, value: str, element: WebElement | None = None) -> ActionChains:
self.click(element)

self.w3c_actions.key_action.key_up(value)
self.w3c_actions.pointer_action.pause()
self.w3c_actions.fill_pause_except('key')

return self

Expand All @@ -239,7 +236,7 @@ def move_by_offset(self, xoffset: int, yoffset: int) -> ActionChains:
"""

self.w3c_actions.pointer_action.move_by(xoffset, yoffset)
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer')

return self

Expand All @@ -251,7 +248,7 @@ def move_to_element(self, to_element: WebElement) -> ActionChains:
"""

self.w3c_actions.pointer_action.move_to(to_element)
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer')

return self

Expand All @@ -266,15 +263,16 @@ def move_to_element_with_offset(self, to_element: WebElement, xoffset: int, yoff
"""

self.w3c_actions.pointer_action.move_to(to_element, int(xoffset), int(yoffset))
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer')

return self

def pause(self, seconds: float | int) -> ActionChains:
"""Pause all inputs for the specified duration in seconds."""

self.w3c_actions.pointer_action.pause(seconds)
self.w3c_actions.key_action.pause(seconds)
self.w3c_actions.pointer_action.pause(seconds)
self.w3c_actions.wheel_action.pause(seconds)

return self

Expand All @@ -289,7 +287,7 @@ def release(self, on_element: WebElement | None = None) -> ActionChains:
self.move_to_element(on_element)

self.w3c_actions.pointer_action.release()
self.w3c_actions.key_action.pause()
self.w3c_actions.fill_pause_except('pointer')

return self

Expand Down Expand Up @@ -329,6 +327,8 @@ def scroll_to_element(self, element: WebElement) -> ActionChains:
"""

self.w3c_actions.wheel_action.scroll(origin=element)
self.w3c_actions.fill_pause_except('wheel')

return self

def scroll_by_amount(self, delta_x: int, delta_y: int) -> ActionChains:
Expand All @@ -341,6 +341,8 @@ def scroll_by_amount(self, delta_x: int, delta_y: int) -> ActionChains:
"""

self.w3c_actions.wheel_action.scroll(delta_x=delta_x, delta_y=delta_y)
self.w3c_actions.fill_pause_except('wheel')

return self

def scroll_from_origin(self, scroll_origin: ScrollOrigin, delta_x: int, delta_y: int) -> ActionChains:
Expand Down Expand Up @@ -369,6 +371,8 @@ def scroll_from_origin(self, scroll_origin: ScrollOrigin, delta_x: int, delta_y:
delta_x=delta_x,
delta_y=delta_y,
)
self.w3c_actions.fill_pause_except('wheel')

return self

# Context manager so ActionChains can be used in a 'with .. as' statements.
Expand Down
13 changes: 13 additions & 0 deletions py/selenium/webdriver/common/actions/action_builder.py
Expand Up @@ -15,7 +15,9 @@
# specific language governing permissions and limitations
# under the License.

from typing import Dict
from typing import List
from typing import Literal
from typing import Optional
from typing import Union

Expand Down Expand Up @@ -85,6 +87,17 @@ def add_wheel_input(self, name: str) -> WheelInput:
new_input = WheelInput(name)
self._add_input(new_input)
return new_input

def fill_pause_except(self, type: Literal["key", "pointer", "wheel"], ticks: int = 1) -> None:
actions: Dict[Literal["key", "pointer", "wheel"], Union[KeyActions, PointerActions, WheelActions]] = {
"key": self.key_action,
"pointer": self.pointer_action,
"wheel": self.wheel_action
}
del actions[type]
for action in actions.values():
for _ in range(ticks):
action.pause()

def perform(self) -> None:
enc = {"actions": []}
Expand Down
5 changes: 2 additions & 3 deletions py/test/selenium/webdriver/common/interactions_tests.py
Expand Up @@ -207,15 +207,14 @@ def test_sending_keys_to_element(driver, pages):
assert "abc" == e.get_attribute("value")


def test_can_send_keys_between_clicks(driver, pages):
def test_can_perform_actions_with_multiple_devices(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()
ActionChains(driver).click(keyup).scroll_by_amount(0, 100).send_keys("foobar").perform()

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

Expand Down
Expand Up @@ -193,18 +193,21 @@ def test_sending_keys_to_element_with_keyboard(driver, pages):
assert "abc" == e.get_attribute("value")


def test_can_send_keys_between_clicks_with_keyboard(driver, pages):
def test_can_perform_actions_with_multiple_input_devices(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")

mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
key_board = KeyInput("test keyboard")
wheel = WheelInput("test wheel")

devices = [mouse, key_board, wheel]

ActionChains(driver, devices=[key_board]).click(keyup).send_keys("foobar").click(keydown).perform()
ActionChains(driver, devices=devices).click(keyup).scroll_by_amount(0, 100).send_keys("foobar").perform()

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

Expand Down