diff --git a/src/textual/command.py b/src/textual/command.py index 93823bb999..005d3d0bc7 100644 --- a/src/textual/command.py +++ b/src/textual/command.py @@ -1232,7 +1232,7 @@ def _select_or_command( self._cancel_gather_commands() self.app.post_message(CommandPalette.Closed(option_selected=True)) self.dismiss() - self.call_later(self._selected_command.command) + self.app.call_later(self._selected_command.command) @on(OptionList.OptionHighlighted) def _stop_event_leak(self, event: OptionList.OptionHighlighted) -> None: diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index fa62ca0252..fd5ca32fa2 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -2950,7 +2950,12 @@ def on_mount(self) -> None: def on_resize(self) -> None: self.add_class("narrow") - assert snap_compare(SCApp()) + async def run_before(pilot: Pilot): + await pilot.pause() + await pilot.wait_for_animation() + await pilot.pause() + + assert snap_compare(SCApp(), run_before=run_before) def test_add_remove_tabs(snap_compare): diff --git a/tests/test_command.py b/tests/test_command.py new file mode 100644 index 0000000000..3ebb6ed8d3 --- /dev/null +++ b/tests/test_command.py @@ -0,0 +1,63 @@ +from __future__ import annotations + +from typing import Iterable + +from textual.app import App, ComposeResult, SystemCommand +from textual.containers import Grid +from textual.screen import ModalScreen, Screen +from textual.widgets import Button, Label + + +class QuitScreen(ModalScreen[bool]): + """Screen with a dialog to quit.""" + + def compose(self) -> ComposeResult: + yield Grid( + Label("Are you sure you want to quit?", id="question"), + Button("Quit", variant="error", id="quit"), + Button("Cancel", variant="primary", id="cancel"), + id="dialog", + ) + + def on_button_pressed(self, event: Button.Pressed) -> None: + if event.button.id == "quit": + self.dismiss(True) + else: + self.dismiss(False) + + +class ModalApp(App): + """An app with a modal dialog.""" + + BINDINGS = [("q", "request_quit", "Quit")] + + def __init__(self) -> None: + self.check_quit_called = False + super().__init__() + + def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]: + yield from super().get_system_commands(screen) + yield SystemCommand( + "try a modal quit dialog", "this should work", self.action_request_quit + ) + + def action_request_quit(self) -> None: + """Action to display the quit dialog.""" + + def check_quit(quit: bool | None) -> None: + """Called when QuitScreen is dismissed.""" + self.check_quit_called = True + + self.push_screen(QuitScreen(), check_quit) + + +async def test_command_dismiss(): + """Regression test for https://github.com/Textualize/textual/issues/5512""" + app = ModalApp() + + async with app.run_test() as pilot: + await pilot.press("ctrl+p", *"modal quit", "enter") + await pilot.pause() + await pilot.press("enter") + await pilot.pause() + assert app.check_quit_called