Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/common/actions/action_builder.py
4016 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
19
from typing import Any, Union
20
21
from selenium.webdriver.common.actions import interaction
22
from selenium.webdriver.common.actions.key_actions import KeyActions
23
from selenium.webdriver.common.actions.key_input import KeyInput
24
from selenium.webdriver.common.actions.pointer_actions import PointerActions
25
from selenium.webdriver.common.actions.pointer_input import PointerInput
26
from selenium.webdriver.common.actions.wheel_actions import WheelActions
27
from selenium.webdriver.common.actions.wheel_input import WheelInput
28
from selenium.webdriver.remote.command import Command
29
30
31
class ActionBuilder:
32
def __init__(
33
self,
34
driver,
35
mouse: PointerInput | None = None,
36
wheel: WheelInput | None = None,
37
keyboard: KeyInput | None = None,
38
duration: int = 250,
39
) -> None:
40
mouse = mouse or PointerInput(interaction.POINTER_MOUSE, "mouse")
41
keyboard = keyboard or KeyInput(interaction.KEY)
42
wheel = wheel or WheelInput(interaction.WHEEL)
43
self.devices: list[PointerInput | KeyInput | WheelInput] = [mouse, keyboard, wheel]
44
self._key_action = KeyActions(keyboard)
45
self._pointer_action = PointerActions(mouse, duration=duration)
46
self._wheel_action = WheelActions(wheel)
47
self.driver = driver
48
49
def get_device_with(self, name: str) -> Union["WheelInput", "PointerInput", "KeyInput"] | None:
50
"""Get the device with the given name.
51
52
Args:
53
name: The name of the device to get.
54
55
Returns:
56
The device with the given name, or None if not found.
57
"""
58
return next(filter(lambda x: x == name, self.devices), None)
59
60
@property
61
def pointer_inputs(self) -> list[PointerInput]:
62
return [device for device in self.devices if isinstance(device, PointerInput)]
63
64
@property
65
def key_inputs(self) -> list[KeyInput]:
66
return [device for device in self.devices if isinstance(device, KeyInput)]
67
68
@property
69
def key_action(self) -> KeyActions:
70
return self._key_action
71
72
@property
73
def pointer_action(self) -> PointerActions:
74
return self._pointer_action
75
76
@property
77
def wheel_action(self) -> WheelActions:
78
return self._wheel_action
79
80
def add_key_input(self, name: str) -> KeyInput:
81
"""Add a new key input device to the action builder.
82
83
Args:
84
name: The name of the key input device.
85
86
Returns:
87
The newly created key input device.
88
89
Example:
90
>>> action_builder = ActionBuilder(driver)
91
>>> action_builder.add_key_input(name="keyboard2")
92
"""
93
new_input = KeyInput(name)
94
self._add_input(new_input)
95
return new_input
96
97
def add_pointer_input(self, kind: str, name: str) -> PointerInput:
98
"""Add a new pointer input device to the action builder.
99
100
Args:
101
kind: The kind of pointer input device. Valid values are "mouse",
102
"touch", or "pen".
103
name: The name of the pointer input device.
104
105
Returns:
106
The newly created pointer input device.
107
108
Example:
109
>>> action_builder = ActionBuilder(driver)
110
>>> action_builder.add_pointer_input(kind="mouse", name="mouse")
111
"""
112
new_input = PointerInput(kind, name)
113
self._add_input(new_input)
114
return new_input
115
116
def add_wheel_input(self, name: str) -> WheelInput:
117
"""Add a new wheel input device to the action builder.
118
119
Args:
120
name: The name of the wheel input device.
121
122
Returns:
123
The newly created wheel input device.
124
125
Example:
126
>>> action_builder = ActionBuilder(driver)
127
>>> action_builder.add_wheel_input(name="wheel2")
128
"""
129
new_input = WheelInput(name)
130
self._add_input(new_input)
131
return new_input
132
133
def perform(self) -> None:
134
"""Performs all stored actions.
135
136
Example:
137
>>> action_builder = ActionBuilder(driver)
138
>>> keyboard = action_builder.key_input
139
>>> el = driver.find_element(id: "some_id")
140
>>> action_builder.click(el).pause(keyboard).pause(keyboard).pause(keyboard).send_keys("keys").perform()
141
"""
142
enc: dict[str, list[Any]] = {"actions": []}
143
for device in self.devices:
144
encoded = device.encode()
145
if encoded["actions"]:
146
enc["actions"].append(encoded)
147
device.actions = []
148
self.driver.execute(Command.W3C_ACTIONS, enc)
149
150
def clear_actions(self) -> None:
151
"""Clears actions that are already stored on the remote end.
152
153
Example:
154
>>> action_builder = ActionBuilder(driver)
155
>>> keyboard = action_builder.key_input
156
>>> el = driver.find_element(By.ID, "some_id")
157
>>> action_builder.click(el).pause(keyboard).pause(keyboard).pause(keyboard).send_keys("keys")
158
>>> action_builder.clear_actions()
159
"""
160
self.driver.execute(Command.W3C_CLEAR_ACTIONS)
161
162
def _add_input(self, new_input: KeyInput | PointerInput | WheelInput) -> None:
163
"""Add a new input device to the action builder.
164
165
Args:
166
new_input: The new input device to add.
167
"""
168
self.devices.append(new_input)
169
170