""" Comprehensive test suite for EU-Utility Run with: pytest tests/ -v """ import pytest import sys import os # Add project to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) class TestCoreServices: """Test suite for core services.""" def test_event_bus_singleton(self): """Test EventBus is singleton.""" from core.event_bus import get_event_bus bus1 = get_event_bus() bus2 = get_event_bus() assert bus1 is bus2 def test_event_publish_subscribe(self): """Test event publishing and subscribing.""" from core.event_bus import get_event_bus, SkillGainEvent bus = get_event_bus() received = [] def handler(event): received.append(event) sub_id = bus.subscribe_typed(SkillGainEvent, handler) event = SkillGainEvent(skill_name="Rifle", skill_value=25.0, gain_amount=0.01) bus.publish(event) # Give async time to process import time time.sleep(0.1) assert len(received) == 1 assert received[0].skill_name == "Rifle" bus.unsubscribe(sub_id) def test_nexus_api_singleton(self): """Test NexusAPI is singleton.""" from core.nexus_api import get_nexus_api api1 = get_nexus_api() api2 = get_nexus_api() assert api1 is api2 def test_data_store_operations(self): """Test DataStore operations.""" from core.data_store import get_data_store store = get_data_store() # Test save and load store.save("test_plugin", "test_key", {"value": 42}) data = store.load("test_plugin", "test_key", None) assert data == {"value": 42} # Test delete store.delete("test_plugin", "test_key") data = store.load("test_plugin", "test_key", None) assert data is None class TestPluginAPI: """Test suite for PluginAPI.""" def test_plugin_api_singleton(self): """Test PluginAPI is singleton.""" from core.plugin_api import get_api api1 = get_api() api2 = get_api() assert api1 is api2 def test_api_registration(self): """Test API endpoint registration.""" from core.plugin_api import get_api, APIEndpoint, APIType api = get_api() def test_handler(): return "test" endpoint = APIEndpoint( name="test_api", api_type=APIType.CUSTOM, description="Test API", handler=test_handler, plugin_id="test_plugin", version="1.0.0" ) result = api.register_api(endpoint) assert result is True # Cleanup api.unregister_api("test_plugin", "test_api") class TestSecurity: """Test suite for security features.""" def test_path_traversal_protection(self): """Test path traversal is blocked.""" from core.security_utils import validate_path # Valid path assert validate_path("/safe/path/file.txt", "/safe/path") is True # Path traversal attempt assert validate_path("/safe/path/../../../etc/passwd", "/safe/path") is False # Null byte injection assert validate_path("/safe/path/file.txt\x00.jpg", "/safe/path") is False def test_input_sanitization(self): """Test input sanitization.""" from core.security_utils import sanitize_input # Script tag removal assert "") # SQL injection prevention assert "'" not in sanitize_input("'; DROP TABLE users; --") class TestThemeManager: """Test suite for theme system.""" def test_theme_manager_singleton(self): """Test ThemeManager is singleton.""" from core.theme_manager import theme_manager from core.theme_manager import ThemeManager tm1 = ThemeManager() tm2 = ThemeManager() assert tm1 is tm2 def test_theme_getters(self): """Test theme retrieval.""" from core.theme_manager import theme_manager dark_theme = theme_manager.get_theme('dark') assert 'bg_primary' in dark_theme assert 'accent' in dark_theme light_theme = theme_manager.get_theme('light') assert light_theme['bg_primary'] != dark_theme['bg_primary'] def test_stylesheet_generation(self): """Test QSS stylesheet generation.""" from core.theme_manager import theme_manager stylesheet = theme_manager.get_stylesheet('dark') assert 'background-color' in stylesheet assert 'color' in stylesheet class TestUtilities: """Test suite for utility functions.""" def test_ped_formatting(self): """Test PED formatting.""" from plugins.base_plugin import BasePlugin class TestPlugin(BasePlugin): name = "Test" version = "1.0.0" author = "Test" description = "Test" plugin = TestPlugin(None, {}) assert "PED" in plugin.format_ped(123.45) assert "PEC" in plugin.format_pec(50) def test_dpp_calculation(self): """Test DPP calculation.""" from plugins.base_plugin import BasePlugin class TestPlugin(BasePlugin): name = "Test" version = "1.0.0" author = "Test" description = "Test" plugin = TestPlugin(None, {}) # DPP = damage / ((ammo * 0.01 + decay) / 100) dpp = plugin.calculate_dpp(50, 100, 2.5) assert dpp > 0 def test_markup_calculation(self): """Test markup calculation.""" from plugins.base_plugin import BasePlugin class TestPlugin(BasePlugin): name = "Test" version = "1.0.0" author = "Test" description = "Test" plugin = TestPlugin(None, {}) markup = plugin.calculate_markup(150, 100) assert markup == 150.0 # 150% markup class TestPluginLoading: """Test suite for plugin loading.""" def test_plugin_discovery(self): """Test plugin discovery.""" import os plugins_dir = os.path.join(os.path.dirname(__file__), '..', 'plugins') if os.path.exists(plugins_dir): plugin_dirs = [d for d in os.listdir(plugins_dir) if os.path.isdir(os.path.join(plugins_dir, d)) and not d.startswith('_')] # Should have multiple plugins assert len(plugin_dirs) > 5 def test_plugin_structure(self): """Test plugin directory structure.""" import os plugins_dir = os.path.join(os.path.dirname(__file__), '..', 'plugins') if os.path.exists(plugins_dir): for plugin_name in os.listdir(plugins_dir): plugin_path = os.path.join(plugins_dir, plugin_name) if os.path.isdir(plugin_path) and not plugin_name.startswith('_'): # Check for required files init_file = os.path.join(plugin_path, '__init__.py') plugin_file = os.path.join(plugin_path, 'plugin.py') if os.path.exists(plugin_file): assert os.path.exists(init_file) or os.path.exists(plugin_file) # Integration tests @pytest.mark.integration def test_full_plugin_lifecycle(): """Integration test: full plugin lifecycle.""" from plugins.base_plugin import BasePlugin lifecycle_events = [] class LifecyclePlugin(BasePlugin): name = "LifecycleTest" version = "1.0.0" author = "Test" description = "Test lifecycle" def initialize(self): lifecycle_events.append('initialize') def get_ui(self): lifecycle_events.append('get_ui') return None def on_show(self): lifecycle_events.append('on_show') def on_hide(self): lifecycle_events.append('on_hide') def shutdown(self): lifecycle_events.append('shutdown') # Test lifecycle plugin = LifecyclePlugin(None, {}) plugin.initialize() plugin.get_ui() plugin.on_show() plugin.on_hide() plugin.shutdown() assert 'initialize' in lifecycle_events assert 'shutdown' in lifecycle_events if __name__ == '__main__': pytest.main([__file__, '-v'])