237 lines
8 KiB
Python
237 lines
8 KiB
Python
"""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://dev.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://devagravitystg.file.core.windows.net/devagravitysync/",
|
|
local_path=str(tmp_path)
|
|
)
|
|
],
|
|
check_file_exists=True,
|
|
)
|
|
interceptor = DragInterceptor(config)
|
|
|
|
# Azure URL
|
|
azure_url = "https://devagravitystg.file.core.windows.net/devagravitysync/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
|