更新
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
import pytest
|
||||
from PySide6.QtCore import QPoint, QTimer
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QPushButton
|
||||
|
||||
from doctor_workstation.services import DemoDoctorRepository
|
||||
from doctor_workstation.ui import apply_theme
|
||||
from doctor_workstation.ui.pages import (
|
||||
appointments,
|
||||
consultations,
|
||||
patients,
|
||||
prescription_library,
|
||||
prescriptions,
|
||||
)
|
||||
from doctor_workstation.ui.widgets import PageHeader
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def application() -> QApplication:
|
||||
app = QApplication.instance() or QApplication([])
|
||||
apply_theme(app)
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page_factory(application: QApplication, monkeypatch: pytest.MonkeyPatch):
|
||||
def immediate(function: Any, *args: Any, on_success=None, on_error=None,
|
||||
on_finished=None, **kwargs: Any) -> object:
|
||||
try:
|
||||
result = function(*args, **kwargs)
|
||||
except Exception as error:
|
||||
if on_error:
|
||||
on_error(error)
|
||||
else:
|
||||
if on_success:
|
||||
on_success(result)
|
||||
finally:
|
||||
if on_finished:
|
||||
on_finished()
|
||||
return object()
|
||||
|
||||
modules = (appointments, consultations, patients, prescription_library, prescriptions)
|
||||
for module in modules:
|
||||
monkeypatch.setattr(module, "run_async", immediate)
|
||||
opened = []
|
||||
|
||||
def create(kind: str, width: int = 1040):
|
||||
repo = DemoDoctorRepository()
|
||||
session = repo.login(repo.DEMO_ACCOUNT, repo.DEMO_PASSWORD)
|
||||
classes = {
|
||||
"appointments": appointments.AppointmentsPage,
|
||||
"patients": patients.PatientsPage,
|
||||
"consultations": consultations.ConsultationsPage,
|
||||
"prescriptions": prescriptions.PrescriptionsPage,
|
||||
"prescription_library": prescription_library.PrescriptionLibraryPage,
|
||||
}
|
||||
page = classes[kind](repo, permissions=session.permissions, current_user=session.user)
|
||||
opened.append(page)
|
||||
page.resize(width, 700)
|
||||
page.show()
|
||||
page.refresh()
|
||||
for _ in range(4):
|
||||
application.processEvents()
|
||||
return page
|
||||
|
||||
yield create
|
||||
for page in opened:
|
||||
for timer in page.findChildren(QTimer):
|
||||
timer.stop()
|
||||
page.close()
|
||||
page.deleteLater()
|
||||
application.processEvents()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["appointments", "patients", "consultations", "prescriptions", "prescription_library"])
|
||||
def test_list_header_fits_the_real_bundled_font(page_factory, kind: str) -> None:
|
||||
page = page_factory(kind)
|
||||
header = page.findChild(PageHeader)
|
||||
assert header is not None
|
||||
for label in header.findChildren(QLabel):
|
||||
if label.isVisible() and label.text() and label.property("role"):
|
||||
assert label.height() >= label.fontMetrics().height(), (
|
||||
kind, label.text(), label.height(), label.fontMetrics().height()
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["patients", "prescription_library"])
|
||||
@pytest.mark.parametrize("width", [1040, 1200])
|
||||
def test_row_actions_are_fully_reachable_at_each_width(page_factory, kind, width):
|
||||
page = page_factory(kind, width)
|
||||
table = page.patient_workspace.table if kind == "patients" else page.table
|
||||
assert table.rowCount() > 0
|
||||
assert table.horizontalHeader().visualIndex(9) == 9
|
||||
actions = table.cellWidget(0, 9)
|
||||
assert actions is not None
|
||||
assert table.horizontalScrollBar().value() == 0
|
||||
# Both approved layouts put actions after the nine data columns. Preserve
|
||||
# full-size controls and the existing reachability assertion after scrolling.
|
||||
table.horizontalScrollBar().setValue(table.horizontalScrollBar().maximum())
|
||||
QApplication.processEvents()
|
||||
assert actions.geometry().left() >= 0
|
||||
assert actions.geometry().right() < table.viewport().width()
|
||||
assert actions.height() >= actions.minimumSizeHint().height()
|
||||
for child in actions.findChildren(QPushButton):
|
||||
assert actions.rect().contains(child.mapTo(actions, QPoint()))
|
||||
assert actions.rect().contains(child.mapTo(actions, child.rect().bottomRight()))
|
||||
|
||||
|
||||
def test_appointment_detail_lines_and_cancel_fit_without_overlapping(page_factory) -> None:
|
||||
page = page_factory("appointments")
|
||||
table = page.table
|
||||
assert table.rowCount() > 0
|
||||
host = table.cellWidget(0, 4)
|
||||
assert host.width() >= host.minimumSizeHint().width()
|
||||
assert host.height() >= host.minimumSizeHint().height()
|
||||
for label in host.findChildren(QLabel):
|
||||
assert label.height() >= label.fontMetrics().height()
|
||||
assert host.rect().contains(label.geometry())
|
||||
cancel = next(button for button in host.findChildren(QPushButton) if button.text() == "取消")
|
||||
for label in host.findChildren(QLabel):
|
||||
assert not label.geometry().intersects(cancel.geometry())
|
||||
# Underlying text is still available to sorting while a delegate paints only
|
||||
# the selection surface beneath the actual controls.
|
||||
assert table.item(0, 4).text()
|
||||
assert isinstance(table.itemDelegateForColumn(4), appointments._AppointmentInfoDelegate)
|
||||
assert table.horizontalScrollBar().maximum() == 0
|
||||
search = page.findChild(QPushButton, "AppointmentSearchButton")
|
||||
assert search.height() == page.patient_input.height()
|
||||
assert all(button.height() == search.height() for button in page.date_buttons.values() if button.isVisible())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["patients", "prescriptions", "prescription_library", "consultations"])
|
||||
def test_filter_actions_align_with_their_inputs(page_factory, kind: str) -> None:
|
||||
page = page_factory(kind)
|
||||
if kind == "patients":
|
||||
controls = page.patient_workspace
|
||||
widgets = (controls.keyword_edit, controls.search_button, controls.reset_button)
|
||||
statuses = tuple(controls.status_buttons.values())
|
||||
assert len({widget.height() for widget in statuses}) == 1
|
||||
assert len({widget.mapTo(controls.status_host, QPoint()).y() for widget in statuses}) == 1
|
||||
for widget in statuses:
|
||||
assert controls.status_host.rect().contains(widget.geometry())
|
||||
assert widget.height() >= widget.fontMetrics().height()
|
||||
elif kind == "prescriptions":
|
||||
widgets = (page.sn_filter, page.query_button, page.reset_button, page.doctor_filter.button)
|
||||
elif kind == "prescription_library":
|
||||
widgets = (page.name_filter, page.query_button, page.reset_button)
|
||||
else:
|
||||
widgets = (page.search_button, page.reset_button, page.custom_date_edit)
|
||||
assert len({widget.height() for widget in widgets}) == 1
|
||||
Reference in New Issue
Block a user