diff --git a/CHANGELOG.md b/CHANGELOG.md index 21dcd4c1ae..f129a59d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +### Fixed + +- Fixed `Pilot.click` not working with `times` parameter https://github.com/Textualize/textual/pull/5398 + ### Added - Added `from_app_focus` to `Focus` event to indicate if a widget is being focused because the app itself has regained focus or not https://github.com/Textualize/textual/pull/5379 @@ -15,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - The content of an `Input` will now only be automatically selected when the widget is focused by the user, not when the app itself has regained focus (similar to web browsers). https://github.com/Textualize/textual/pull/5379 + ## [1.0.0] - 2024-12-12 ### Added diff --git a/src/textual/pilot.py b/src/textual/pilot.py index 473341b7e9..2554bf3b8d 100644 --- a/src/textual/pilot.py +++ b/src/textual/pilot.py @@ -442,7 +442,8 @@ async def _post_mouse_events( # the driver works and emits a click event. kwargs = message_arguments if mouse_event_cls is Click: - kwargs["chain"] = chain + kwargs = {**kwargs, "chain": chain} + widget_at, _ = app.get_widget_at(*offset) event = mouse_event_cls(**kwargs) # Bypass event processing in App.on_event. Because App.on_event diff --git a/tests/test_pilot.py b/tests/test_pilot.py index 008d711389..a44e827a74 100644 --- a/tests/test_pilot.py +++ b/tests/test_pilot.py @@ -1,8 +1,10 @@ from string import punctuation +from typing import Type import pytest from textual import events, work +from textual._on import on from textual.app import App, ComposeResult from textual.binding import Binding from textual.containers import Center, Middle @@ -424,3 +426,27 @@ def on_button_pressed(self): assert not pressed await pilot.click(button) assert pressed + + +@pytest.mark.parametrize("times", [1, 2, 3]) +async def test_click_times(times: int): + """Test that Pilot.click() can be called with a `times` argument.""" + + events_received: list[Type[events.Event]] = [] + + class TestApp(App[None]): + def compose(self) -> ComposeResult: + yield Label("Click counter") + + @on(events.Click) + @on(events.MouseDown) + @on(events.MouseUp) + def on_label_clicked(self, event: events.Event): + events_received.append(event.__class__) + + app = TestApp() + async with app.run_test() as pilot: + await pilot.click(Label, times=times) + assert ( + events_received == [events.MouseDown, events.MouseUp, events.Click] * times + )