Bläddra i källkod

Add ui.input trigger autocomplete trigger capability (#4001)

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 <mail@falkoschindler.de>
Co-authored-by: Falko Schindler <falko@zauberzeug.com>
Adrian Pachzelt 5 månader sedan
förälder
incheckning
f5d1ef3847

+ 8 - 1
nicegui/testing/user_interaction.py

@@ -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
 
@@ -36,6 +36,13 @@ class UserInteraction(Generic[T]):
         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

+ 9 - 0
tests/test_user_simulation.py

@@ -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 - 0
website/documentation/content/user_documentation.py

@@ -156,6 +156,32 @@ def upload_table():
             ''')
 
 
+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.