更新
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
"""Native Qt coverage for presentation-only filter folding on both queues."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
import pytest
|
||||
from PySide6.QtCore import QPoint, QRect, Qt, Signal
|
||||
from PySide6.QtTest import QTest
|
||||
from PySide6.QtWidgets import QApplication, QPushButton, QWidget
|
||||
|
||||
from doctor_workstation.ui import shell as shell_module
|
||||
from doctor_workstation.ui.pages import appointments, consultations
|
||||
from doctor_workstation.ui.shell import NavigationItem, ShellWindow
|
||||
from doctor_workstation.ui.theme import apply_theme
|
||||
|
||||
|
||||
class _Dialog(QWidget):
|
||||
saved = Signal()
|
||||
|
||||
def __init__(self, _repository: Any, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
|
||||
class _Repository:
|
||||
def __init__(self) -> None:
|
||||
self.calls: list[dict[str, Any]] = []
|
||||
|
||||
def _list(self, **query: Any) -> dict[str, Any]:
|
||||
self.calls.append(query)
|
||||
rows = [{
|
||||
"id": index, "diagnosis_id": index, "patient_id": index + 2000,
|
||||
"source_patient_id": index + 2000, "patient_name": f"演示患者{index:02d}",
|
||||
"patient_phone": "13800001234", "gender": 2, "age": 38,
|
||||
"status": 1, "status_desc": "待接诊", "doctor_name": "演示医生",
|
||||
"doctor_id": 30, "assistant_name": "演示医助", "has_appointment": True,
|
||||
"appointment_id": index + 1000, "appointment_status": 1,
|
||||
"appointment_date": date.today().isoformat(), "appointment_time": "09:00-09:30",
|
||||
"diagnosis_confirmed": True, "has_prescription": False,
|
||||
"appointments": [{"id": index + 1000, "status": 1,
|
||||
"doctor_name": "演示医生", "time_text": "09:00-09:30"}],
|
||||
} for index in range(1, 16)]
|
||||
return {"lists": rows, "count": 15, "extend": {"status_count": {"1": 15}}}
|
||||
|
||||
list_appointments = _list
|
||||
list_consultations = _list
|
||||
|
||||
|
||||
def _inline(function: Any, *, on_success=None, on_error=None, on_finished=None) -> None:
|
||||
try:
|
||||
result = function()
|
||||
except Exception as error:
|
||||
if on_error is not None:
|
||||
on_error(error)
|
||||
else:
|
||||
if on_success is not None:
|
||||
on_success(result)
|
||||
finally:
|
||||
if on_finished is not None:
|
||||
on_finished()
|
||||
|
||||
|
||||
def _settle(application: QApplication) -> None:
|
||||
for _ in range(4):
|
||||
application.processEvents()
|
||||
QTest.qWait(10)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def application() -> QApplication:
|
||||
app = QApplication.instance() or QApplication([])
|
||||
apply_theme(app)
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def list_window(application: QApplication, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(appointments, "run_async", _inline)
|
||||
monkeypatch.setattr(consultations, "run_async", _inline)
|
||||
monkeypatch.setattr(consultations, "DiagnosisDialog", _Dialog)
|
||||
monkeypatch.setattr(consultations.ConsultationsPage, "_load_filter_options", lambda self: None)
|
||||
monkeypatch.setattr(consultations.ConsultationsPage, "_refresh_counts", lambda self: None)
|
||||
monkeypatch.setattr(appointments.AppointmentsPage, "_load_departments", lambda self: None)
|
||||
monkeypatch.setattr(shell_module.motion, "reduced_motion", lambda: True)
|
||||
navigation = [
|
||||
NavigationItem("appointments", "挂号列表", "号", appointments.AppointmentsPage,
|
||||
("doctor.appointment/lists",)),
|
||||
NavigationItem("consultations", "问诊列表", "询", consultations.ConsultationsPage,
|
||||
("tcm.diagnosis/lists",)),
|
||||
]
|
||||
monkeypatch.setattr(shell_module, "_resolve_navigation",
|
||||
lambda *_args, **_kwargs: [(item, item.title) for item in navigation])
|
||||
repository = _Repository()
|
||||
window = ShellWindow(repository, {"user": {"name": "演示医生", "role_id": 1},
|
||||
"demo_mode": True}, permissions={"*"})
|
||||
yield window, repository
|
||||
window.close()
|
||||
window.deleteLater()
|
||||
_settle(application)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["appointments", "consultations"])
|
||||
@pytest.mark.parametrize(("width", "height"), [(1366, 768), (1536, 960)])
|
||||
def test_folding_reclaims_rows_and_retains_query_refresh_and_navigation_state(
|
||||
application: QApplication, list_window: Any, kind: str, width: int, height: int,
|
||||
) -> None:
|
||||
window, repository = list_window
|
||||
window.resize(width, height)
|
||||
window.show()
|
||||
assert window.navigate(kind)
|
||||
_settle(application)
|
||||
page = window.pages[kind]
|
||||
page.poll_timer.stop()
|
||||
panel = page.filter_panel if kind == "appointments" else page.filters_card
|
||||
header = page.header if kind == "appointments" else page.page_header
|
||||
search = page.patient_input if kind == "appointments" else page.patient_name_edit
|
||||
nested = page.more_filters_button if kind == "appointments" else page.more_filter_button
|
||||
action = page.toolbar_edit_button if kind == "appointments" else page.add_button
|
||||
disclosure = page.filter_disclosure
|
||||
filters = page._query_filters if kind == "appointments" else page._filters
|
||||
assert not disclosure.expanded
|
||||
assert panel.isHidden() and not search.isVisible()
|
||||
assert header.height() <= 44
|
||||
assert not header.subtitle_label.isVisible()
|
||||
assert disclosure.button.isVisible() and action.isVisible()
|
||||
assert 30 <= disclosure.button.height() <= 34
|
||||
assert window.refresh_button.isVisible()
|
||||
assert any(button.isVisible() and button.text() == "刷新"
|
||||
for button in page.findChildren(QPushButton))
|
||||
collapsed_height = page.table.viewport().height()
|
||||
capture_dir = os.environ.get("COLLAPSIBLE_LIST_SCREENSHOTS")
|
||||
if capture_dir:
|
||||
Path(capture_dir).mkdir(parents=True, exist_ok=True)
|
||||
assert window.grab().save(str(Path(capture_dir) / f"{kind}-{width}-collapsed.png"))
|
||||
|
||||
calls_before = len(repository.calls)
|
||||
QTest.mouseClick(disclosure.button, Qt.MouseButton.LeftButton)
|
||||
_settle(application)
|
||||
assert len(repository.calls) == calls_before
|
||||
assert panel.isVisible() and search.isVisible()
|
||||
assert collapsed_height >= page.table.viewport().height() + 100
|
||||
assert panel.rect().contains(QRect(search.mapTo(panel, QPoint()), search.size()))
|
||||
assert search.parentWidget().rect().contains(search.geometry())
|
||||
assert not page.advanced_filters.isVisible()
|
||||
if capture_dir:
|
||||
assert window.grab().save(str(Path(capture_dir) / f"{kind}-{width}-expanded.png"))
|
||||
(Path(capture_dir) / f"{kind}-{width}-metrics.json").write_text(
|
||||
json.dumps({"window": [width, height], "header_height": header.height(),
|
||||
"toggle_height": disclosure.button.height(),
|
||||
"collapsed_viewport_height": collapsed_height,
|
||||
"expanded_viewport_height": page.table.viewport().height(),
|
||||
"viewport_gain": collapsed_height - page.table.viewport().height()},
|
||||
indent=2), encoding="utf-8",
|
||||
)
|
||||
|
||||
search.setText("演示患者")
|
||||
query_button = (page.findChild(QPushButton, "AppointmentSearchButton")
|
||||
if kind == "appointments" else page.search_button)
|
||||
QTest.mouseClick(query_button, Qt.MouseButton.LeftButton)
|
||||
_settle(application)
|
||||
assert len(repository.calls) > calls_before
|
||||
assert repository.calls[-1]["patient_name"] == "演示患者"
|
||||
QTest.mouseClick(nested, Qt.MouseButton.LeftButton)
|
||||
_settle(application)
|
||||
assert page.advanced_filters.isVisible()
|
||||
query = dict(filters())
|
||||
calls_before = len(repository.calls)
|
||||
QTest.mouseClick(disclosure.button, Qt.MouseButton.LeftButton)
|
||||
_settle(application)
|
||||
assert len(repository.calls) == calls_before
|
||||
assert filters() == query
|
||||
assert search.text() == "演示患者"
|
||||
assert panel.isHidden()
|
||||
assert page.table.viewport().height() == collapsed_height
|
||||
|
||||
window.resize(width - 50, height - 20)
|
||||
window.refresh_button.click()
|
||||
_settle(application)
|
||||
assert not disclosure.expanded and panel.isHidden()
|
||||
assert filters() == query
|
||||
other = "consultations" if kind == "appointments" else "appointments"
|
||||
assert window.navigate(other)
|
||||
assert window.navigate(kind)
|
||||
_settle(application)
|
||||
assert not disclosure.expanded and panel.isHidden()
|
||||
QTest.mouseClick(disclosure.button, Qt.MouseButton.LeftButton)
|
||||
_settle(application)
|
||||
assert page.advanced_filters.isVisible() and nested.isChecked()
|
||||
window.refresh_button.click()
|
||||
_settle(application)
|
||||
assert disclosure.expanded and panel.isVisible()
|
||||
assert filters() == query
|
||||
Reference in New Issue
Block a user