diff --git a/gsd-openclaw/tests/test_orchestrator.py b/gsd-openclaw/tests/test_orchestrator.py index 3f79178..270ac87 100644 --- a/gsd-openclaw/tests/test_orchestrator.py +++ b/gsd-openclaw/tests/test_orchestrator.py @@ -545,3 +545,183 @@ class TestIntegrationFlows: # Verify result is a confirmation card assert "schema" in result + + +class TestSpecialCommands: + """Tests for special command handling (new-project, use).""" + + @pytest.fixture + def orchestrator_with_mocks(self): + """Create orchestrator with mocked dependencies for special commands.""" + from gsd_openclaw.orchestrator import Orchestrator + + mock_tmux_manager = MagicMock() + mock_formatter = MagicMock() + mock_executor = MagicMock() + + orchestrator = Orchestrator( + tmux_manager=mock_tmux_manager, + formatter=mock_formatter + ) + orchestrator.executor = mock_executor + + return orchestrator + + def test_orchestrator_initializes_with_user_context_manager(self, orchestrator_with_mocks): + """Orchestrator should initialize with UserContextManager instance.""" + orch = orchestrator_with_mocks + + # Should have user_context_managers dict + assert hasattr(orch, 'user_context_managers') + assert isinstance(orch.user_context_managers, dict) + + def test_new_project_creates_session_before_executing(self, orchestrator_with_mocks): + """_handle_new_project should create tmux session before executing command.""" + from gsd_openclaw.tmux_session import TmuxSession + + orch = orchestrator_with_mocks + + mock_session = MagicMock(spec=TmuxSession) + mock_session.session_id = "test-123" + mock_session.tmux_session = MagicMock() + orch.tmux_manager.create_session.return_value = mock_session + orch.tmux_manager.get_session.return_value = None + + orch.executor.execute.return_value = CommandResult( + output="Project created successfully", + completed=True, + has_error=False, + error_type=None + ) + + orch.formatter.format_success.return_value = {"card": "success"} + + result = orch._handle_new_project("user1", "my-project") + + # Verify session was created first + orch.tmux_manager.create_session.assert_called_once_with("my-project") + + def test_new_project_updates_user_context(self, orchestrator_with_mocks): + """_handle_new_project should update user context with new project.""" + from gsd_openclaw.tmux_session import TmuxSession + + orch = orchestrator_with_mocks + + mock_session = MagicMock(spec=TmuxSession) + mock_session.session_id = "test-123" + mock_session.tmux_session = MagicMock() + orch.tmux_manager.create_session.return_value = mock_session + orch.tmux_manager.get_session.return_value = None + + orch.executor.execute.return_value = CommandResult( + output="Project created successfully", + completed=True, + has_error=False, + error_type=None + ) + + orch.formatter.format_success.return_value = {"card": "success"} + + result = orch._handle_new_project("user1", "my-project") + + # Verify user context was updated + user_ctx = orch._get_user_context_manager("user1") + assert user_ctx.get_current_project() == "my-project" + + def test_new_project_executes_command_in_session(self, orchestrator_with_mocks): + """_handle_new_project should execute the command in the new session.""" + from gsd_openclaw.tmux_session import TmuxSession + + orch = orchestrator_with_mocks + + mock_session = MagicMock(spec=TmuxSession) + mock_session.session_id = "test-123" + mock_session.tmux_session = MagicMock() + orch.tmux_manager.create_session.return_value = mock_session + orch.tmux_manager.get_session.return_value = None + + orch.executor.execute.return_value = CommandResult( + output="Project initialized", + completed=True, + has_error=False, + error_type=None + ) + + orch.formatter.format_success.return_value = {"card": "success"} + + result = orch._handle_new_project("user1", "my-project") + + # Verify command was executed + orch.executor.execute.assert_called_once() + call_args = orch.executor.execute.call_args + assert call_args[0][0] == mock_session + assert "/gsd:new-project my-project" in call_args[0][1] + + def test_new_project_returns_success_card(self, orchestrator_with_mocks): + """_handle_new_project should return formatted success card.""" + from gsd_openclaw.tmux_session import TmuxSession + + orch = orchestrator_with_mocks + + mock_session = MagicMock(spec=TmuxSession) + mock_session.session_id = "test-123" + mock_session.tmux_session = MagicMock() + orch.tmux_manager.create_session.return_value = mock_session + orch.tmux_manager.get_session.return_value = None + + orch.executor.execute.return_value = CommandResult( + output="Project created", + completed=True, + has_error=False, + error_type=None + ) + + orch.formatter.format_success.return_value = {"card": "success"} + + result = orch._handle_new_project("user1", "my-project") + + orch.formatter.format_success.assert_called_once() + + def test_handle_message_routes_new_project_command(self, orchestrator_with_mocks): + """handle_message should route 'new-project' command to _handle_new_project.""" + from gsd_openclaw.tmux_session import TmuxSession + + orch = orchestrator_with_mocks + + mock_session = MagicMock(spec=TmuxSession) + mock_session.session_id = "test-123" + mock_session.tmux_session = MagicMock() + orch.tmux_manager.create_session.return_value = mock_session + orch.tmux_manager.get_session.return_value = None + + orch.executor.execute.return_value = CommandResult( + output="Project created", + completed=True, + has_error=False, + error_type=None + ) + + orch.formatter.format_success.return_value = {"card": "success"} + + # Patch _handle_new_project to verify it's called + with patch.object(orch, '_handle_new_project', return_value={"card": "mocked"}) as mock_handler: + result = orch.handle_message( + user_id="user1", + message="/gsd:new-project test-project", + channel="test-channel", + context={} + ) + + mock_handler.assert_called_once_with("user1", "test-project") + + def test_new_project_with_empty_name_returns_error(self, orchestrator_with_mocks): + """_handle_new_project with empty project name should return error.""" + orch = orchestrator_with_mocks + + orch.formatter.format_error.return_value = {"card": "error"} + + result = orch._handle_new_project("user1", "") + + orch.formatter.format_error.assert_called_once() + call_args = orch.formatter.format_error.call_args + assert "Project name" in str(call_args)