Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError when using testing pilot to check for chained click events #5395

Open
PureStupid opened this issue Dec 15, 2024 · 2 comments · May be fixed by #5398
Open

TypeError when using testing pilot to check for chained click events #5395

PureStupid opened this issue Dec 15, 2024 · 2 comments · May be fixed by #5398
Assignees
Labels
bug Something isn't working

Comments

@PureStupid
Copy link
Contributor

PureStupid commented Dec 15, 2024

Declaration

I checked closed issues
I have checked against the most recent version of Textual

Description

Related PR: #5369

When using pilot.click() with the times argument set to more than 1 to test for chained click events gives a TypeError.

MouseEvent.__init__() got an unexpected keyword argument 'chain'

AFAIK this issue happens to any times argument value that isn't 1.
This also applies to the double_click and triple_click aliases.

MRE

In app.py

from textual.app import App


class MyApp(App):
    pass


if __name__ == "__main__":
    app = MyApp()
    app.run()

In test_app.py

from textual_tryout.app import MyApp


async def test_app_click():
    app = MyApp()
    async with app.run_test() as pilot:
        await pilot.click(times=2)  # Any number of times more than 1

Traceback

__________________________________________ test_app_click ___________________________________________ 

    async def test_app_click():
        app = MyApp()
        async with app.run_test() as pilot:
>           await pilot.click(times=2)

tests\test_app.py:7:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv\Lib\site-packages\textual\pilot.py:234: in click
    return await self._post_mouse_events(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Pilot app=MyApp(title='MyApp', classes={'-dark-mode'}, pseudo_classes={'dark', 'focus'})>     
events = [<class 'textual.events.MouseDown'>, <class 'textual.events.MouseUp'>, <class 'textual.events.Click'>]
widget = None, offset = Offset(x=0, y=0), button = 1, shift = False, meta = False, control = False    
times = 2

    async def _post_mouse_events(
        self,
        events: list[type[MouseEvent]],
        widget: Widget | type[Widget] | str | None | None = None,
        offset: tuple[int, int] = (0, 0),
        button: int = 0,
        shift: bool = False,
        meta: bool = False,
        control: bool = False,
        times: int = 1,
    ) -> bool:
        """Simulate a series of mouse events to be fired at a given position.

        The final position for the events is computed based on the selector provided and
        the offset specified and it must be within the visible area of the screen.

        This function abstracts away the commonalities of the other mouse event-related
        functions that the pilot exposes.

        Args:
            widget: A widget or selector used as the origin
                for the event's offset. If this is not specified, the offset is interpreted
                relative to the screen. You can use this parameter to try to target a
                specific widget. However, if the widget is currently hidden or obscured by
                another widget, the events may not land on the widget you specified.
            offset: The offset for the events. The offset is relative to the widget / selector        
                provided or to the screen, if no selector is provided.
            shift: Simulate the events with the shift key held down.
            meta: Simulate the events with the meta key held down.
            control: Simulate the events with the control key held down.
            times: The number of times to click. 2 will double-click, 3 will triple-click, etc.       
        Raises:
            OutOfBounds: If the position for the events is outside of the (visible) screen.

        Returns:
            True if no selector was specified or if the *final* event landed on the
                selected widget, False otherwise.
        """
        app = self.app
        screen = app.screen
        target_widget: Widget
        if widget is None:
            target_widget = screen
        elif isinstance(widget, Widget):
            target_widget = widget
        else:
            target_widget = app.query_one(widget)

        message_arguments = _get_mouse_message_arguments(
            target_widget,
            offset,
            button=button,
            shift=shift,
            meta=meta,
            control=control,
        )

        offset = Offset(message_arguments["x"], message_arguments["y"])
        if offset not in screen.region:
            raise OutOfBounds(
                "Target offset is outside of currently-visible screen region."
            )

        widget_at = None
        for chain in range(1, times + 1):
            for mouse_event_cls in events:
                # Get the widget under the mouse before the event because the app might
                # react to the event and move things around. We override on each iteration
                # because we assume the final event in `events` is the actual event we care
                # about and that all the preceding events are just setup.
                # E.g., the click event is preceded by MouseDown/MouseUp to emulate how
                # the driver works and emits a click event.
                kwargs = message_arguments
                if mouse_event_cls is Click:
                    kwargs["chain"] = chain
                widget_at, _ = app.get_widget_at(*offset)
>               event = mouse_event_cls(**kwargs)
E               TypeError: MouseEvent.__init__() got an unexpected keyword argument 'chain'

.venv\Lib\site-packages\textual\pilot.py:447: TypeError
====================================== short test summary info ====================================== 
FAILED tests/test_app.py::test_app_click - TypeError: MouseEvent.__init__() got an unexpected keyword argument 'chain'
========================================= 1 failed in 0.49s ========================================= 

Textual Diagnostics

Versions

Name Value
Textual 1.0.0
Rich 13.9.4

Python

Name Value
Version 3.12.3
Implementation CPython
Compiler GCC 13.2.0
Executable /home/admin/development/textual_tryout/.venv/bin/python

Operating System

Name Value
System Linux
Release 5.15.146.1-microsoft-standard-WSL2
Version #1 SMP Thu Jan 11 04:09:03 UTC 2024

Terminal

Name Value
Terminal Application vscode (1.96.0)
TERM xterm-256color
COLORTERM truecolor
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=155, height=34
legacy_windows False
min_width 1
max_width 155
is_terminal True
encoding utf-8
max_height 34
justify None
overflow None
no_wrap False
highlight None
markup None
height None
Copy link

We found the following entry in the FAQ which you may find helpful:

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by FAQtory

@willmcgugan willmcgugan added the bug Something isn't working label Dec 15, 2024
@darrenburns
Copy link
Member

Fixed by #5398

@darrenburns darrenburns linked a pull request Dec 16, 2024 that will close this issue
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants