test_cli_loading_indicator.py
1 """Regression tests for loading feedback on slow slash commands.""" 2 3 from unittest.mock import patch 4 5 from cli import HermesCLI 6 7 8 class TestCLILoadingIndicator: 9 def _make_cli(self): 10 cli_obj = HermesCLI.__new__(HermesCLI) 11 cli_obj._app = None 12 cli_obj._last_invalidate = 0.0 13 cli_obj._command_running = False 14 cli_obj._command_status = "" 15 return cli_obj 16 17 def test_skills_command_sets_busy_state_and_prints_status(self, capsys): 18 cli_obj = self._make_cli() 19 seen = {} 20 21 def fake_handle(cmd: str): 22 seen["cmd"] = cmd 23 seen["running"] = cli_obj._command_running 24 seen["status"] = cli_obj._command_status 25 print("skills done") 26 27 with patch.object(cli_obj, "_handle_skills_command", side_effect=fake_handle), \ 28 patch.object(cli_obj, "_invalidate") as invalidate_mock: 29 assert cli_obj.process_command("/skills search kubernetes") 30 31 output = capsys.readouterr().out 32 assert "⏳ Searching skills..." in output 33 assert "skills done" in output 34 assert seen == { 35 "cmd": "/skills search kubernetes", 36 "running": True, 37 "status": "Searching skills...", 38 } 39 assert cli_obj._command_running is False 40 assert cli_obj._command_status == "" 41 assert invalidate_mock.call_count == 2 42 43 def test_reload_mcp_sets_busy_state_and_prints_status(self, capsys): 44 cli_obj = self._make_cli() 45 seen = {} 46 47 def fake_reload(): 48 seen["running"] = cli_obj._command_running 49 seen["status"] = cli_obj._command_status 50 print("reload done") 51 52 # /reload-mcp now wraps the actual reload in a prompt-cache-invalidation 53 # confirmation prompt (commit 4d7fc0f37). This test exercises the 54 # loading-indicator path, not the confirmation UX, so pre-approve the 55 # reload via config so the handler goes straight into _reload_mcp(). 56 fake_cfg = {"approvals": {"mcp_reload_confirm": False}} 57 58 with patch.object(cli_obj, "_reload_mcp", side_effect=fake_reload), \ 59 patch.object(cli_obj, "_invalidate") as invalidate_mock, \ 60 patch("cli.load_cli_config", return_value=fake_cfg): 61 assert cli_obj.process_command("/reload-mcp") 62 63 output = capsys.readouterr().out 64 assert "⏳ Reloading MCP servers..." in output 65 assert "reload done" in output 66 assert seen == { 67 "running": True, 68 "status": "Reloading MCP servers...", 69 } 70 assert cli_obj._command_running is False 71 assert cli_obj._command_status == "" 72 assert invalidate_mock.call_count == 2