from __future__ import annotations import os from typing import Any os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") import pytest from PySide6.QtWidgets import QApplication, QWidget from doctor_workstation.ui import shell as shell_module from doctor_workstation.ui.shell import NavigationItem, ShellWindow class _ShellPageDouble(QWidget): def __init__( self, _repository: Any, *, permissions: Any, current_user: Any, ) -> None: super().__init__() self.permissions = permissions self.current_user = current_user self.refresh_count = 0 def refresh(self) -> None: self.refresh_count += 1 @pytest.fixture(scope="module") def application() -> QApplication: return QApplication.instance() or QApplication([]) @pytest.fixture def shell_window( application: QApplication, monkeypatch: pytest.MonkeyPatch, ) -> ShellWindow: navigation = [ NavigationItem(key, title, glyph, _ShellPageDouble, (permission,)) for key, title, glyph, permission in ( ("reception", "接诊台", "◎", "doctor.appointment/lists"), ("appointments", "挂号列表", "号", "doctor.appointment/lists"), ("prescription_library", "我的处方库", "方", "tcm.prescriptionLibrary/lists"), ("prescriptions", "已开处方", "笺", "tcm.prescription/lists"), ("patients", "我的患者", "患", "firstvisit.myPatient/lists"), ("consultations", "问诊列表", "询", "tcm.diagnosis/lists"), ) ] monkeypatch.setattr( shell_module, "_resolve_navigation", lambda _menu, _permissions, *, demo_mode: [(item, item.title) for item in navigation], ) window = ShellWindow( object(), { "user": {"name": "陈医生", "department_name": "中医门诊", "role_ids": [1]}, "demo_mode": True, }, permissions={item.permissions[0] for item in navigation}, ) window.show() application.processEvents() yield window window.close() application.processEvents() def test_shell_matches_admin_geometry_at_both_acceptance_sizes( application: QApplication, shell_window: ShellWindow, ) -> None: for width, height in ((1024, 640), (1440, 900)): shell_window.resize(width, height) application.processEvents() assert shell_window.sidebar.width() == 208 assert shell_window.topbar.height() == 58 assert shell_window.tabs_host.height() == 42 assert shell_window.workspace.width() == width - 208 assert shell_window.stack.width() == width - 208 assert shell_window.stack.height() == height - 100 assert shell_window.stack.geometry().right() < shell_window.workspace.width() assert shell_window.stack.geometry().bottom() < shell_window.workspace.height() image = shell_window.grab().toImage() assert image.pixelColor(20, 300).name().lower() == "#ffffff" assert image.pixelColor(500, 10).name().lower() == "#ffffff" assert image.pixelColor(220, 110).name().lower() == "#f5f7fb" def test_every_visible_page_navigates_and_visited_tabs_track_active_page( shell_window: ShellWindow, ) -> None: changed: list[str] = [] shell_window.page_changed.connect(changed.append) for key in ( "reception", "appointments", "prescription_library", "prescriptions", "patients", "consultations", ): assert shell_window.navigate(key) assert shell_window.stack.currentWidget() is shell_window.pages[key] assert shell_window.nav_buttons[key].isChecked() assert shell_window.tab_bar.tabData(shell_window.tab_bar.currentIndex()) == key assert shell_window.visited_tab_keys() == ( "reception", "appointments", "prescription_library", "prescriptions", "patients", "consultations", ) assert changed[-6:] == [ "reception", "appointments", "prescription_library", "prescriptions", "patients", "consultations", ] def test_non_fixed_tabs_close_and_active_close_renavigates( shell_window: ShellWindow, ) -> None: for key in ("patients", "consultations"): assert shell_window.navigate(key) assert not shell_window.close_tab("reception") assert shell_window.close_tab("patients") assert "patients" not in shell_window.visited_tab_keys() assert shell_window.tab_bar.tabData(shell_window.tab_bar.currentIndex()) == "consultations" assert shell_window.close_current_tab() assert shell_window.tab_bar.tabData(shell_window.tab_bar.currentIndex()) == "reception" assert shell_window.stack.currentWidget() is shell_window.pages["reception"] assert shell_window.nav_buttons["reception"].isChecked() shell_window.close_all_tabs() assert shell_window.visited_tab_keys() == ("reception",) assert shell_window.stack.currentWidget() is shell_window.pages["reception"] def test_sidebar_collapse_preserves_active_navigation(shell_window: ShellWindow) -> None: assert shell_window.navigate("consultations") shell_window.toggle_sidebar() assert shell_window.sidebar.width() == 72 assert shell_window.nav_buttons["consultations"].text() == "" assert shell_window.nav_buttons["consultations"].isChecked() shell_window.toggle_sidebar() assert shell_window.sidebar.width() == 208 assert shell_window.nav_buttons["consultations"].text().endswith("问诊列表") assert shell_window.nav_buttons["consultations"].isChecked() def test_shell_directional_controls_have_no_unicode_arrow_text( shell_window: ShellWindow, ) -> None: assert shell_window.fold_button.text() == "" assert shell_window.refresh_button.text() == "" assert shell_window.fullscreen_button.text() == "" assert shell_window.tabs_menu_button.text() == "" assert all( arrow not in button.text() for button in shell_window.findChildren(QWidget) if hasattr(button, "text") and callable(button.text) for arrow in ("←", "→", "↑", "↓", "▲", "▼", "▴", "▾") )