| 1223 | ], |
| 1224 | ) |
| 1225 | def test_async_alert(base_app, msg, prompt, is_stale) -> None: |
| 1226 | import time |
| 1227 | |
| 1228 | with ( |
| 1229 | mock.patch("cmd2.cmd2.print_formatted_text") as mock_print, |
| 1230 | mock.patch("cmd2.cmd2.get_app") as mock_get_app, |
| 1231 | ): |
| 1232 | # Set up the chained mock: get_app() returns mock_app, which has invalidate() |
| 1233 | mock_app = mock.MagicMock() |
| 1234 | mock_get_app.return_value = mock_app |
| 1235 | |
| 1236 | base_app.add_alert(msg=msg, prompt=prompt) |
| 1237 | alert = base_app._alert_queue[0] |
| 1238 | |
| 1239 | # Stale means alert was created before the current prompt. |
| 1240 | if is_stale: |
| 1241 | # In the past |
| 1242 | alert.timestamp = 0.0 |
| 1243 | else: |
| 1244 | # In the future |
| 1245 | alert.timestamp = time.monotonic() + 99999999 |
| 1246 | |
| 1247 | with create_pipe_input() as pipe_input: |
| 1248 | base_app.main_session = PromptSession( |
| 1249 | input=pipe_input, |
| 1250 | output=DummyOutput(), |
| 1251 | history=base_app.main_session.history, |
| 1252 | completer=base_app.main_session.completer, |
| 1253 | ) |
| 1254 | pipe_input.send_text("quit\n") |
| 1255 | |
| 1256 | base_app._cmdloop() |
| 1257 | |
| 1258 | # If there was a message, patch_stdout handles the redraw (no invalidate) |
| 1259 | if msg: |
| 1260 | assert msg in str(mock_print.call_args_list[0]) |
| 1261 | mock_app.invalidate.assert_not_called() |
| 1262 | |
| 1263 | # If there's only a prompt update, we expect invalidate() only if not continuation/stale |
| 1264 | elif prompt is not None: |
| 1265 | if is_stale: |
| 1266 | mock_app.invalidate.assert_not_called() |
| 1267 | else: |
| 1268 | mock_app.invalidate.assert_called_once() |
| 1269 | |
| 1270 | # The state of base_app.prompt should always be correct regardless of redraw |
| 1271 | if prompt is not None: |
| 1272 | if is_stale: |
| 1273 | assert base_app.prompt != prompt |
| 1274 | else: |
| 1275 | assert base_app.prompt == prompt |
| 1276 | |
| 1277 | |
| 1278 | def test_add_alert(base_app) -> None: |