""" Widget System Tests Tests for the widget registry and floating widgets including: - Widget registration - Widget creation - Positioning and resizing - Opacity control - Widget lifecycle """ class WidgetSystemTests: """Test suite for widget system.""" name = "Widget System" icon = "๐ŸŽจ" description = "Tests widget creation, positioning, resizing, opacity, and lifecycle" def __init__(self): self.tests = { 'registry_initialization': self.test_registry_initialization, 'widget_registration': self.test_widget_registration, 'widget_creation': self.test_widget_creation, 'widget_lookup': self.test_widget_lookup, 'widget_by_plugin': self.test_widget_by_plugin, 'widget_unregister': self.test_widget_unregister, 'widget_clear': self.test_widget_clear, 'widget_info_structure': self.test_widget_info_structure, 'overlay_widget_creation': self.test_overlay_widget_creation, 'widget_positioning': self.test_widget_positioning, } def test_registry_initialization(self) -> dict: """Test widget registry initialization.""" try: from core.widget_registry import WidgetRegistry, get_widget_registry # Test singleton pattern reg1 = get_widget_registry() reg2 = get_widget_registry() if reg1 is not reg2: return { 'passed': False, 'message': "WidgetRegistry singleton not working correctly", 'severity': 'error' } # Test that registry has _widgets dict if not hasattr(reg1, '_widgets'): return { 'passed': False, 'message': "Registry missing _widgets dictionary", 'severity': 'error' } return { 'passed': True, 'message': "WidgetRegistry singleton working correctly", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error initializing registry: {e}", 'severity': 'error' } def test_widget_registration(self) -> dict: """Test widget registration.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel registry = get_widget_registry() # Test registration test_widget_id = "_test_widget_123" def create_test_widget(): return QLabel("Test") registry.register_widget( widget_id=test_widget_id, name="Test Widget", description="A test widget", icon="๐Ÿงช", creator=create_test_widget, plugin_id="test_plugin" ) # Verify registration if test_widget_id not in registry._widgets: return { 'passed': False, 'message': "Widget not found after registration", 'severity': 'error' } # Cleanup registry.unregister_widget(test_widget_id) return { 'passed': True, 'message': "Widget registration working", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error registering widget: {e}", 'severity': 'error' } def test_widget_creation(self) -> dict: """Test widget creation via registry.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel, QWidget registry = get_widget_registry() test_widget_id = "_test_creation_123" def create_widget(): return QLabel("Test Widget") registry.register_widget( widget_id=test_widget_id, name="Creation Test", description="Testing widget creation", icon="๐Ÿ”จ", creator=create_widget, plugin_id="test" ) # Test creation widget = registry.create_widget(test_widget_id) if widget is None: registry.unregister_widget(test_widget_id) return { 'passed': False, 'message': "create_widget returned None", 'severity': 'error' } if not isinstance(widget, QWidget): registry.unregister_widget(test_widget_id) return { 'passed': False, 'message': "Created widget is not a QWidget", 'severity': 'error' } # Cleanup registry.unregister_widget(test_widget_id) return { 'passed': True, 'message': "Widget creation working correctly", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error creating widget: {e}", 'severity': 'error' } def test_widget_lookup(self) -> dict: """Test widget lookup by ID.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel registry = get_widget_registry() test_id = "_test_lookup_123" registry.register_widget( widget_id=test_id, name="Lookup Test", description="Testing lookup", icon="๐Ÿ”", creator=lambda: QLabel("Test"), plugin_id="test" ) # Test get_widget info = registry.get_widget(test_id) if info is None: registry.unregister_widget(test_id) return { 'passed': False, 'message': "get_widget returned None for existing widget", 'severity': 'error' } if info.id != test_id: registry.unregister_widget(test_id) return { 'passed': False, 'message': f"Widget ID mismatch: expected {test_id}, got {info.id}", 'severity': 'error' } # Test non-existent widget non_existent = registry.get_widget("_non_existent_widget_999") if non_existent is not None: registry.unregister_widget(test_id) return { 'passed': False, 'message': "get_widget should return None for non-existent widgets", 'severity': 'warning' } registry.unregister_widget(test_id) return { 'passed': True, 'message': "Widget lookup working correctly", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error looking up widget: {e}", 'severity': 'error' } def test_widget_by_plugin(self) -> dict: """Test getting widgets by plugin ID.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel registry = get_widget_registry() test_plugin_id = "_test_plugin_456" # Register multiple widgets for same plugin for i in range(3): registry.register_widget( widget_id=f"_test_wp_{i}", name=f"Widget {i}", description=f"Test widget {i}", icon="๐Ÿ“ฆ", creator=lambda: QLabel("Test"), plugin_id=test_plugin_id ) # Get widgets by plugin widgets = registry.get_widgets_by_plugin(test_plugin_id) if len(widgets) != 3: # Cleanup for i in range(3): registry.unregister_widget(f"_test_wp_{i}") return { 'passed': False, 'message': f"Expected 3 widgets, got {len(widgets)}", 'severity': 'error' } # Cleanup for i in range(3): registry.unregister_widget(f"_test_wp_{i}") return { 'passed': True, 'message': f"get_widgets_by_plugin returned {len(widgets)} widgets", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error getting widgets by plugin: {e}", 'severity': 'error' } def test_widget_unregister(self) -> dict: """Test widget unregistration.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel registry = get_widget_registry() test_id = "_test_unregister_123" registry.register_widget( widget_id=test_id, name="Unregister Test", description="Testing unregistration", icon="๐Ÿ—‘๏ธ", creator=lambda: QLabel("Test"), plugin_id="test" ) # Verify registration if test_id not in registry._widgets: return { 'passed': False, 'message': "Widget not registered", 'severity': 'error' } # Unregister registry.unregister_widget(test_id) # Verify unregistration if test_id in registry._widgets: return { 'passed': False, 'message': "Widget still in registry after unregister", 'severity': 'error' } # Verify get_widget returns None info = registry.get_widget(test_id) if info is not None: return { 'passed': False, 'message': "get_widget returns widget after unregister", 'severity': 'error' } return { 'passed': True, 'message': "Widget unregistration working", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error unregistering widget: {e}", 'severity': 'error' } def test_widget_clear(self) -> dict: """Test clearing all widgets.""" try: from core.widget_registry import get_widget_registry from PyQt6.QtWidgets import QLabel registry = get_widget_registry() # Register some widgets for i in range(5): registry.register_widget( widget_id=f"_test_clear_{i}", name=f"Clear Test {i}", description="Testing clear", icon="๐Ÿงน", creator=lambda: QLabel("Test"), plugin_id="test" ) # Clear registry.clear() # Verify if len(registry._widgets) != 0: return { 'passed': False, 'message': f"Registry not empty after clear: {len(registry._widgets)} widgets", 'severity': 'error' } all_widgets = registry.get_all_widgets() if len(all_widgets) != 0: return { 'passed': False, 'message': f"get_all_widgets not empty after clear", 'severity': 'error' } return { 'passed': True, 'message': "Registry clear working", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error clearing widgets: {e}", 'severity': 'error' } def test_widget_info_structure(self) -> dict: """Test WidgetInfo dataclass structure.""" try: from core.widget_registry import WidgetInfo # Check required fields required_fields = ['id', 'name', 'description', 'icon', 'creator', 'plugin_id'] # Create a test WidgetInfo def dummy_creator(): return None info = WidgetInfo( id="test", name="Test", description="Test description", icon="๐Ÿงช", creator=dummy_creator, plugin_id="test_plugin" ) missing = [] for field in required_fields: if not hasattr(info, field): missing.append(field) if missing: return { 'passed': False, 'message': f"WidgetInfo missing fields: {missing}", 'severity': 'error' } return { 'passed': True, 'message': f"WidgetInfo structure correct with {len(required_fields)} fields", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error checking WidgetInfo: {e}", 'severity': 'error' } def test_overlay_widget_creation(self) -> dict: """Test widget creation from overlay.""" try: from core.overlay_window import OverlayWindow issues = [] recommendations = [] # Check _add_registered_widget method if not hasattr(OverlayWindow, '_add_registered_widget'): issues.append("_add_registered_widget method missing") # Check widget storage if not hasattr(OverlayWindow, '_active_widgets'): recommendations.append("Consider adding _active_widgets list to prevent GC") # Check widgets tab if not hasattr(OverlayWindow, '_create_widgets_tab'): issues.append("_create_widgets_tab method missing") if not hasattr(OverlayWindow, '_refresh_widgets_tab'): issues.append("_refresh_widgets_tab method missing") if issues: return { 'passed': False, 'message': "; ".join(issues), 'severity': 'error', 'recommendation': recommendations[0] if recommendations else None } return { 'passed': True, 'message': "Overlay widget creation present", 'severity': 'info' } except Exception as e: return { 'passed': False, 'message': f"Error checking overlay widget creation: {e}", 'severity': 'error' } def test_widget_positioning(self) -> dict: """Test widget positioning features.""" try: from core.overlay_window import OverlayWindow from core.widget_system import WidgetConfig issues = [] recommendations = [] # Check widget config if 'WidgetConfig' in dir(): config = WidgetConfig() if not hasattr(config, 'x') or not hasattr(config, 'y'): issues.append("WidgetConfig missing position fields") else: recommendations.append("Consider adding WidgetConfig for widget settings") # Check if widgets can be positioned # In _add_registered_widget, widgets are positioned at screen center import inspect if hasattr(OverlayWindow, '_add_registered_widget'): source = inspect.getsource(OverlayWindow._add_registered_widget) if 'move(' not in source: recommendations.append("Consider allowing custom widget positions") if issues: return { 'passed': False, 'message': "; ".join(issues), 'severity': 'warning' } return { 'passed': True, 'message': "Widget positioning features present", 'severity': 'info', 'recommendation': recommendations[0] if recommendations else None } except Exception as e: return { 'passed': False, 'message': f"Error checking widget positioning: {e}", 'severity': 'error' }