EU-Utility/tests/unit/test_core_services.py

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