更新
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from types import SimpleNamespace
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
import pytest
|
||||
from PySide6.QtCore import QPoint
|
||||
from PySide6.QtGui import QPalette
|
||||
from PySide6.QtWidgets import QApplication, QDialog, QLabel, QVBoxLayout, QWidget
|
||||
|
||||
from doctor_workstation.core import PermissionSet
|
||||
from doctor_workstation.ui import apply_theme
|
||||
from doctor_workstation.ui.appointment_drawer import APPOINTMENT_DRAWER_QSS, _SlotCard
|
||||
from doctor_workstation.ui.diagnosis_drawer import DIAGNOSIS_QSS, DiagnosisTabWidget
|
||||
from doctor_workstation.ui.dialogs import prescription_ai as ai_module
|
||||
from doctor_workstation.ui.dialogs.prescription import PrescriptionEditorDialog
|
||||
from doctor_workstation.ui.dialogs.prescription_ai import PrescriptionAiReportDialog
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def application() -> QApplication:
|
||||
app = QApplication.instance() or QApplication([])
|
||||
apply_theme(app)
|
||||
return app
|
||||
|
||||
|
||||
def settle(application: QApplication) -> None:
|
||||
for _ in range(10):
|
||||
application.processEvents()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("width", [600, 760, 860])
|
||||
def test_prescription_form_keeps_date_gender_and_controls_readable(
|
||||
application: QApplication, width: int
|
||||
) -> None:
|
||||
host = QWidget()
|
||||
host.resize(width, 640)
|
||||
host.show()
|
||||
editor = PrescriptionEditorDialog(
|
||||
SimpleNamespace(list_medicines=lambda **kwargs: {"lists": [], "count": 0}),
|
||||
{"diagnosis_id": 501, "patient_name": "林晓岚", "prescription_type": "浓缩水丸"},
|
||||
parent=host,
|
||||
)
|
||||
editor.show()
|
||||
settle(application)
|
||||
try:
|
||||
display = editor.date_edit._display
|
||||
assert display.width() >= display.fontMetrics().horizontalAdvance(display.text()) + 15
|
||||
for button in (editor.gender_male, editor.gender_female):
|
||||
assert button.width() >= button.sizeHint().width()
|
||||
controls = [editor.patient_name, editor.age, editor.date_edit, editor.prescription_type, editor.times_per_day]
|
||||
assert len({control.height() for control in controls}) == 1
|
||||
assert editor.body_content.width() == editor.body_scroll.viewport().width()
|
||||
assert editor.body_scroll.horizontalScrollBar().maximum() == 0
|
||||
footer_position = editor.footer.mapToGlobal(QPoint())
|
||||
editor.body_scroll.verticalScrollBar().setValue(editor.body_scroll.verticalScrollBar().maximum())
|
||||
settle(application)
|
||||
assert editor.footer.mapToGlobal(QPoint()) == footer_position
|
||||
assert editor.save_button.visibleRegion().boundingRect() == editor.save_button.rect()
|
||||
# Changing prescription type keeps its conditional fields reachable after reflow.
|
||||
editor.prescription_type.setCurrentText("饮片")
|
||||
settle(application)
|
||||
assert not editor._main_decoction_field.isHidden()
|
||||
assert editor._main_bag_field.isHidden()
|
||||
if width == 860:
|
||||
for resized_width in (600, 860):
|
||||
editor.resize(resized_width, 640)
|
||||
settle(application)
|
||||
assert display.width() >= display.fontMetrics().horizontalAdvance(display.text()) + 15
|
||||
assert editor._main_decoction_field.width() >= editor.need_decoction.minimumSizeHint().width() + 104
|
||||
finally:
|
||||
editor.close()
|
||||
host.close()
|
||||
|
||||
|
||||
def test_diagnosis_overflow_rail_leaves_selected_tab_underline_visible(application: QApplication) -> None:
|
||||
tabs = DiagnosisTabWidget()
|
||||
tabs.setObjectName("DiagnosisDrawerTabs")
|
||||
tabs.setStyleSheet(DIAGNOSIS_QSS)
|
||||
for title in ("病历", "医生备注", "日常记录", "处方", "业务订单", "视频录制回放", "聊天", "指派医助记录", "挂号记录"):
|
||||
tabs.addTab(QWidget(), title)
|
||||
tabs.resize(614, 480)
|
||||
tabs.show()
|
||||
settle(application)
|
||||
try:
|
||||
selected = tabs.tabBar().tabRect(tabs.currentIndex())
|
||||
selected.moveTopLeft(tabs.tabBar().pos() + selected.topLeft())
|
||||
assert tabs.tab_scrollbar.isVisible()
|
||||
assert not selected.intersects(tabs.tab_scrollbar.geometry())
|
||||
tabs.tab_scrollbar.setValue(tabs.count() - 1)
|
||||
assert tabs.currentIndex() == tabs.count() - 1
|
||||
finally:
|
||||
tabs.close()
|
||||
|
||||
|
||||
def test_appointment_slot_labels_follow_checked_and_disabled_states(application: QApplication) -> None:
|
||||
dialog = QDialog()
|
||||
dialog.setObjectName("AppointmentDrawerOverlay")
|
||||
dialog.setStyleSheet(APPOINTMENT_DRAWER_QSS)
|
||||
layout = QVBoxLayout(dialog)
|
||||
card = _SlotCard("09:00-09:30", "可约")
|
||||
card.setProperty("appointmentSlot", True)
|
||||
card.setProperty("availability", "available")
|
||||
card.setCheckable(True)
|
||||
layout.addWidget(card)
|
||||
dialog.show()
|
||||
settle(application)
|
||||
try:
|
||||
for checked, expected in ((True, "#ffffff"), (False, "#1a1c1f")):
|
||||
card.setChecked(checked)
|
||||
settle(application)
|
||||
assert card.time_label.palette().color(QPalette.ColorRole.WindowText).name() == expected
|
||||
card.setChecked(True)
|
||||
card.setEnabled(False)
|
||||
settle(application)
|
||||
assert card.time_label.palette().color(QPalette.ColorGroup.Disabled, QPalette.ColorRole.WindowText).name() == "#8e8f90"
|
||||
finally:
|
||||
dialog.close()
|
||||
|
||||
|
||||
def test_ai_report_columns_keep_headings_at_the_same_text_baseline(
|
||||
application: QApplication, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
def immediate(function, **kwargs):
|
||||
kwargs["on_success"](function())
|
||||
if kwargs.get("on_finished"):
|
||||
kwargs["on_finished"]()
|
||||
|
||||
monkeypatch.setattr(ai_module, "run_async", immediate)
|
||||
report = {"summary": "复核参考", "possible_symptoms": ["乏力", "纳差", "睡眠不安"], "main_indications": "脾气不足", "efficacy": ["健脾", "益气", "养阴"], "suitable_people": ["需由医师辨证确认"]}
|
||||
repository = SimpleNamespace(list_prescription_template_ai_reports=lambda template_id: {"prescription_id": template_id, "reports": [{"report_id": 1, "model_key": "qwen", "report": report}]})
|
||||
dialog = PrescriptionAiReportDialog(repository, PermissionSet(["*"]))
|
||||
dialog.open_for({"id": 1, "prescription_name": "测试方", "herbs": []})
|
||||
dialog.show()
|
||||
settle(application)
|
||||
try:
|
||||
labels = {label.text(): label for label in dialog.findChildren(QLabel) if label.objectName() == "PrescriptionAiSectionTitle"}
|
||||
for left, right in (("可能症状与证候", "主治方向"), ("主要功效", "可能适用人群")):
|
||||
# QLabel vertically centers text: compare the centers, not just widget origins.
|
||||
centers = [labels[text].mapTo(dialog, labels[text].rect().center()).y() for text in (left, right)]
|
||||
assert abs(centers[0] - centers[1]) <= 1
|
||||
finally:
|
||||
dialog.close()
|
||||
Reference in New Issue
Block a user