"""Shared fixtures for the customer app UI tests. The tests render real Qt widgets with the offscreen platform plugin, so they need no display and no camera hardware. A single ``QApplication`` is shared by the whole session (Qt forbids creating more than one). """ from __future__ import annotations import os import sys from pathlib import Path import pytest os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") if sys.platform == "win32" and "QT_QPA_FONTDIR" not in os.environ: _fonts = Path(os.environ.get("WINDIR", r"C:\Windows")) / "Fonts" if _fonts.is_dir(): os.environ["QT_QPA_FONTDIR"] = str(_fonts) # ``tools/ui_check.py`` owns the palette rules; importing it keeps one source of # truth between the pytest suite and the dependency-free checker. _TOOLS_DIR = Path(__file__).resolve().parents[1] / "tools" if _TOOLS_DIR.is_dir() and str(_TOOLS_DIR) not in sys.path: sys.path.insert(0, str(_TOOLS_DIR)) @pytest.fixture(scope="session") def qt_app(): from PyQt5.QtWidgets import QApplication app = QApplication.instance() or QApplication([]) yield app @pytest.fixture def make_window(qt_app, tmp_path, monkeypatch): """Build a ``CustomerMainWindow`` whose preference writes stay in tmp_path.""" from orisys_app_shared import prefs as prefs_pkg from orisys_app_shared import paths as paths_mod from orisys_customer.app_window import CustomerMainWindow prefs_file = tmp_path / "preference.json" monkeypatch.setattr(paths_mod, "preference_path", lambda: prefs_file) monkeypatch.setattr(prefs_pkg.store, "preference_path", lambda: prefs_file) default_prefs = { "language": "zh_CN", "theme": "dark", "sensor_type": "box", "source_mode": "camera", } created = [] def _make(**overrides): data = dict(default_prefs) data.update(overrides) window = CustomerMainWindow(prefs=data) created.append(window) return window yield _make for window in created: try: window.close() except Exception: pass def visible_descendants(widget): """Yield every visible descendant widget of ``widget``.""" for child in widget.findChildren(object): if not hasattr(child, "isVisible") or not hasattr(child, "geometry"): continue if child.isVisible(): yield child