446 lines
13 KiB
Python
446 lines
13 KiB
Python
"""
|
|
Unit Tests - Core Services
|
|
==========================
|
|
|
|
Tests for Event Bus, Data Store, Settings, and other core services.
|
|
"""
|
|
|
|
import pytest
|
|
import json
|
|
import time
|
|
from unittest.mock import Mock, patch
|
|
|
|
|
|
class TestEventBus:
|
|
"""Test Event Bus functionality."""
|
|
|
|
def test_event_bus_initialization(self, event_bus):
|
|
"""Test event bus initialization."""
|
|
assert event_bus.subscribers == {}
|
|
assert event_bus.event_history == []
|
|
|
|
def test_subscribe_to_event(self, event_bus):
|
|
"""Test subscribing to an event."""
|
|
callback = Mock()
|
|
|
|
sub_id = event_bus.subscribe("test_event", callback)
|
|
|
|
assert sub_id != ""
|
|
assert "test_event" in event_bus.subscribers
|
|
assert len(event_bus.subscribers["test_event"]) == 1
|
|
|
|
def test_unsubscribe_from_event(self, event_bus):
|
|
"""Test unsubscribing from an event."""
|
|
callback = Mock()
|
|
sub_id = event_bus.subscribe("test_event", callback)
|
|
|
|
result = event_bus.unsubscribe(sub_id)
|
|
|
|
assert result is True
|
|
assert len(event_bus.subscribers.get("test_event", [])) == 0
|
|
|
|
def test_publish_event(self, event_bus):
|
|
"""Test publishing an event."""
|
|
callback = Mock()
|
|
event_bus.subscribe("test_event", callback)
|
|
|
|
event_bus.publish("test_event", {"key": "value"})
|
|
|
|
callback.assert_called_once()
|
|
args = callback.call_args[0][0]
|
|
assert args.data == {"key": "value"}
|
|
|
|
def test_publish_event_no_subscribers(self, event_bus):
|
|
"""Test publishing event with no subscribers."""
|
|
# Should not raise exception
|
|
event_bus.publish("test_event", {"key": "value"})
|
|
|
|
def test_multiple_subscribers(self, event_bus):
|
|
"""Test multiple subscribers for same event."""
|
|
callback1 = Mock()
|
|
callback2 = Mock()
|
|
|
|
event_bus.subscribe("test_event", callback1)
|
|
event_bus.subscribe("test_event", callback2)
|
|
|
|
event_bus.publish("test_event", "data")
|
|
|
|
callback1.assert_called_once()
|
|
callback2.assert_called_once()
|
|
|
|
def test_event_history(self, event_bus):
|
|
"""Test event history tracking."""
|
|
event_bus.subscribe("test_event", Mock())
|
|
|
|
event_bus.publish("test_event", "data1")
|
|
event_bus.publish("test_event", "data2")
|
|
|
|
assert len(event_bus.event_history) == 2
|
|
|
|
def test_get_event_history(self, event_bus):
|
|
"""Test getting event history."""
|
|
event_bus.subscribe("test_event", Mock())
|
|
event_bus.publish("test_event", "data")
|
|
|
|
history = event_bus.get_event_history("test_event")
|
|
|
|
assert len(history) == 1
|
|
|
|
def test_clear_event_history(self, event_bus):
|
|
"""Test clearing event history."""
|
|
event_bus.subscribe("test_event", Mock())
|
|
event_bus.publish("test_event", "data")
|
|
|
|
event_bus.clear_history()
|
|
|
|
assert len(event_bus.event_history) == 0
|
|
|
|
|
|
class TestDataStore:
|
|
"""Test Data Store functionality."""
|
|
|
|
def test_data_store_initialization(self, temp_dir):
|
|
"""Test data store initialization."""
|
|
from core.data_store import DataStore
|
|
|
|
store_path = temp_dir / "test_store.json"
|
|
store = DataStore(str(store_path))
|
|
|
|
assert store.file_path == str(store_path)
|
|
assert store._data == {}
|
|
|
|
def test_data_store_set_get(self, data_store):
|
|
"""Test setting and getting data."""
|
|
data_store.set("key1", "value1")
|
|
|
|
result = data_store.get("key1")
|
|
|
|
assert result == "value1"
|
|
|
|
def test_data_store_get_default(self, data_store):
|
|
"""Test getting data with default value."""
|
|
result = data_store.get("nonexistent", default="default")
|
|
|
|
assert result == "default"
|
|
|
|
def test_data_store_delete(self, data_store):
|
|
"""Test deleting data."""
|
|
data_store.set("key1", "value1")
|
|
data_store.delete("key1")
|
|
|
|
result = data_store.get("key1")
|
|
|
|
assert result is None
|
|
|
|
def test_data_store_has_key(self, data_store):
|
|
"""Test checking if key exists."""
|
|
data_store.set("key1", "value1")
|
|
|
|
assert data_store.has("key1") is True
|
|
assert data_store.has("key2") is False
|
|
|
|
def test_data_store_persistence(self, temp_dir):
|
|
"""Test data persistence to file."""
|
|
from core.data_store import DataStore
|
|
|
|
store_path = temp_dir / "test_store.json"
|
|
|
|
# Create and save
|
|
store1 = DataStore(str(store_path))
|
|
store1.set("key1", "value1")
|
|
store1.save()
|
|
|
|
# Load in new instance
|
|
store2 = DataStore(str(store_path))
|
|
|
|
assert store2.get("key1") == "value1"
|
|
|
|
def test_data_store_get_all(self, data_store):
|
|
"""Test getting all data."""
|
|
data_store.set("key1", "value1")
|
|
data_store.set("key2", "value2")
|
|
|
|
all_data = data_store.get_all()
|
|
|
|
assert len(all_data) == 2
|
|
assert all_data["key1"] == "value1"
|
|
assert all_data["key2"] == "value2"
|
|
|
|
def test_data_store_clear(self, data_store):
|
|
"""Test clearing all data."""
|
|
data_store.set("key1", "value1")
|
|
data_store.set("key2", "value2")
|
|
|
|
data_store.clear()
|
|
|
|
assert data_store.get_all() == {}
|
|
|
|
def test_data_store_nested_data(self, data_store):
|
|
"""Test storing nested data structures."""
|
|
nested = {
|
|
"level1": {
|
|
"level2": {
|
|
"value": "deep"
|
|
}
|
|
},
|
|
"list": [1, 2, 3]
|
|
}
|
|
|
|
data_store.set("nested", nested)
|
|
result = data_store.get("nested")
|
|
|
|
assert result["level1"]["level2"]["value"] == "deep"
|
|
assert result["list"] == [1, 2, 3]
|
|
|
|
|
|
class TestSettings:
|
|
"""Test Settings functionality."""
|
|
|
|
def test_settings_initialization(self, temp_dir):
|
|
"""Test settings initialization."""
|
|
from core.settings import Settings
|
|
|
|
config_path = temp_dir / "config" / "settings.json"
|
|
config_path.parent.mkdir(parents=True)
|
|
|
|
settings = Settings(str(config_path))
|
|
|
|
assert settings.config_path == str(config_path)
|
|
assert settings._config == {}
|
|
|
|
def test_settings_get_set(self, temp_dir):
|
|
"""Test getting and setting configuration values."""
|
|
from core.settings import Settings
|
|
|
|
config_path = temp_dir / "config" / "settings.json"
|
|
config_path.parent.mkdir(parents=True)
|
|
|
|
settings = Settings(str(config_path))
|
|
|
|
settings.set("section.key", "value")
|
|
result = settings.get("section.key")
|
|
|
|
assert result == "value"
|
|
|
|
def test_settings_get_default(self, temp_dir):
|
|
"""Test getting settings with default."""
|
|
from core.settings import Settings
|
|
|
|
config_path = temp_dir / "config" / "settings.json"
|
|
config_path.parent.mkdir(parents=True)
|
|
|
|
settings = Settings(str(config_path))
|
|
|
|
result = settings.get("nonexistent", default="default")
|
|
|
|
assert result == "default"
|
|
|
|
def test_settings_persistence(self, temp_dir):
|
|
"""Test settings persistence."""
|
|
from core.settings import Settings
|
|
|
|
config_path = temp_dir / "config" / "settings.json"
|
|
config_path.parent.mkdir(parents=True)
|
|
|
|
settings1 = Settings(str(config_path))
|
|
settings1.set("test.value", 123)
|
|
settings1.save()
|
|
|
|
settings2 = Settings(str(config_path))
|
|
|
|
assert settings2.get("test.value") == 123
|
|
|
|
def test_settings_has(self, temp_dir):
|
|
"""Test checking if setting exists."""
|
|
from core.settings import Settings
|
|
|
|
config_path = temp_dir / "config" / "settings.json"
|
|
config_path.parent.mkdir(parents=True)
|
|
|
|
settings = Settings(str(config_path))
|
|
settings.set("test.value", 123)
|
|
|
|
assert settings.has("test.value") is True
|
|
assert settings.has("test.nonexistent") is False
|
|
|
|
|
|
class TestLogger:
|
|
"""Test Logger functionality."""
|
|
|
|
def test_logger_initialization(self):
|
|
"""Test logger initialization."""
|
|
from core.logger import get_logger
|
|
|
|
logger = get_logger("test")
|
|
|
|
assert logger.name == "test"
|
|
|
|
def test_logger_levels(self):
|
|
"""Test logger levels."""
|
|
from core.logger import get_logger
|
|
import logging
|
|
|
|
logger = get_logger("test_levels")
|
|
|
|
# Ensure logger can log at all levels without errors
|
|
logger.debug("Debug message")
|
|
logger.info("Info message")
|
|
logger.warning("Warning message")
|
|
logger.error("Error message")
|
|
|
|
|
|
class TestHotkeyManager:
|
|
"""Test Hotkey Manager functionality."""
|
|
|
|
def test_hotkey_manager_initialization(self):
|
|
"""Test hotkey manager initialization."""
|
|
from core.hotkey_manager import HotkeyManager
|
|
|
|
hm = HotkeyManager()
|
|
|
|
assert hasattr(hm, 'hotkeys')
|
|
|
|
def test_register_hotkey(self):
|
|
"""Test registering a hotkey."""
|
|
from core.hotkey_manager import HotkeyManager
|
|
|
|
hm = HotkeyManager()
|
|
callback = Mock()
|
|
|
|
result = hm.register("ctrl+shift+t", callback, "test_action")
|
|
|
|
assert result is True
|
|
|
|
def test_unregister_hotkey(self):
|
|
"""Test unregistering a hotkey."""
|
|
from core.hotkey_manager import HotkeyManager
|
|
|
|
hm = HotkeyManager()
|
|
callback = Mock()
|
|
|
|
hm.register("ctrl+shift+t", callback, "test_action")
|
|
result = hm.unregister("test_action")
|
|
|
|
assert result is True
|
|
|
|
def test_get_all_hotkeys(self):
|
|
"""Test getting all registered hotkeys."""
|
|
from core.hotkey_manager import HotkeyManager
|
|
|
|
hm = HotkeyManager()
|
|
callback = Mock()
|
|
|
|
hm.register("ctrl+shift+a", callback, "action_a")
|
|
hm.register("ctrl+shift+b", callback, "action_b")
|
|
|
|
hotkeys = hm.get_all_hotkeys()
|
|
|
|
assert len(hotkeys) >= 2
|
|
|
|
|
|
class TestClipboard:
|
|
"""Test Clipboard functionality."""
|
|
|
|
def test_clipboard_copy_paste(self):
|
|
"""Test clipboard copy and paste."""
|
|
from core.clipboard import ClipboardManager
|
|
|
|
cm = ClipboardManager()
|
|
|
|
# Copy text
|
|
cm.copy("Test clipboard content")
|
|
|
|
# Paste text
|
|
result = cm.paste()
|
|
|
|
assert result == "Test clipboard content"
|
|
|
|
def test_clipboard_clear(self):
|
|
"""Test clipboard clear."""
|
|
from core.clipboard import ClipboardManager
|
|
|
|
cm = ClipboardManager()
|
|
|
|
cm.copy("Test")
|
|
cm.clear()
|
|
|
|
result = cm.paste()
|
|
|
|
assert result == ""
|
|
|
|
|
|
class TestNotifications:
|
|
"""Test Notification functionality."""
|
|
|
|
def test_notification_manager_initialization(self):
|
|
"""Test notification manager initialization."""
|
|
from core.notifications import NotificationManager
|
|
|
|
nm = NotificationManager()
|
|
|
|
assert nm is not None
|
|
|
|
def test_show_notification(self):
|
|
"""Test showing notification."""
|
|
from core.notifications import NotificationManager
|
|
|
|
nm = NotificationManager()
|
|
|
|
# Should not raise exception
|
|
nm.show("Test Title", "Test message", duration=1000)
|
|
|
|
|
|
class TestThemeManager:
|
|
"""Test Theme Manager functionality."""
|
|
|
|
def test_theme_initialization(self):
|
|
"""Test theme initialization."""
|
|
from core.theme_manager import ThemeManager
|
|
|
|
tm = ThemeManager()
|
|
|
|
assert tm.current_theme is not None
|
|
|
|
def test_get_color(self):
|
|
"""Test getting theme colors."""
|
|
from core.theme_manager import ThemeManager
|
|
|
|
tm = ThemeManager()
|
|
|
|
color = tm.get_color("primary")
|
|
|
|
assert color is not None
|
|
|
|
def test_set_theme(self):
|
|
"""Test setting theme."""
|
|
from core.theme_manager import ThemeManager
|
|
|
|
tm = ThemeManager()
|
|
|
|
tm.set_theme("dark")
|
|
|
|
assert tm.current_theme == "dark"
|
|
|
|
|
|
class TestPerformanceOptimizations:
|
|
"""Test Performance Optimization functionality."""
|
|
|
|
def test_cache_decorator(self):
|
|
"""Test cache decorator."""
|
|
from core.performance_optimizations import cached
|
|
|
|
call_count = 0
|
|
|
|
@cached(ttl_seconds=1)
|
|
def expensive_function(x):
|
|
nonlocal call_count
|
|
call_count += 1
|
|
return x * 2
|
|
|
|
result1 = expensive_function(5)
|
|
result2 = expensive_function(5)
|
|
|
|
assert result1 == 10
|
|
assert result2 == 10
|
|
assert call_count == 1 # Should only be called once due to caching
|