Skip to content

Commit

Permalink
Add ui.input trigger autocomplete trigger capability (#4001)
Browse files Browse the repository at this point in the history
This fixes the issue mentioned in #3886 .

The PR implements a workaround in the testing/user_interaction module by
checking if a trigger event is a "tab" event and then replacing the
current text value by the first element in the autocomplete list.

---------

Co-authored-by: Falko Schindler <[email protected]>
Co-authored-by: Falko Schindler <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2024
1 parent dd2504a commit f5d1ef3
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
9 changes: 8 additions & 1 deletion nicegui/testing/user_interaction.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Generic, Set, Type, TypeVar, Union
from typing import TYPE_CHECKING, Generic, List, Set, Type, TypeVar, Union

from typing_extensions import Self

Expand Down Expand Up @@ -36,6 +36,13 @@ def trigger(self, event: str) -> Self:
assert self.user.client
with self.user.client:
for element in self.elements:
if isinstance(element, ui.input) and event == 'keydown.tab':
autocomplete: List[str] = element.props['_autocomplete']
for option in autocomplete:
if option.startswith(element.value):
element.value = option
break

for listener in element._event_listeners.values(): # pylint: disable=protected-access
if listener.type != event:
continue
Expand Down
9 changes: 9 additions & 0 deletions tests/test_user_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,12 @@ async def test_validation(user: User) -> None:
await user.should_not_see('Not a number')
user.find(ui.input).type('some invalid entry')
await user.should_see('Not a number')


async def test_trigger_autocomplete(user: User) -> None:
ui.input(label='fruit', autocomplete=['apple', 'banana', 'cherry'])

await user.open('/')
await user.should_not_see('apple')
user.find('fruit').type('a').trigger('keydown.tab')
await user.should_see('apple')
26 changes: 26 additions & 0 deletions website/documentation/content/user_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,32 @@ def receive_file(e: events.UploadEventArguments):
''')


doc.text('Autocomplete', '''
The `UserInteraction` object returned by `user.find(...)` provides methods to trigger events on the found elements.
This demo shows how to trigger a "keydown.tab" event to autocomplete an input field.
''')


@doc.ui
def trigger_events():
with ui.row().classes('gap-4 items-stretch'):
with python_window(classes='w-[500px]', title='some UI code'):
ui.markdown('''
```python
fruits = ['apple', 'banana', 'cherry']
ui.input(label='fruit', autocomplete=fruits)
```
''')
with python_window(classes='w-[500px]', title='user assertions'):
ui.markdown('''
```python
await user.open('/')
user.find('fruit').type('a').trigger('keydown.tab')
await user.should_see('apple')
```
''')


doc.text('Test Downloads', '''
You can verify that a download was triggered by checking `user.downloads.http_responses`.
By awaiting `user.downloads.next()` you can get the next download response.
Expand Down

0 comments on commit f5d1ef3

Please sign in to comment.