Something went wrong. Try again.
The agent that grows with you
Something went wrong. Try again.
3.4 kB · 105 lines
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106"""Tests for CLI background command TUI refresh behavior.
Ensures the TUI is properly refreshed before printing background task outputto prevent spinner/status bar overlap (#2718)."""
import threadingfrom types import SimpleNamespacefrom unittest.mock import MagicMock, patch
import pytest
from cli import HermesCLI
def _make_cli(): """Create a minimal HermesCLI instance for testing.""" cli_obj = HermesCLI.__new__(HermesCLI) cli_obj.model = "test-model" cli_obj._background_tasks = {} cli_obj._background_task_counter = 0 cli_obj.conversation_history = [] cli_obj.agent = None cli_obj._app = None return cli_obj
class TestBackgroundCommandTuiRefresh: """Tests for TUI refresh in background command output."""
def test_invalidate_called_before_success_output(self): """App.invalidate() is called before printing background success output.""" cli_obj = _make_cli() mock_app = MagicMock() cli_obj._app = mock_app
# Track call order call_order = [] original_invalidate = mock_app.invalidate
def track_invalidate(): call_order.append("invalidate") return original_invalidate()
mock_app.invalidate = track_invalidate
# Patch print to track when it's called with patch("builtins.print") as mock_print: mock_print.side_effect = lambda *args, **kwargs: call_order.append("print")
# Simulate the background task output code path if cli_obj._app: cli_obj._app.invalidate() import time time.sleep(0.01) # reduced for test print()
# Verify invalidate was called before print assert call_order[0] == "invalidate" assert "print" in call_order
def test_invalidate_called_before_error_output(self): """App.invalidate() is called before printing background error output.""" cli_obj = _make_cli() mock_app = MagicMock() cli_obj._app = mock_app
call_order = [] mock_app.invalidate.side_effect = lambda: call_order.append("invalidate")
with patch("builtins.print") as mock_print: mock_print.side_effect = lambda *args, **kwargs: call_order.append("print")
# Simulate error path if cli_obj._app: cli_obj._app.invalidate() import time time.sleep(0.01) print()
assert call_order[0] == "invalidate" assert "print" in call_order
def test_no_crash_when_app_is_none(self): """No crash when _app is None (non-TUI mode).""" cli_obj = _make_cli() cli_obj._app = None
# This should not raise if cli_obj._app: cli_obj._app.invalidate() # If we get here without exception, test passes
def test_background_task_thread_safety(self): """Background task tracking is thread-safe.""" cli_obj = _make_cli()
# Simulate adding and removing background tasks task_id = "test_task_1" cli_obj._background_tasks[task_id] = MagicMock() assert task_id in cli_obj._background_tasks
# Clean up cli_obj._background_tasks.pop(task_id, None) assert task_id not in cli_obj._background_tasks