EU-Utility/tests/ui/test_ui_automation.py

420 lines
13 KiB
Python

"""
UI Automation Tests
===================
Automated UI tests using pytest-qt for Qt application testing.
"""
import pytest
from unittest.mock import Mock, patch
@pytest.mark.ui
class TestDashboardUI:
"""Test Dashboard UI components."""
def test_dashboard_opens(self, qtbot):
"""Test dashboard opens correctly."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.dashboard import Dashboard
app = QApplication.instance() or QApplication([])
dashboard = Dashboard()
qtbot.addWidget(dashboard)
dashboard.show()
qtbot.wait_for_window_shown(dashboard)
assert dashboard.isVisible()
def test_dashboard_widget_interaction(self, qtbot):
"""Test dashboard widget interaction."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.dashboard import Dashboard, PEDTrackerWidget
app = QApplication.instance() or QApplication([])
dashboard = Dashboard()
qtbot.addWidget(dashboard)
# Add widget
widget = PEDTrackerWidget()
dashboard.add_widget(widget)
assert widget in dashboard.widgets
# Update data
widget.update_data({"ped": 1500.00, "change": 50.00})
def test_dashboard_navigation_tabs(self, qtbot):
"""Test dashboard navigation between tabs."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
app = QApplication.instance() or QApplication([])
# Test that multiple views can be created
from core.ui.dashboard_view import DashboardView
from core.ui.settings_view import SettingsView
dashboard_view = DashboardView()
settings_view = SettingsView()
qtbot.addWidget(dashboard_view)
qtbot.addWidget(settings_view)
dashboard_view.show()
settings_view.show()
assert dashboard_view.isVisible()
assert settings_view.isVisible()
@pytest.mark.ui
class TestOverlayWindowUI:
"""Test Overlay Window UI components."""
def test_overlay_window_opens(self, qtbot):
"""Test overlay window opens correctly."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(None)
qtbot.addWidget(window)
window.show()
qtbot.wait_for_window_shown(window)
assert window.isVisible()
def test_overlay_toggle_visibility(self, qtbot):
"""Test overlay toggle visibility."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(None)
qtbot.addWidget(window)
# Show
window.show_overlay()
assert window.is_visible is True
# Hide
window.hide_overlay()
assert window.is_visible is False
# Toggle
window.toggle_overlay()
assert window.is_visible is True
def test_overlay_plugin_navigation(self, qtbot, mock_plugin_manager):
"""Test overlay plugin navigation."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QWidget
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
# Mock plugins with UI
mock_plugin1 = Mock()
mock_plugin1.name = "Plugin 1"
mock_ui1 = QWidget()
mock_plugin1.get_ui.return_value = mock_ui1
mock_plugin2 = Mock()
mock_plugin2.name = "Plugin 2"
mock_ui2 = QWidget()
mock_plugin2.get_ui.return_value = mock_ui2
mock_plugin_manager.get_all_plugins.return_value = {
"plugin1": mock_plugin1,
"plugin2": mock_plugin2
}
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(mock_plugin_manager)
qtbot.addWidget(window)
# Verify plugins loaded
assert len(window.sidebar_buttons) >= 0
@pytest.mark.ui
class TestActivityBarUI:
"""Test Activity Bar UI components."""
def test_activity_bar_opens(self, qtbot, mock_plugin_manager):
"""Test activity bar opens correctly."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.activity_bar import WindowsTaskbar
app = QApplication.instance() or QApplication([])
taskbar = WindowsTaskbar(mock_plugin_manager)
qtbot.addWidget(taskbar)
if taskbar.config.enabled:
assert taskbar.isVisible()
def test_activity_bar_search(self, qtbot, mock_plugin_manager):
"""Test activity bar search functionality."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.activity_bar import WindowsTaskbar
app = QApplication.instance() or QApplication([])
taskbar = WindowsTaskbar(mock_plugin_manager)
qtbot.addWidget(taskbar)
# Enter search text
qtbot.keyClicks(taskbar.search_box, "test search")
assert taskbar.search_box.text() == "test search"
def test_activity_bar_auto_hide(self, qtbot, mock_plugin_manager):
"""Test activity bar auto-hide behavior."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.activity_bar import WindowsTaskbar
app = QApplication.instance() or QApplication([])
taskbar = WindowsTaskbar(mock_plugin_manager)
qtbot.addWidget(taskbar)
# Verify auto-hide is configured
assert hasattr(taskbar, 'hide_timer')
assert taskbar.config.auto_hide is True
@pytest.mark.ui
class TestSettingsDialogUI:
"""Test Settings Dialog UI components."""
def test_settings_dialog_opens(self, qtbot):
"""Test settings dialog opens."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.activity_bar import TaskbarSettingsDialog, ActivityBarConfig
app = QApplication.instance() or QApplication([])
config = ActivityBarConfig()
dialog = TaskbarSettingsDialog(config)
qtbot.addWidget(dialog)
dialog.show()
assert dialog.isVisible()
def test_settings_dialog_save(self, qtbot):
"""Test settings dialog save."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.activity_bar import TaskbarSettingsDialog, ActivityBarConfig
app = QApplication.instance() or QApplication([])
config = ActivityBarConfig()
dialog = TaskbarSettingsDialog(config)
qtbot.addWidget(dialog)
# Change settings
dialog.autohide_cb.setChecked(False)
dialog.icon_size.setValue(40)
# Get config
new_config = dialog.get_config()
assert new_config.auto_hide is False
assert new_config.icon_size == 40
@pytest.mark.ui
class TestResponsiveUI:
"""Test responsive UI behavior."""
def test_window_resize_handling(self, qtbot):
"""Test window resize handling."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(None)
qtbot.addWidget(window)
# Test various sizes
window.resize(800, 600)
assert window.width() == 800
assert window.height() == 600
window.resize(1200, 800)
assert window.width() == 1200
assert window.height() == 800
def test_minimum_window_size(self, qtbot):
"""Test minimum window size enforcement."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(None)
assert window.minimumWidth() > 0
assert window.minimumHeight() > 0
def test_sidebar_responsiveness(self, qtbot):
"""Test sidebar responsiveness."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.overlay_window import OverlayWindow
app = QApplication.instance() or QApplication([])
with patch.object(OverlayWindow, '_setup_tray'):
window = OverlayWindow(None)
# Sidebar should have min/max constraints
assert window.sidebar.minimumWidth() > 0
assert window.sidebar.maximumWidth() > window.sidebar.minimumWidth()
@pytest.mark.ui
class TestThemeUI:
"""Test theme switching UI."""
def test_theme_toggle(self, qtbot):
"""Test theme toggle."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication
from core.eu_styles import EUTheme
app = QApplication.instance() or QApplication([])
# Get initial theme
initial_theme = EUTheme.current_theme
# Toggle theme
new_theme = "light" if EUTheme.is_dark() else "dark"
EUTheme.set_theme(new_theme)
assert EUTheme.current_theme == new_theme
def test_stylesheet_application(self, qtbot):
"""Test stylesheet application."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QWidget
from core.eu_styles import get_global_stylesheet
app = QApplication.instance() or QApplication([])
widget = QWidget()
qtbot.addWidget(widget)
stylesheet = get_global_stylesheet()
widget.setStyleSheet(stylesheet)
assert widget.styleSheet() != ""
@pytest.mark.ui
class TestAccessibilityUI:
"""Test accessibility features."""
def test_accessibility_names(self, qtbot):
"""Test accessibility names are set."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QPushButton
app = QApplication.instance() or QApplication([])
button = QPushButton("Test")
button.setAccessibleName("Test Button")
button.setAccessibleDescription("A test button")
qtbot.addWidget(button)
assert button.accessibleName() == "Test Button"
def test_keyboard_navigation(self, qtbot):
"""Test keyboard navigation."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
app = QApplication.instance() or QApplication([])
widget = QWidget()
layout = QVBoxLayout(widget)
btn1 = QPushButton("Button 1")
btn2 = QPushButton("Button 2")
layout.addWidget(btn1)
layout.addWidget(btn2)
qtbot.addWidget(widget)
widget.show()
# Tab navigation should work
btn1.setFocus()
assert btn1.hasFocus()
@pytest.mark.ui
class TestTrayIconUI:
"""Test system tray icon UI."""
def test_tray_icon_exists(self, qtbot):
"""Test tray icon exists."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QSystemTrayIcon
app = QApplication.instance() or QApplication([])
if not QSystemTrayIcon.isSystemTrayAvailable():
pytest.skip("System tray not available")
tray = QSystemTrayIcon()
qtbot.addWidget(tray)
tray.show()
assert tray.isVisible()
def test_tray_context_menu(self, qtbot):
"""Test tray context menu."""
pytest.importorskip("PyQt6")
from PyQt6.QtWidgets import QApplication, QSystemTrayIcon, QMenu
app = QApplication.instance() or QApplication([])
if not QSystemTrayIcon.isSystemTrayAvailable():
pytest.skip("System tray not available")
tray = QSystemTrayIcon()
menu = QMenu()
menu.addAction("Show")
menu.addAction("Quit")
tray.setContextMenu(menu)
assert tray.contextMenu() is not None