"""Unit tests for DragInterceptor component.""" from pathlib import Path from unittest.mock import MagicMock, patch import pytest from webdrop_bridge.config import Config from webdrop_bridge.core.drag_interceptor import DragInterceptor @pytest.fixture def test_config(tmp_path): """Create test configuration.""" return Config( app_name="Test App", app_version="1.0.0", log_level="INFO", log_file=None, allowed_roots=[tmp_path], allowed_urls=[], webapp_url="https://wps.agravity.io/", url_mappings=[], check_file_exists=True, ) class TestDragInterceptorInitialization: """Test DragInterceptor initialization and setup.""" def test_drag_interceptor_creation(self, qtbot, test_config): """Test DragInterceptor can be instantiated.""" interceptor = DragInterceptor(test_config) assert interceptor is not None assert interceptor._validator is not None assert interceptor._url_converter is not None def test_drag_interceptor_has_signals(self, qtbot, test_config): """Test DragInterceptor has required signals.""" interceptor = DragInterceptor(test_config) assert hasattr(interceptor, "drag_started") assert hasattr(interceptor, "drag_failed") def test_set_validator(self, qtbot, test_config): """Test validator is set during construction.""" interceptor = DragInterceptor(test_config) assert interceptor._validator is not None class TestDragInterceptorValidation: """Test path validation in drag operations.""" def test_handle_drag_empty_text(self, qtbot, test_config): """Test handling drag with empty text fails.""" interceptor = DragInterceptor(test_config) with qtbot.waitSignal(interceptor.drag_failed): result = interceptor.handle_drag("") assert result is False def test_handle_drag_valid_file_path(self, qtbot, tmp_path): """Test handling drag with valid file path.""" # Create a test file test_file = tmp_path / "test.txt" test_file.write_text("test content") config = Config( app_name="Test", app_version="1.0.0", log_level="INFO", log_file=None, allowed_roots=[tmp_path], allowed_urls=[], webapp_url="https://test.com/", url_mappings=[], check_file_exists=True, ) interceptor = DragInterceptor(config) # Mock the drag operation to simulate success with patch("webdrop_bridge.core.drag_interceptor.QDrag") as mock_drag: mock_drag_instance = MagicMock() # Simulate successful copy action from PySide6.QtCore import Qt mock_drag_instance.exec.return_value = Qt.DropAction.CopyAction mock_drag.return_value = mock_drag_instance result = interceptor.handle_drag(str(test_file)) # Should return True on successful drag assert result is True def test_handle_drag_invalid_path(self, qtbot, test_config): """Test drag with invalid path fails.""" interceptor = DragInterceptor(test_config) # Path outside allowed roots invalid_path = "/etc/passwd" with qtbot.waitSignal(interceptor.drag_failed): result = interceptor.handle_drag(invalid_path) assert result is False def test_handle_drag_nonexistent_file(self, qtbot, test_config, tmp_path): """Test drag with nonexistent file fails.""" interceptor = DragInterceptor(test_config) nonexistent = tmp_path / "nonexistent.txt" with qtbot.waitSignal(interceptor.drag_failed): result = interceptor.handle_drag(str(nonexistent)) assert result is False class TestDragInterceptorAzureURL: """Test Azure URL to local path conversion in drag operations.""" def test_handle_drag_azure_url(self, qtbot, tmp_path): """Test handling drag with Azure Blob Storage URL.""" from webdrop_bridge.config import URLMapping # Create test file that would be the result test_file = tmp_path / "test.png" test_file.write_text("image data") config = Config( app_name="Test", app_version="1.0.0", log_level="INFO", log_file=None, allowed_roots=[tmp_path], allowed_urls=[], webapp_url="https://test.com/", url_mappings=[ URLMapping( url_prefix="https://wpsagravitystg.file.core.windows.net/wpsagravitysync/", local_path=str(tmp_path) ) ], check_file_exists=True, ) interceptor = DragInterceptor(config) # Azure URL azure_url = "https://wpsagravitystg.file.core.windows.net/wpsagravitysync/test.png" # Mock the drag operation with patch("webdrop_bridge.core.drag_interceptor.QDrag") as mock_drag: mock_drag_instance = MagicMock() from PySide6.QtCore import Qt mock_drag_instance.exec.return_value = Qt.DropAction.CopyAction mock_drag.return_value = mock_drag_instance result = interceptor.handle_drag(azure_url) assert result is True def test_handle_drag_unmapped_url(self, qtbot, test_config): """Test handling drag with unmapped URL fails.""" interceptor = DragInterceptor(test_config) # URL with no mapping unmapped_url = "https://unknown.blob.core.windows.net/container/file.png" with qtbot.waitSignal(interceptor.drag_failed): result = interceptor.handle_drag(unmapped_url) assert result is False class TestDragInterceptorSignals: """Test signal emission on drag operations.""" def test_drag_started_signal_emitted(self, qtbot, tmp_path): """Test drag_started signal is emitted on success.""" test_file = tmp_path / "test.txt" test_file.write_text("content") config = Config( app_name="Test", app_version="1.0.0", log_level="INFO", log_file=None, allowed_roots=[tmp_path], allowed_urls=[], webapp_url="https://test.com/", url_mappings=[], check_file_exists=True, ) interceptor = DragInterceptor(config) # Connect to signal manually signal_spy = [] interceptor.drag_started.connect(lambda src, path: signal_spy.append((src, path))) from PySide6.QtCore import Qt with patch("webdrop_bridge.core.drag_interceptor.QDrag") as mock_drag: mock_drag_instance = MagicMock() mock_drag_instance.exec.return_value = Qt.DropAction.CopyAction mock_drag.return_value = mock_drag_instance result = interceptor.handle_drag(str(test_file)) # Verify result and signal emission assert result is True assert len(signal_spy) == 1 def test_drag_failed_signal_on_empty_text(self, qtbot, test_config): """Test drag_failed signal on empty text.""" interceptor = DragInterceptor(test_config) # Connect to signal manually signal_spy = [] interceptor.drag_failed.connect(lambda src, msg: signal_spy.append((src, msg))) result = interceptor.handle_drag("") # Verify result and signal emission assert result is False assert len(signal_spy) == 1 assert "Empty" in signal_spy[0][1] def test_drag_failed_signal_on_validation_error(self, qtbot, test_config): """Test drag_failed signal on validation failure.""" interceptor = DragInterceptor(test_config) # Connect to signal manually signal_spy = [] interceptor.drag_failed.connect(lambda src, msg: signal_spy.append((src, msg))) result = interceptor.handle_drag("/invalid/path/file.txt") # Verify result and signal emission assert result is False assert len(signal_spy) == 1