/ tests / cli / test_cli_status_command.py
test_cli_status_command.py
  1  """Tests for CLI /status command behavior."""
  2  from datetime import datetime
  3  from pathlib import Path
  4  from types import SimpleNamespace
  5  from unittest.mock import MagicMock, patch
  6  
  7  from cli import HermesCLI
  8  from hermes_cli.commands import resolve_command
  9  
 10  
 11  def _make_cli():
 12      cli_obj = HermesCLI.__new__(HermesCLI)
 13      cli_obj.config = {}
 14      cli_obj.console = MagicMock()
 15      cli_obj.agent = None
 16      cli_obj.conversation_history = []
 17      cli_obj.session_id = "session-123"
 18      cli_obj._pending_input = MagicMock()
 19      cli_obj._status_bar_visible = True
 20      cli_obj.model = "openai/gpt-5.4"
 21      cli_obj.provider = "openai"
 22      cli_obj.session_start = datetime(2026, 4, 9, 19, 24)
 23      cli_obj._agent_running = False
 24      cli_obj._session_db = MagicMock()
 25      cli_obj._session_db.get_session.return_value = None
 26      return cli_obj
 27  
 28  
 29  def test_status_command_is_available_in_cli_registry():
 30      cmd = resolve_command("status")
 31      assert cmd is not None
 32      assert cmd.gateway_only is False
 33  
 34  
 35  def test_process_command_status_dispatches_without_toggling_status_bar():
 36      cli_obj = _make_cli()
 37  
 38      with patch.object(cli_obj, "_show_session_status", create=True) as mock_status:
 39          assert cli_obj.process_command("/status") is True
 40  
 41      mock_status.assert_called_once_with()
 42      assert cli_obj._status_bar_visible is True
 43  
 44  
 45  def test_statusbar_still_toggles_visibility():
 46      cli_obj = _make_cli()
 47  
 48      assert cli_obj.process_command("/statusbar") is True
 49      assert cli_obj._status_bar_visible is False
 50  
 51  
 52  def test_status_prefix_prefers_status_command_over_statusbar_toggle():
 53      cli_obj = _make_cli()
 54  
 55      with patch.object(cli_obj, "_show_session_status") as mock_status:
 56          assert cli_obj.process_command("/sta") is True
 57  
 58      mock_status.assert_called_once_with()
 59      assert cli_obj._status_bar_visible is True
 60  
 61  
 62  def test_show_session_status_prints_gateway_style_summary():
 63      cli_obj = _make_cli()
 64      cli_obj.agent = SimpleNamespace(
 65          session_total_tokens=321,
 66          session_api_calls=4,
 67      )
 68      cli_obj._session_db.get_session.return_value = {
 69          "title": "My titled session",
 70          "started_at": 1775791440,
 71      }
 72  
 73      with patch("cli.display_hermes_home", return_value="~/.hermes"):
 74          cli_obj._show_session_status()
 75  
 76      printed = "\n".join(str(call.args[0]) for call in cli_obj.console.print.call_args_list)
 77      assert "Hermes CLI Status" in printed
 78      assert "Session ID: session-123" in printed
 79      assert "Path: ~/.hermes" in printed
 80      assert "Title: My titled session" in printed
 81      assert "Model: openai/gpt-5.4 (openai)" in printed
 82      assert "Tokens: 321" in printed
 83      assert "Agent Running: No" in printed
 84      _, kwargs = cli_obj.console.print.call_args
 85      assert kwargs.get("highlight") is False
 86      assert kwargs.get("markup") is False
 87  
 88  
 89  def test_profile_command_reports_custom_root_profile(monkeypatch, tmp_path, capsys):
 90      """Profile detection works for custom-root deployments (not under ~/.hermes)."""
 91      cli_obj = _make_cli()
 92      profile_home = tmp_path / "profiles" / "coder"
 93  
 94      monkeypatch.setenv("HERMES_HOME", str(profile_home))
 95      monkeypatch.setattr(Path, "home", lambda: tmp_path / "unrelated-home")
 96  
 97      cli_obj._handle_profile_command()
 98  
 99      out = capsys.readouterr().out
100      assert "Profile: coder" in out
101      assert f"Home:    {profile_home}" in out