Path: blob/trunk/py/selenium/webdriver/common/actions/action_builder.py
4016 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.161718from typing import Any, Union1920from selenium.webdriver.common.actions import interaction21from selenium.webdriver.common.actions.key_actions import KeyActions22from selenium.webdriver.common.actions.key_input import KeyInput23from selenium.webdriver.common.actions.pointer_actions import PointerActions24from selenium.webdriver.common.actions.pointer_input import PointerInput25from selenium.webdriver.common.actions.wheel_actions import WheelActions26from selenium.webdriver.common.actions.wheel_input import WheelInput27from selenium.webdriver.remote.command import Command282930class ActionBuilder:31def __init__(32self,33driver,34mouse: PointerInput | None = None,35wheel: WheelInput | None = None,36keyboard: KeyInput | None = None,37duration: int = 250,38) -> None:39mouse = mouse or PointerInput(interaction.POINTER_MOUSE, "mouse")40keyboard = keyboard or KeyInput(interaction.KEY)41wheel = wheel or WheelInput(interaction.WHEEL)42self.devices: list[PointerInput | KeyInput | WheelInput] = [mouse, keyboard, wheel]43self._key_action = KeyActions(keyboard)44self._pointer_action = PointerActions(mouse, duration=duration)45self._wheel_action = WheelActions(wheel)46self.driver = driver4748def get_device_with(self, name: str) -> Union["WheelInput", "PointerInput", "KeyInput"] | None:49"""Get the device with the given name.5051Args:52name: The name of the device to get.5354Returns:55The device with the given name, or None if not found.56"""57return next(filter(lambda x: x == name, self.devices), None)5859@property60def pointer_inputs(self) -> list[PointerInput]:61return [device for device in self.devices if isinstance(device, PointerInput)]6263@property64def key_inputs(self) -> list[KeyInput]:65return [device for device in self.devices if isinstance(device, KeyInput)]6667@property68def key_action(self) -> KeyActions:69return self._key_action7071@property72def pointer_action(self) -> PointerActions:73return self._pointer_action7475@property76def wheel_action(self) -> WheelActions:77return self._wheel_action7879def add_key_input(self, name: str) -> KeyInput:80"""Add a new key input device to the action builder.8182Args:83name: The name of the key input device.8485Returns:86The newly created key input device.8788Example:89>>> action_builder = ActionBuilder(driver)90>>> action_builder.add_key_input(name="keyboard2")91"""92new_input = KeyInput(name)93self._add_input(new_input)94return new_input9596def add_pointer_input(self, kind: str, name: str) -> PointerInput:97"""Add a new pointer input device to the action builder.9899Args:100kind: The kind of pointer input device. Valid values are "mouse",101"touch", or "pen".102name: The name of the pointer input device.103104Returns:105The newly created pointer input device.106107Example:108>>> action_builder = ActionBuilder(driver)109>>> action_builder.add_pointer_input(kind="mouse", name="mouse")110"""111new_input = PointerInput(kind, name)112self._add_input(new_input)113return new_input114115def add_wheel_input(self, name: str) -> WheelInput:116"""Add a new wheel input device to the action builder.117118Args:119name: The name of the wheel input device.120121Returns:122The newly created wheel input device.123124Example:125>>> action_builder = ActionBuilder(driver)126>>> action_builder.add_wheel_input(name="wheel2")127"""128new_input = WheelInput(name)129self._add_input(new_input)130return new_input131132def perform(self) -> None:133"""Performs all stored actions.134135Example:136>>> action_builder = ActionBuilder(driver)137>>> keyboard = action_builder.key_input138>>> el = driver.find_element(id: "some_id")139>>> action_builder.click(el).pause(keyboard).pause(keyboard).pause(keyboard).send_keys("keys").perform()140"""141enc: dict[str, list[Any]] = {"actions": []}142for device in self.devices:143encoded = device.encode()144if encoded["actions"]:145enc["actions"].append(encoded)146device.actions = []147self.driver.execute(Command.W3C_ACTIONS, enc)148149def clear_actions(self) -> None:150"""Clears actions that are already stored on the remote end.151152Example:153>>> action_builder = ActionBuilder(driver)154>>> keyboard = action_builder.key_input155>>> el = driver.find_element(By.ID, "some_id")156>>> action_builder.click(el).pause(keyboard).pause(keyboard).pause(keyboard).send_keys("keys")157>>> action_builder.clear_actions()158"""159self.driver.execute(Command.W3C_CLEAR_ACTIONS)160161def _add_input(self, new_input: KeyInput | PointerInput | WheelInput) -> None:162"""Add a new input device to the action builder.163164Args:165new_input: The new input device to add.166"""167self.devices.append(new_input)168169170