Skip to content

Commit

Permalink
Add pressed() method
Browse files Browse the repository at this point in the history
  • Loading branch information
jsfehler committed Jun 28, 2024
1 parent b83d353 commit 9e47def
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 19 deletions.
25 changes: 23 additions & 2 deletions docs/keyboard.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ keyboard events inside the current browser window.
.. note:: Input detection is limited to the page. You cannot control the browser
or your operating system directly using the keyboard.

The keyboard interface is generally used to trigger modifier keys.
For text input, using the keyboard is not recommended. Instead, use the
:func:`element.fill() <splinter.driver.ElementAPI.fill>` method.

.. note:: The control modifier key is different across operating systems.
e.g.: macOS uses `Command` and Windows & Linux use `Control`.
If you need a cross-platform solution, `CTRL` can be used and will be resolved
e.g.: macOS uses `COMMAND` and Windows & Linux use `CONTROL`.
For a cross-platform solution, `CTRL` can be used and will be resolved
for you.

Actions
Expand Down Expand Up @@ -86,6 +90,23 @@ This allows multiple presses to be chained together:
the press method is designed for single keys. There may be unintended
side effects to using it in place of Element.fill() or Element.type().

Press Using a Context Manager
-----------------------------

Using the `pressed()` method, a context manager will be invoked.
The specified key will be held down, then released when the block is exited.

.. code-block:: python
from splinter import Browser
browser = Browser()
browser.visit("https://duckduckgo.com/")
with browser.keyboard.pressed("SHIFT"):
browser.find_by_css("[@name='q']").fill('splinter')
Element.press()
---------------

Expand Down
18 changes: 18 additions & 0 deletions splinter/driver/webdriver/keyboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import contextlib
import platform
from collections.abc import Iterator
from typing import Union

from selenium.webdriver.common.action_chains import ActionChains
Expand Down Expand Up @@ -136,3 +138,19 @@ def press(self, key_pattern: str, delay: int = 0) -> "Keyboard":
chain.perform()

return self

@contextlib.contextmanager
def pressed(self, key_pattern: str) -> Iterator[None]:
"""Hold a key pattern inside a `with` block and releas it upon exit.
Arguments:
key_pattern: Pattern of keys to hold and release.
Example:
>>> b = Browser()
>>> with b.keyboard.pressed('CONTROL'):
>>> ...
"""
self.down(key_pattern)
yield
self.up(key_pattern)
38 changes: 21 additions & 17 deletions tests/tests_webdriver/test_keyboard.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
from splinter.driver.webdriver import Keyboard


def test_keyboard_down_modifier(browser, app_url):
"""Scenario: Keys can be held down"""
browser.visit(app_url)

keyboard = Keyboard(browser.driver)

keyboard.down("CONTROL")
browser.keyboard.down("CONTROL")

elem = browser.find_by_css("#keypress_detect")
assert elem.first
Expand All @@ -17,22 +12,18 @@ def test_keyboard_up_modifier(browser, app_url):
"""Scenario: Keys can be held up"""
browser.visit(app_url)

keyboard = Keyboard(browser.driver)

keyboard.down("CONTROL")
keyboard.up("CONTROL")
browser.keyboard.down("CONTROL")
browser.keyboard.up("CONTROL")

elem = browser.find_by_css("#keyup_detect")
assert elem.first


def test_keyboard_press_modifier(browser, app_url):
"""Keys can be pressed"""
"""Scenario: Keys can be pressed"""
browser.visit(app_url)

keyboard = Keyboard(browser.driver)

keyboard.press("CONTROL")
browser.keyboard.press("CONTROL")

elem = browser.find_by_css("#keyup_detect")
assert elem.first
Expand All @@ -42,14 +33,27 @@ def test_element_press_combo(browser, app_url):
"""Scenario: Key presses can be used in a combo"""
browser.visit(app_url)

keyboard = Keyboard(browser.driver)

keyboard.press("CONTROL+a")
browser.keyboard.press("CONTROL+a")

elem = browser.find_by_css("#keypress_detect_a")
assert elem.first


def test_keyboard_pressed_modifier(browser, app_url):
"""Scenario: Keys can be pressed by a context manager."""
browser.visit(app_url)

with browser.keyboard.pressed("CONTROL"):
down_elem = browser.find_by_css("#keypress_detect")
assert down_elem.first

up_elem = browser.find_by_css("#keyup_detect")
assert up_elem.is_empty()

up_elem = browser.find_by_css("#keyup_detect")
assert up_elem.first


def test_keyboard_ctrl(browser, app_url):
"""Scenario: The CTRL value is correct across platforms"""
browser.visit(app_url)
Expand Down

0 comments on commit 9e47def

Please sign in to comment.