""" Integration tests for remote control functionality. Tests the remote control system including Unix socket and TCP communication, command parsing, and settings management. """ import pytest import socket import time from unittest.mock import Mock, patch from fenrirscreenreader.core.remoteManager import RemoteManager @pytest.mark.integration @pytest.mark.remote class TestRemoteCommandParsing: """Test remote control command parsing and execution.""" def setup_method(self): """Create RemoteManager instance for each test.""" self.manager = RemoteManager() def test_say_command_parsing(self, mock_environment): """Test parsing of 'command say' messages.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "say Hello World" ) assert result["success"] is True assert "Speaking" in result["message"] mock_environment["runtime"]["OutputManager"].speak_text.assert_called_once_with( "Hello World" ) def test_interrupt_command(self, mock_environment): """Test speech interruption command.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response("interrupt") assert result["success"] is True mock_environment["runtime"][ "OutputManager" ].interrupt_output.assert_called_once() def test_setting_change_parsing(self, mock_environment): """Test parsing of 'setting set' commands.""" self.manager.initialize(mock_environment) # Mock parse_setting_args to verify it gets called with patch.object( mock_environment["runtime"]["SettingsManager"], "parse_setting_args" ) as mock_parse: result = self.manager.handle_settings_change_with_response( "set speech#rate=0.8" ) assert result["success"] is True mock_parse.assert_called_once_with("speech#rate=0.8") def test_clipboard_command(self, mock_environment): """Test clipboard setting via remote control.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "clipboard Test clipboard content" ) assert result["success"] is True mock_environment["runtime"][ "MemoryManager" ].add_value_to_first_index.assert_called_once_with( "clipboardHistory", "Test clipboard content" ) def test_quit_command(self, mock_environment): """Test Fenrir shutdown command.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "quitapplication" ) assert result["success"] is True mock_environment["runtime"][ "EventManager" ].stop_main_event_loop.assert_called_once() def test_unknown_command_rejection(self, mock_environment): """Test that unknown commands are rejected.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "unknown_command" ) assert result["success"] is False assert "Unknown command" in result["message"] @pytest.mark.integration @pytest.mark.remote class TestRemoteSettingsControl: """Test remote control of settings.""" def setup_method(self): """Create RemoteManager instance for each test.""" self.manager = RemoteManager() def test_setting_reset(self, mock_environment): """Test resetting settings to defaults.""" self.manager.initialize(mock_environment) with patch.object( mock_environment["runtime"]["SettingsManager"], "reset_setting_arg_dict" ) as mock_reset: result = self.manager.handle_settings_change_with_response("reset") assert result["success"] is True mock_reset.assert_called_once() def test_setting_save(self, mock_environment): """Test saving settings to file.""" self.manager.initialize(mock_environment) mock_environment["runtime"]["SettingsManager"].get_settings_file = Mock( return_value="/tmp/test.conf" ) with patch.object( mock_environment["runtime"]["SettingsManager"], "save_settings" ) as mock_save: result = self.manager.handle_settings_change_with_response("save") assert result["success"] is True mock_save.assert_called_once() def test_settings_remote_disabled(self, mock_environment): """Test that settings commands are blocked when disabled.""" mock_environment["runtime"]["SettingsManager"].get_setting_as_bool = Mock( return_value=False ) self.manager.initialize(mock_environment) result = self.manager.handle_settings_change_with_response( "set speech#rate=0.5" ) assert result["success"] is False assert "disabled" in result["message"].lower() @pytest.mark.integration @pytest.mark.remote class TestRemoteDataFormat: """Test remote control data format handling.""" def setup_method(self): """Create RemoteManager instance for each test.""" self.manager = RemoteManager() def test_command_prefix_case_insensitive(self, mock_environment): """Test that command prefixes are case-insensitive.""" self.manager.initialize(mock_environment) # All of these should work result1 = self.manager.handle_remote_incomming_with_response( "COMMAND say test" ) result2 = self.manager.handle_remote_incomming_with_response( "command say test" ) result3 = self.manager.handle_remote_incomming_with_response( "CoMmAnD say test" ) assert all(r["success"] for r in [result1, result2, result3]) def test_setting_prefix_case_insensitive(self, mock_environment): """Test that setting prefixes are case-insensitive.""" self.manager.initialize(mock_environment) with patch.object( mock_environment["runtime"]["SettingsManager"], "parse_setting_args" ): result1 = self.manager.handle_remote_incomming_with_response( "SETTING set speech#rate=0.5" ) result2 = self.manager.handle_remote_incomming_with_response( "setting set speech#rate=0.5" ) assert all(r["success"] for r in [result1, result2]) def test_empty_data_handling(self, mock_environment): """Test handling of empty remote data.""" self.manager.initialize(mock_environment) result = self.manager.handle_remote_incomming_with_response("") assert result["success"] is False assert "No data" in result["message"] def test_invalid_format_rejection(self, mock_environment): """Test rejection of invalid command format.""" self.manager.initialize(mock_environment) result = self.manager.handle_remote_incomming_with_response( "invalid format without prefix" ) assert result["success"] is False assert "Unknown command format" in result["message"] @pytest.mark.integration @pytest.mark.remote class TestWindowDefinition: """Test window definition via remote control.""" def setup_method(self): """Create RemoteManager instance for each test.""" self.manager = RemoteManager() def test_define_window_valid_coordinates(self, mock_environment): """Test defining a window with valid coordinates.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "window 10 5 70 20" ) assert result["success"] is True mock_environment["runtime"][ "CursorManager" ].set_window_for_application.assert_called_once() # Verify the coordinates were parsed correctly call_args = mock_environment["runtime"][ "CursorManager" ].set_window_for_application.call_args start, end = call_args[0] assert start == {"x": 10, "y": 5} assert end == {"x": 70, "y": 20} def test_define_window_insufficient_coordinates(self, mock_environment): """Test that window definition with < 4 coordinates is ignored.""" self.manager.initialize(mock_environment) # Should succeed but not call set_window_for_application result = self.manager.handle_command_execution_with_response("window 10 20") assert result["success"] is True mock_environment["runtime"][ "CursorManager" ].set_window_for_application.assert_not_called() def test_reset_window(self, mock_environment): """Test resetting window to full screen.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response("resetwindow") assert result["success"] is True mock_environment["runtime"][ "CursorManager" ].clear_window_for_application.assert_called_once() @pytest.mark.integration @pytest.mark.remote class TestVMenuControl: """Test VMenu control via remote.""" def setup_method(self): """Create RemoteManager instance for each test.""" self.manager = RemoteManager() def test_set_vmenu(self, mock_environment): """Test setting VMenu to specific menu.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response( "vmenu /vim/file/save" ) assert result["success"] is True mock_environment["runtime"]["VmenuManager"].set_curr_menu.assert_called_once_with( "/vim/file/save" ) def test_reset_vmenu(self, mock_environment): """Test resetting VMenu to default.""" self.manager.initialize(mock_environment) result = self.manager.handle_command_execution_with_response("resetvmenu") assert result["success"] is True mock_environment["runtime"]["VmenuManager"].set_curr_menu.assert_called_once_with() @pytest.mark.integration @pytest.mark.remote @pytest.mark.slow class TestRemoteControlThroughput: """Test remote control performance characteristics.""" def test_rapid_say_commands(self, mock_environment): """Test handling of rapid successive say commands.""" manager = RemoteManager() manager.initialize(mock_environment) # Send 100 rapid commands for i in range(100): result = manager.handle_command_execution_with_response(f"say test {i}") assert result["success"] is True # Verify all were queued assert ( mock_environment["runtime"]["OutputManager"].speak_text.call_count == 100 ) def test_rapid_setting_changes(self, mock_environment): """Test handling of rapid setting changes.""" manager = RemoteManager() manager.initialize(mock_environment) # Rapidly change speech rate with patch.object( mock_environment["runtime"]["SettingsManager"], "parse_setting_args" ) as mock_parse: for rate in [0.5, 0.6, 0.7, 0.8, 0.9, 1.0]: result = manager.handle_settings_change_with_response( f"set speech#rate={rate}" ) assert result["success"] is True assert mock_parse.call_count == 6