feat: enhance drag-and-drop functionality to support multiple file paths and URLs
This commit is contained in:
parent
1e848e84b2
commit
c612072dc8
5 changed files with 384 additions and 480 deletions
|
|
@ -82,6 +82,7 @@ class TestDragInterceptorValidation:
|
|||
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
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ class TestDragInterceptorAzureURL:
|
|||
url_mappings=[
|
||||
URLMapping(
|
||||
url_prefix="https://devagravitystg.file.core.windows.net/devagravitysync/",
|
||||
local_path=str(tmp_path)
|
||||
local_path=str(tmp_path),
|
||||
)
|
||||
],
|
||||
check_file_exists=True,
|
||||
|
|
@ -150,6 +151,7 @@ class TestDragInterceptorAzureURL:
|
|||
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
|
||||
|
||||
|
|
@ -196,6 +198,7 @@ class TestDragInterceptorSignals:
|
|||
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
|
||||
|
|
@ -235,3 +238,234 @@ class TestDragInterceptorSignals:
|
|||
# Verify result and signal emission
|
||||
assert result is False
|
||||
assert len(signal_spy) == 1
|
||||
|
||||
|
||||
class TestDragInterceptorMultipleDrags:
|
||||
"""Test multiple file drag support."""
|
||||
|
||||
def test_handle_drag_with_list_single_item(self, qtbot, tmp_path):
|
||||
"""Test handle_drag with list containing single file path."""
|
||||
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)
|
||||
|
||||
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)])
|
||||
|
||||
assert result is True
|
||||
|
||||
def test_handle_drag_with_multiple_files(self, qtbot, tmp_path):
|
||||
"""Test handle_drag with list of multiple file paths."""
|
||||
# Create multiple test files
|
||||
test_file1 = tmp_path / "test1.txt"
|
||||
test_file1.write_text("content1")
|
||||
test_file2 = tmp_path / "test2.txt"
|
||||
test_file2.write_text("content2")
|
||||
test_file3 = tmp_path / "test3.txt"
|
||||
test_file3.write_text("content3")
|
||||
|
||||
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)
|
||||
|
||||
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_file1),
|
||||
str(test_file2),
|
||||
str(test_file3),
|
||||
]
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
||||
def test_handle_drag_with_multiple_azure_urls(self, qtbot, tmp_path):
|
||||
"""Test handle_drag with list of multiple Azure URLs."""
|
||||
from webdrop_bridge.config import URLMapping
|
||||
|
||||
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://produktagravitystg.file.core.windows.net/produktagravitysync/",
|
||||
local_path=str(tmp_path),
|
||||
)
|
||||
],
|
||||
check_file_exists=False, # Don't check file existence for this test
|
||||
)
|
||||
interceptor = DragInterceptor(config)
|
||||
|
||||
# Multiple Azure URLs (as would be in a multi-drag)
|
||||
azure_urls = [
|
||||
"https://produktagravitystg.file.core.windows.net/produktagravitysync/axtZdPVjs5iUaKU2muKMFN1WZ/igkjieyjcko.jpg",
|
||||
"https://produktagravitystg.file.core.windows.net/produktagravitysync/aWd7mDjnsm2w0PHU9AryQBYz2/457101023fd46d673e2ce6642f78fb0d62736f0f06c7.jpg",
|
||||
]
|
||||
|
||||
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(azure_urls)
|
||||
|
||||
assert result is True
|
||||
# Verify QDrag.exec was called (meaning drag was set up correctly)
|
||||
mock_drag_instance.exec.assert_called_once()
|
||||
|
||||
def test_handle_drag_mixed_urls_and_paths(self, qtbot, tmp_path):
|
||||
"""Test handle_drag with mixed Azure URLs and local paths."""
|
||||
from webdrop_bridge.config import URLMapping
|
||||
|
||||
# Create test file
|
||||
test_file = tmp_path / "local_file.txt"
|
||||
test_file.write_text("local 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=[
|
||||
URLMapping(
|
||||
url_prefix="https://devagravitystg.file.core.windows.net/devagravitysync/",
|
||||
local_path=str(tmp_path),
|
||||
)
|
||||
],
|
||||
check_file_exists=False, # Don't check existence for remote files
|
||||
)
|
||||
interceptor = DragInterceptor(config)
|
||||
|
||||
mixed_items = [
|
||||
str(test_file), # local path
|
||||
"https://devagravitystg.file.core.windows.net/devagravitysync/remote.jpg", # Azure URL
|
||||
]
|
||||
|
||||
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(mixed_items)
|
||||
|
||||
assert result is True
|
||||
|
||||
def test_handle_drag_multiple_empty_list(self, qtbot, test_config):
|
||||
"""Test handle_drag with empty list fails."""
|
||||
interceptor = DragInterceptor(test_config)
|
||||
|
||||
with qtbot.waitSignal(interceptor.drag_failed):
|
||||
result = interceptor.handle_drag([])
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_handle_drag_multiple_one_invalid_fails(self, qtbot, tmp_path):
|
||||
"""Test handle_drag with multiple files fails if one is invalid."""
|
||||
test_file1 = tmp_path / "test1.txt"
|
||||
test_file1.write_text("content1")
|
||||
|
||||
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)
|
||||
|
||||
# One valid, one invalid
|
||||
files = [
|
||||
str(test_file1),
|
||||
"/etc/passwd", # Invalid - outside allowed roots
|
||||
]
|
||||
|
||||
with qtbot.waitSignal(interceptor.drag_failed):
|
||||
result = interceptor.handle_drag(files)
|
||||
|
||||
assert result is False
|
||||
|
||||
def test_handle_drag_multiple_signal_with_pipes(self, qtbot, tmp_path):
|
||||
"""Test drag_started signal contains pipe-separated paths for multiple files."""
|
||||
test_file1 = tmp_path / "test1.txt"
|
||||
test_file1.write_text("content1")
|
||||
test_file2 = tmp_path / "test2.txt"
|
||||
test_file2.write_text("content2")
|
||||
|
||||
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)
|
||||
|
||||
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_file1), str(test_file2)])
|
||||
|
||||
assert result is True
|
||||
assert len(signal_spy) == 1
|
||||
# Multiple paths should be separated by " | "
|
||||
assert " | " in signal_spy[0][1]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue