from __future__ import annotations import os os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") import pytest from PySide6.QtCore import QEvent from PySide6.QtGui import QFont from PySide6.QtWidgets import QApplication, QLabel, QToolButton, QVBoxLayout, QWidget from doctor_workstation.ui.diagnosis_index_widgets import DiagnosisTableHost from doctor_workstation.ui.reception_style import body_family @pytest.fixture(scope="module") def application() -> QApplication: return QApplication.instance() or QApplication([]) @pytest.mark.parametrize("tech_blue", [False, True]) @pytest.mark.parametrize("size", [(1024, 640), (1710, 920)]) @pytest.mark.parametrize("with_channel", [False, True]) def test_public_video_status_fits_frozen_cell_with_inherited_item_padding( application: QApplication, tech_blue: bool, size: tuple[int, int], with_channel: bool, ) -> None: root = QWidget() font = QFont(body_family()) font.setPixelSize(13) root.setFont(font) # Match GLOBAL_QSS without changing the application's theme between tests. root.setStyleSheet("QTableView::item { padding: 6px 8px; border-bottom: 1px solid #E1E9F4; }") layout = QVBoxLayout(root) host = DiagnosisTableHost( parent=root, tech_blue=tech_blue, action_policy={"video_call": True, "view": True, "edit": True}, video_entry_allowed=lambda _record: False, ) layout.addWidget(host) statuses = [ ("ended", "视频已结束 · 10-17 14:19"), ("ended", "视频已结束 · 10-17 14:27"), ("ended", "视频已结束"), ("live", "通话中"), ("pending_room", "接通中"), ("missed", "上次通话未接听"), ("cancelled", "上次通话已取消"), ("none", "—"), ] rows = [ { "id": index + 1, "patient_id": index + 100, "patient_name": "测试患者", "gender": 1, "age": 50, "has_appointment": 1, "appointment_id": index + 200, "appointment_status": 1, "appointment_type": "video", "latest_appointment_channel_text": "自媒体4H" if with_channel else "", "appointments": [{"id": index + 200, "status": 1, "doctor_name": "测试医生", "time_text": "2026-10-17 14:15", "appointment_type": "video"}], "video_call_hint": {"state": state, "label": text}, } for index, (state, text) in enumerate(statuses * 4) ] try: host.set_rows(rows) root.resize(*size) root.show() for _ in range(4): application.processEvents() for index, (_state, text) in enumerate(statuses): cell = host.fixed.indexWidget(host.model.index(index, 10)) assert not cell.findChildren(QToolButton) label = cell.findChild(QLabel) assert label is not None assert label.height() >= label.heightForWidth(label.width()) assert cell.rect().contains(label.geometry()) assert abs(label.geometry().center().y() - cell.rect().center().y()) <= 1 assert label.toolTip() == text if " · " in text: assert label.text() == text.replace(" · ", "\n") assert label.fontMetrics().horizontalAdvance("10-17 14:19") <= label.width() assert cell.width() >= host.fixed.columnWidth(10) - 2 host.main.horizontalScrollBar().setValue(host.main.horizontalScrollBar().maximum()) for fraction in (2, 3): host.main.verticalScrollBar().setValue(host.main.verticalScrollBar().maximum() // fraction) application.processEvents() assert host.fixed.verticalScrollBar().value() == host.main.verticalScrollBar().value() row = host.main.indexAt(host.main.viewport().rect().center()).row() assert row >= 0 assert host.main.visualRect(host.model.index(row, 0)).top() == host.fixed.visualRect( host.model.index(row, 10) ).top() finally: root.close() root.deleteLater() application.sendPostedEvents(None, QEvent.Type.DeferredDelete)