420 lines
13 KiB
Python
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
|