Files
textual/tests/test_app_focus_blur.py
Dave Pearson 4bb9b59473 Don't restore focus on AppFocus if something has focus
While the application is in an AppBlur state, it's possible that some code
could have been running that updated what's focused. It doesn't make sense
to have Textual itself override the dev's choice to have focus be somewhere
else (perhaps the result of some long-running background process, that
they've tabbed away from, and when they tab back they expect to be in a
specific control).

So here I tweak the code that restores the focused widget so that it only
restores if it's still the case that nothing has focus.
2024-03-07 15:31:05 +00:00

80 lines
2.8 KiB
Python

"""Test the workings of reacting to AppFocus and AppBlur."""
from textual.app import App, ComposeResult
from textual.events import AppBlur, AppFocus
from textual.widgets import Input
class FocusBlurApp(App[None]):
AUTO_FOCUS = "#input-4"
def compose(self) -> ComposeResult:
for n in range(10):
yield Input(id=f"input-{n}")
async def test_app_blur() -> None:
"""Test that AppBlur removes focus."""
async with FocusBlurApp().run_test() as pilot:
assert pilot.app.focused is not None
assert pilot.app.focused.id == "input-4"
pilot.app.post_message(AppBlur())
await pilot.pause()
assert pilot.app.focused is None
async def test_app_focus_restores_focus() -> None:
"""Test that AppFocus restores the correct focus."""
async with FocusBlurApp().run_test() as pilot:
assert pilot.app.focused is not None
assert pilot.app.focused.id == "input-4"
pilot.app.post_message(AppBlur())
await pilot.pause()
assert pilot.app.focused is None
pilot.app.post_message(AppFocus())
await pilot.pause()
assert pilot.app.focused is not None
assert pilot.app.focused.id == "input-4"
async def test_app_focus_restores_none_focus() -> None:
"""Test that AppFocus doesn't set focus if nothing was focused."""
async with FocusBlurApp().run_test() as pilot:
pilot.app.screen.focused = None
pilot.app.post_message(AppBlur())
await pilot.pause()
assert pilot.app.focused is None
pilot.app.post_message(AppFocus())
await pilot.pause()
assert pilot.app.focused is None
async def test_app_focus_handles_missing_widget() -> None:
"""Test that AppFocus works even when the last-focused widget has gone away."""
async with FocusBlurApp().run_test() as pilot:
assert pilot.app.focused is not None
assert pilot.app.focused.id == "input-4"
pilot.app.post_message(AppBlur())
await pilot.pause()
assert pilot.app.focused is None
await pilot.app.query_one("#input-4").remove()
pilot.app.post_message(AppFocus())
await pilot.pause()
assert pilot.app.focused is None
async def test_app_focus_defers_to_new_focus() -> None:
"""Test that AppFocus doesn't undo a fresh focus done while the app is in AppBlur state."""
async with FocusBlurApp().run_test() as pilot:
assert pilot.app.focused is not None
assert pilot.app.focused.id == "input-4"
pilot.app.post_message(AppBlur())
await pilot.pause()
assert pilot.app.focused is None
pilot.app.query_one("#input-1").focus()
await pilot.pause()
pilot.app.post_message(AppFocus())
await pilot.pause()
assert pilot.app.focused.id == "input-1"