215 lines
6.3 KiB
Python
215 lines
6.3 KiB
Python
"""Tests for draggable tab functionality."""
|
|
|
|
import json
|
|
import pytest
|
|
|
|
from development_hub.draggable_tab_widget import (
|
|
DraggableTabBar,
|
|
DraggableTabWidget,
|
|
TAB_MIME_TYPE,
|
|
)
|
|
|
|
|
|
class TestDraggableTabBar:
|
|
"""Tests for DraggableTabBar."""
|
|
|
|
def test_create_with_pane_id(self, qtbot):
|
|
"""Tab bar stores pane ID."""
|
|
bar = DraggableTabBar("test-pane-123")
|
|
qtbot.addWidget(bar)
|
|
assert bar.pane_id == "test-pane-123"
|
|
|
|
def test_accepts_drops(self, qtbot):
|
|
"""Tab bar accepts drops."""
|
|
bar = DraggableTabBar("test")
|
|
qtbot.addWidget(bar)
|
|
assert bar.acceptDrops() == True
|
|
|
|
|
|
class TestDraggableTabWidget:
|
|
"""Tests for DraggableTabWidget."""
|
|
|
|
def test_create_with_pane_id(self, qtbot):
|
|
"""Tab widget stores pane ID."""
|
|
widget = DraggableTabWidget(pane_id="my-pane")
|
|
qtbot.addWidget(widget)
|
|
assert widget.pane_id == "my-pane"
|
|
|
|
def test_auto_generates_pane_id(self, qtbot):
|
|
"""Tab widget auto-generates pane ID if not provided."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
assert widget.pane_id is not None
|
|
assert len(widget.pane_id) > 0
|
|
|
|
def test_pane_id_setter(self, qtbot):
|
|
"""Pane ID can be set after creation."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
widget.pane_id = "new-pane-id"
|
|
assert widget.pane_id == "new-pane-id"
|
|
|
|
def test_accepts_drops(self, qtbot):
|
|
"""Tab widget accepts drops."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
assert widget.acceptDrops() == True
|
|
|
|
def test_tabs_closable(self, qtbot):
|
|
"""Tabs are closable."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
assert widget.tabsClosable() == True
|
|
|
|
def test_tabs_movable(self, qtbot):
|
|
"""Tabs are movable."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
assert widget.isMovable() == True
|
|
|
|
def test_drop_index_empty(self, qtbot):
|
|
"""Drop index at end when no tabs."""
|
|
widget = DraggableTabWidget()
|
|
qtbot.addWidget(widget)
|
|
from PySide6.QtCore import QPoint
|
|
index = widget._get_drop_index(QPoint(0, 0))
|
|
assert index == 0
|
|
|
|
def test_custom_tab_bar(self, qtbot):
|
|
"""Uses custom DraggableTabBar."""
|
|
widget = DraggableTabWidget(pane_id="test")
|
|
qtbot.addWidget(widget)
|
|
assert isinstance(widget.tabBar(), DraggableTabBar)
|
|
assert widget.tabBar().pane_id == "test"
|
|
|
|
|
|
class TestMimeData:
|
|
"""Tests for MIME data format."""
|
|
|
|
def test_mime_type_constant(self):
|
|
"""MIME type constant is defined."""
|
|
assert TAB_MIME_TYPE == "application/x-devhub-tab"
|
|
|
|
def test_drag_data_format(self):
|
|
"""Drag data includes required fields."""
|
|
data = {
|
|
"pane_id": "source-pane",
|
|
"tab_index": 2,
|
|
"tab_text": "Terminal",
|
|
}
|
|
encoded = json.dumps(data).encode('utf-8')
|
|
decoded = json.loads(encoded.decode('utf-8'))
|
|
|
|
assert decoded["pane_id"] == "source-pane"
|
|
assert decoded["tab_index"] == 2
|
|
assert decoded["tab_text"] == "Terminal"
|
|
|
|
|
|
class TestPaneWidgetTabOperations:
|
|
"""Tests for PaneWidget tab operations used in cross-pane drag."""
|
|
|
|
def test_take_tab_at_valid_index(self, qtbot):
|
|
"""take_tab_at removes and returns tab at index."""
|
|
from PySide6.QtWidgets import QLabel
|
|
|
|
from development_hub.pane_widget import PaneWidget
|
|
|
|
pane = PaneWidget()
|
|
qtbot.addWidget(pane)
|
|
|
|
# Add some tabs
|
|
label1 = QLabel("Tab 1")
|
|
label2 = QLabel("Tab 2")
|
|
pane.tab_widget.addTab(label1, "First")
|
|
pane.tab_widget.addTab(label2, "Second")
|
|
|
|
assert pane.tab_count() == 2
|
|
|
|
result = pane.take_tab_at(0)
|
|
assert result is not None
|
|
widget, title = result
|
|
assert title == "First"
|
|
assert pane.tab_count() == 1
|
|
|
|
def test_take_tab_at_invalid_index(self, qtbot):
|
|
"""take_tab_at returns None for invalid index."""
|
|
from development_hub.pane_widget import PaneWidget
|
|
|
|
pane = PaneWidget()
|
|
qtbot.addWidget(pane)
|
|
|
|
result = pane.take_tab_at(99)
|
|
assert result is None
|
|
|
|
result = pane.take_tab_at(-1)
|
|
assert result is None
|
|
|
|
def test_insert_widget_tab(self, qtbot):
|
|
"""insert_widget_tab inserts at correct position."""
|
|
from PySide6.QtWidgets import QLabel
|
|
|
|
from development_hub.pane_widget import PaneWidget
|
|
|
|
pane = PaneWidget()
|
|
qtbot.addWidget(pane)
|
|
|
|
label1 = QLabel("Tab 1")
|
|
label2 = QLabel("Tab 2")
|
|
label3 = QLabel("Tab 3")
|
|
|
|
pane.tab_widget.addTab(label1, "First")
|
|
pane.tab_widget.addTab(label2, "Second")
|
|
|
|
# Insert in middle
|
|
pane.insert_widget_tab(1, label3, "Inserted")
|
|
|
|
assert pane.tab_count() == 3
|
|
assert pane.tab_widget.tabText(0) == "First"
|
|
assert pane.tab_widget.tabText(1) == "Inserted"
|
|
assert pane.tab_widget.tabText(2) == "Second"
|
|
|
|
def test_pane_has_unique_id(self, qtbot):
|
|
"""Each pane has a unique ID."""
|
|
from development_hub.pane_widget import PaneWidget
|
|
|
|
pane1 = PaneWidget()
|
|
pane2 = PaneWidget()
|
|
qtbot.addWidget(pane1)
|
|
qtbot.addWidget(pane2)
|
|
|
|
assert pane1.pane_id != pane2.pane_id
|
|
assert len(pane1.pane_id) > 0
|
|
assert len(pane2.pane_id) > 0
|
|
|
|
|
|
class TestWorkspaceTabDropHandling:
|
|
"""Tests for workspace manager tab drop handling."""
|
|
|
|
def test_find_pane_by_id(self, qtbot):
|
|
"""Workspace can find pane by ID."""
|
|
from development_hub.workspace_manager import WorkspaceManager
|
|
|
|
manager = WorkspaceManager()
|
|
qtbot.addWidget(manager)
|
|
|
|
panes = manager.find_panes()
|
|
assert len(panes) == 1
|
|
|
|
pane = panes[0]
|
|
found = manager._find_pane_by_id(pane.pane_id)
|
|
assert found == pane
|
|
|
|
def test_find_pane_by_id_not_found(self, qtbot):
|
|
"""Returns None for unknown pane ID."""
|
|
from development_hub.workspace_manager import WorkspaceManager
|
|
|
|
manager = WorkspaceManager()
|
|
qtbot.addWidget(manager)
|
|
|
|
found = manager._find_pane_by_id("nonexistent-id")
|
|
assert found is None
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|