Files
luk/tests/test_sync_dashboard.py
2025-12-16 17:13:26 -05:00

236 lines
7.6 KiB
Python

"""Tests for the sync dashboard TUI."""
import pytest
from unittest.mock import MagicMock, patch
from datetime import datetime
from src.cli.sync_dashboard import (
SyncDashboard,
SyncProgressTracker,
TaskStatus,
TaskListItem,
get_dashboard,
get_progress_tracker,
)
class TestSyncProgressTracker:
"""Tests for the SyncProgressTracker class."""
def test_init(self):
"""Test tracker initialization."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
assert tracker.dashboard == mock_dashboard
def test_start_task(self):
"""Test starting a new task."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.start_task("inbox", 100)
mock_dashboard.start_task.assert_called_once_with("inbox", 100)
def test_start_task_default_total(self):
"""Test starting a task with default total."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.start_task("calendar")
mock_dashboard.start_task.assert_called_once_with("calendar", 100)
def test_update_task(self):
"""Test updating task progress."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.update_task("inbox", 50, "Processing...")
mock_dashboard.update_task.assert_called_once_with("inbox", 50, "Processing...")
def test_update_task_without_message(self):
"""Test updating task without message."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.update_task("inbox", 75)
mock_dashboard.update_task.assert_called_once_with("inbox", 75, "")
def test_complete_task(self):
"""Test completing a task."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.complete_task("inbox", "Done!")
mock_dashboard.complete_task.assert_called_once_with("inbox", "Done!")
def test_complete_task_no_message(self):
"""Test completing a task without a message."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.complete_task("inbox")
mock_dashboard.complete_task.assert_called_once_with("inbox", "")
def test_error_task(self):
"""Test marking a task as failed."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.error_task("inbox", "Connection failed")
mock_dashboard.error_task.assert_called_once_with("inbox", "Connection failed")
def test_skip_task(self):
"""Test skipping a task."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.skip_task("sweep", "Not needed")
mock_dashboard.skip_task.assert_called_once_with("sweep", "Not needed")
def test_skip_task_no_reason(self):
"""Test skipping a task without a reason."""
mock_dashboard = MagicMock()
tracker = SyncProgressTracker(mock_dashboard)
tracker.skip_task("sweep")
mock_dashboard.skip_task.assert_called_once_with("sweep", "")
class TestTaskListItem:
"""Tests for the TaskListItem class."""
def test_init(self):
"""Test TaskListItem initialization."""
item = TaskListItem("inbox", "Inbox Sync")
assert item.task_id == "inbox"
assert item.task_name == "Inbox Sync"
assert item.status == TaskStatus.PENDING
assert item.progress == 0
assert item.total == 100
def test_get_status_icon_pending(self):
"""Test status icon for pending."""
item = TaskListItem("inbox", "Inbox Sync")
assert item._get_status_icon() == ""
def test_get_status_icon_running(self):
"""Test status icon for running (animated spinner)."""
from src.cli.sync_dashboard import SPINNER_FRAMES
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.RUNNING
# Running uses spinner frames, starts at frame 0
assert item._get_status_icon() == SPINNER_FRAMES[0]
def test_get_status_icon_completed(self):
"""Test status icon for completed."""
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.COMPLETED
assert item._get_status_icon() == ""
def test_get_status_icon_error(self):
"""Test status icon for error."""
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.ERROR
assert item._get_status_icon() == ""
def test_get_status_color_pending(self):
"""Test status color for pending."""
item = TaskListItem("inbox", "Inbox Sync")
assert item._get_status_color() == "dim"
def test_get_status_color_running(self):
"""Test status color for running."""
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.RUNNING
assert item._get_status_color() == "cyan"
def test_get_status_color_completed(self):
"""Test status color for completed."""
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.COMPLETED
assert item._get_status_color() == "bright_white"
def test_get_status_color_error(self):
"""Test status color for error."""
item = TaskListItem("inbox", "Inbox Sync")
item.status = TaskStatus.ERROR
assert item._get_status_color() == "red"
class TestTaskStatus:
"""Tests for the TaskStatus constants."""
def test_status_values(self):
"""Test TaskStatus values."""
assert TaskStatus.PENDING == "pending"
assert TaskStatus.RUNNING == "running"
assert TaskStatus.COMPLETED == "completed"
assert TaskStatus.ERROR == "error"
class TestSyncDashboard:
"""Tests for the SyncDashboard class."""
def test_bindings_defined(self):
"""Test that key bindings are defined."""
assert len(SyncDashboard.BINDINGS) > 0
# Bindings use the Binding class which has a key attribute
binding_keys = [b.key for b in SyncDashboard.BINDINGS] # type: ignore
assert "q" in binding_keys
assert "r" in binding_keys
assert "s" in binding_keys # Sync now
assert "+" in binding_keys # Increase interval
assert "-" in binding_keys # Decrease interval
assert "ctrl+c" in binding_keys
assert "up" in binding_keys
assert "down" in binding_keys
def test_css_defined(self):
"""Test that CSS is defined."""
assert SyncDashboard.CSS is not None
assert len(SyncDashboard.CSS) > 0
assert ".dashboard" in SyncDashboard.CSS
assert ".sidebar" in SyncDashboard.CSS
assert ".main-panel" in SyncDashboard.CSS
def test_reactive_selected_task(self):
"""Test selected_task reactive attribute is defined."""
assert hasattr(SyncDashboard, "selected_task")
class TestGlobalInstances:
"""Tests for global dashboard instances."""
def test_get_dashboard_initial(self):
"""Test get_dashboard returns None initially."""
# Reset global state
import src.cli.sync_dashboard as dashboard_module
dashboard_module._dashboard_instance = None
result = get_dashboard()
assert result is None
def test_get_progress_tracker_initial(self):
"""Test get_progress_tracker returns None initially."""
# Reset global state
import src.cli.sync_dashboard as dashboard_module
dashboard_module._progress_tracker = None
result = get_progress_tracker()
assert result is None