6565from ._compose import compose
6666from ._compositor import CompositorUpdate
6767from ._context import active_app , active_message_pump
68+ from ._context import message_hook as message_hook_context_var
6869from ._event_broker import NoHandler , extract_handler_actions
6970from ._path import _make_path_object_relative
7071from ._wait import wait_for_idle
100101 # Unused & ignored imports are needed for the docs to link to these objects:
101102 from .css .query import WrongType # type: ignore # noqa: F401
102103 from .devtools .client import DevtoolsClient
104+ from .message import Message
103105 from .pilot import Pilot
104106 from .widget import MountError # type: ignore # noqa: F401
105107
@@ -1060,6 +1062,7 @@ async def run_test(
10601062 headless : bool = True ,
10611063 size : tuple [int , int ] | None = (80 , 24 ),
10621064 tooltips : bool = False ,
1065+ message_hook : Callable [[Message ], None ] | None = None ,
10631066 ) -> AsyncGenerator [Pilot , None ]:
10641067 """An asynchronous context manager for testing app.
10651068
@@ -1078,6 +1081,7 @@ async def run_test(
10781081 size: Force terminal size to `(WIDTH, HEIGHT)`,
10791082 or None to auto-detect.
10801083 tooltips: Enable tooltips when testing.
1084+ message_hook: An optional callback that will called with every message going through the app.
10811085 """
10821086 from .pilot import Pilot
10831087
@@ -1090,6 +1094,8 @@ def on_app_ready() -> None:
10901094 app_ready_event .set ()
10911095
10921096 async def run_app (app ) -> None :
1097+ if message_hook is not None :
1098+ message_hook_context_var .set (message_hook )
10931099 app ._loop = asyncio .get_running_loop ()
10941100 app ._thread_id = threading .get_ident ()
10951101 await app ._process_messages (
@@ -1824,6 +1830,7 @@ async def _process_messages(
18241830 ready_callback : CallbackType | None = None ,
18251831 headless : bool = False ,
18261832 terminal_size : tuple [int , int ] | None = None ,
1833+ message_hook : Callable [[Message ], None ] | None = None ,
18271834 ) -> None :
18281835 self ._set_active ()
18291836 active_message_pump .set (self )
@@ -1978,7 +1985,7 @@ async def take_screenshot() -> None:
19781985
19791986 async def _on_compose (self ) -> None :
19801987 try :
1981- widgets = compose (self )
1988+ widgets = [ * self . screen . _nodes , * compose (self )]
19821989 except TypeError as error :
19831990 raise TypeError (
19841991 f"{ self !r} compose() method returned an invalid result; { error } "
0 commit comments