Skip to content

Commit

Permalink
[#570] NEW: command.paste, command.paste(text)
Browse files Browse the repository at this point in the history
+ the corresponding methods built into web.Element
  • Loading branch information
yashaka committed Feb 3, 2025
1 parent 442d554 commit 348a6aa
Show file tree
Hide file tree
Showing 11 changed files with 488 additions and 66 deletions.
20 changes: 15 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ Next:
- ensure query.* and command.* use proper classes
- rename context.py to client.py

### pyperclip as dependency in Selene

Mainly for `command.paste(text)` command to work out of the box with clipboard.

### Deprecated conditions

- `be.present` in favor of `be.present_in_dom`
Expand Down Expand Up @@ -528,8 +532,11 @@ See a practical example of usage in [FAQ: How to simplify search by Test IDs?](h

### More commands among browser.element(selector).*

web.Element built in methods:
- `press_sequentially(text)`
- `select_all()`
- `copy()`
- `paste(text=None)`
- `drag_and_drop_to(target, _assert_location_changed=False)`
- with option to `.with(drag_and_drop_by_js=True).drag_and_drop_to(target)`
- `drag_and_drop_by_offset(x, y)`
Expand All @@ -540,15 +547,18 @@ See a practical example of usage in [FAQ: How to simplify search by Test IDs?](h

### More commands in command.py

web.Element or web.Browser commands:
- `command.copy`
- `command.paste`
- `command.copy_and_paste(text)`
Requires 3rd party `pyperclip` package to be used,
in order to copy to clipboard before pasting
via simulating `ctrl+v` or `cmd+v` shortcut pressed.
- `command.paste(text)`
The `pyperclip` package was added to Selene as dependency to achieve it.

Element commands:
- `command.press_sequentially(text: str)`

mobile.Element commands:
- `command.long_press(duration=0.1)` alias to `command._long_press(duration=0.1)`
actually the _long_press is now an outdated alias and probably will be deprecated in future releases
- `command.press_sequentially(text: str)`

### More collection queries in query.py

Expand Down
150 changes: 150 additions & 0 deletions docs/faq/clipboard-copy-and-paste-howto.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# How to work with clipboard in Selene? {: #clipboard-copy-and-paste-howto}

{% include-markdown 'warn-from-next-release.md' %}

## Summary

Selene works with clipboard via the [pyperclip](https://pypi.org/project/pyperclip/) package. And there is only one command in Selene that uses it under the hood – [command.paste(text)][selene.core.command.paste]. In other cases you can use `pyperclip` directly to achieve your goals via `paperclip.copy(text)` and `paperclip.paste(text)`.

Let's consider the main scenarios to work with clipboard...

## Main Scenarios

### Copy a text into clipboard

```python
import pyperclip
...

pyperclip.copy('text to copy')
```

### Copy a text of element into clipboard

```python
from selene import browser, query
import pyperclip
...

pyperclip.copy(browser.element('.message').get(query.text))
```

See also [#573](https://github.com/yashaka/selene/issues/573)

### Copy a value of an input element into clipboard

```python
from selene import browser, query
import pyperclip
...

pyperclip.copy(browser.element('input').get(query.value))
```

### Copy currently selected text on the page into clipboard via OS-based shortcut

```python
from selene import browser, command
...

browser.perform(command.copy)
```

See also [#575](https://github.com/yashaka/selene/issues/575)

### Paste into currently focused element a text from the clipboard via OS-based shortcut

```python
from selene import browser, command
...

browser.perform(command.paste)
```

See also [#575](https://github.com/yashaka/selene/issues/575)

### Put a text in the clipboard, then paste it into currently focused element via OS-based shortcut

```python
from selene import browser, command
...

browser.perform(command.paste('some text to put into clipboard first'))
```

See also [#575](https://github.com/yashaka/selene/issues/575)

### Select value of an input element, then copy it into clipboard via OS-based shortcut

```python
from selene import browser, command
...

browser.element('input').select_all().copy()
# OR:
browser.element('input').select_all().perform(command.copy)
```

### Type a text stored in the clipboard into text input at the current cursor position

```python
from selene import browser
import pyperclip
...

browser.element('input').type(pyperclip.paste())
```

### Set a new value to the text input getting this value from the clipboard

```python
from selene import browser
import pyperclip
...

browser.element('input').set_value(pyperclip.paste())
```

### Paste via OS-based shortcut a text stored in the clipboard into text input at the current cursor position

```python
from selene import browser, command
...

browser.element('input').paste()
# OR:
browser.element('input').perform(command.paste)
```

### Paste via OS-based shortcut a text stored in the clipboard into text input substituting the current text via "select all" OS-based shortcut

```python
from selene import browser, command
...

browser.element('input').select_all().paste()
# OR:
browser.element('input').select_all().perform(command.paste)
```

### Copy a text into clipboard, then paste it via OS-based shortcut into text input at the current cursor position

```python
from selene import browser, command
...
text = 'text to append'
browser.element('input').paste(text)
# OR:
browser.element('input').perform(command.paste(text))
```

### Copy a text into clipboard, then paste it via OS-based shortcut into text input substituting the current text via "select all" OS-based shortcut

```python
from selene import browser, command
...
text = 'new text value'
browser.element('input').select_all().paste(text)
# OR:
browser.element('input').select_all().perform(command.paste(text))
```
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ nav:
# - Stub Title 1: learn-advanced/automate-testing-guide.md
- FAQ:
- How to simplify search by Test IDs?: faq/custom-test-id-selectors-howto.md
- How to work with clipboard in Selene?: faq/clipboard-copy-and-paste-howto.md
- How to work with iFrames: faq/iframes-howto.md
- How to work with Shadow DOM: faq/shadow-dom-howto.md
- How to use custom profile: faq/custom-user-profile-howto.md
Expand Down Expand Up @@ -130,6 +131,7 @@ plugins:

# Extensions
markdown_extensions:
- attr_list
- toc:
permalink: "#"
- admonition
Expand Down
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Changelog = "https://github.com/yashaka/selene/releases"
[tool.poetry.dependencies]
python = "^3.8"
selenium = ">=4.12.0"
pyperclip = "^1.9.0"
future = "*"
typing-extensions = ">=4.12.2"

Expand All @@ -62,7 +63,6 @@ mypy = "*"
pydantic = "^1.10.7"
python-dotenv = "0.21.1"
Appium-Python-Client = "^4.2.0"
pyperclip = "^1.8.2"
setuptools = "^70.0.0"

[tool.poetry.group.docs]
Expand All @@ -83,6 +83,7 @@ requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.mypy]
follow_untyped_imports = true
disable_error_code = 'annotation-unchecked'
allow_redefinition = true # TODO: how to properly make it work o_O ?
color_output=1
Expand Down
8 changes: 8 additions & 0 deletions selene/common/fp.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ def pipe(*functions) -> Optional[Callable[[Any], Any]]:
)


def perform(*functions) -> Callable[[], None]:
def one_by_one():
for fn in functions:
fn()

return one_by_one


# TODO: support "detailed history of prev calls on failures"
# TODO: support tuple form of functions
# TODO: support ... as arg placeholder in tuple form of functions
Expand Down
Loading

0 comments on commit 348a6aa

Please sign in to comment.