From af049d4a4d9b5e3235273aedd2a14242d54a7b42 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 19 Dec 2022 09:30:22 +0000 Subject: [PATCH] added test --- src/textual/app.py | 3 +-- tests/test_binding_inheritance.py | 45 ++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index d0a475a82..bdd61771b 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -1386,11 +1386,10 @@ class App(Generic[ReturnType], DOMNode): raise finally: + self._running = True await self._ready() await invoke_ready_callback() - self._running = True - try: await self._process_messages_loop() except asyncio.CancelledError: diff --git a/tests/test_binding_inheritance.py b/tests/test_binding_inheritance.py index 49cc33092..3d4c7f89c 100644 --- a/tests/test_binding_inheritance.py +++ b/tests/test_binding_inheritance.py @@ -11,13 +11,12 @@ background relating to this. from __future__ import annotations -import pytest - from textual.app import App, ComposeResult -from textual.widgets import Static -from textual.screen import Screen from textual.binding import Binding from textual.containers import Container +from textual.screen import Screen +from textual.widget import Widget +from textual.widgets import Static ############################################################################## # These are the movement keys within Textual; they kind of have a special @@ -574,6 +573,7 @@ class PriorityOverlapScreen(Screen): def on_mount(self) -> None: self.query_one(PriorityOverlapWidget).focus() + class PriorityOverlapApp(AppKeyRecorder): """An application with a priority binding.""" @@ -607,3 +607,40 @@ async def test_overlapping_priority_bindings() -> None: "app_e", "screen_f", ] + + +async def test_skip_action() -> None: + """Test that a binding may be skipped by an action returning False""" + + class Handle(Widget, can_focus=True): + BINDINGS = [("t", "test('foo')", "Test")] + + def action_test(self, text: str) -> None: + self.app.exit(text) + + no_handle_invoked = False + + class NoHandle(Widget, can_focus=True): + BINDINGS = [("t", "test('bar')", "Test")] + + def action_test(self, text: str) -> bool: + nonlocal no_handle_invoked + no_handle_invoked = True + return False + + class SkipApp(App): + def compose(self) -> ComposeResult: + yield Handle(NoHandle()) + + def on_mount(self) -> None: + self.query_one(NoHandle).focus() + + async with SkipApp().run_test() as pilot: + # Check the NoHandle widget has focus + assert pilot.app.query_one(NoHandle).has_focus + # Press the "t" key + await pilot.press("t") + # Check the action on the no handle widget was called + assert no_handle_invoked + # Check the return value, confirming that the action on Handle was called + assert pilot.app.return_value == "foo"