103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
"""Doctor choices remain explicit and transactional across mouse/search/keyboard use."""
|
|
import os
|
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
import pytest
|
|
from PySide6.QtCore import QPoint, Qt, QTimer
|
|
from PySide6.QtTest import QTest
|
|
from PySide6.QtWidgets import QApplication
|
|
|
|
from doctor_workstation.ui.pages.prescriptions import DoctorMultiSelect, _DoctorSelectionDialog
|
|
from doctor_workstation.ui.theme import apply_theme
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def application():
|
|
app = QApplication.instance() or QApplication([])
|
|
apply_theme(app)
|
|
return app
|
|
|
|
|
|
@pytest.fixture
|
|
def dialog(application):
|
|
parent = DoctorMultiSelect()
|
|
widget = _DoctorSelectionDialog({1: "医生甲", 2: "医生乙", 3: "医生丙"}, {1}, parent)
|
|
widget.show()
|
|
application.processEvents()
|
|
yield widget
|
|
widget.close()
|
|
parent.deleteLater()
|
|
application.processEvents()
|
|
|
|
|
|
def item_for(dialog, doctor_id):
|
|
return next(dialog.listing.item(i) for i in range(dialog.listing.count())
|
|
if dialog.listing.item(i).data(Qt.ItemDataRole.UserRole) == doctor_id)
|
|
|
|
|
|
def test_row_and_checkbox_toggle_once_and_keyboard(dialog, application):
|
|
item = item_for(dialog, 2)
|
|
rect = dialog.listing.visualItemRect(item)
|
|
QTest.mouseClick(dialog.listing.viewport(), Qt.MouseButton.LeftButton, pos=rect.center())
|
|
assert dialog.selected_ids() == {1, 2}
|
|
assert dialog.count_label.text() == "已选 2 位医生"
|
|
QTest.mouseClick(dialog.listing.viewport(), Qt.MouseButton.LeftButton,
|
|
pos=QPoint(rect.left() + 20, rect.center().y()))
|
|
assert dialog.selected_ids() == {1}
|
|
dialog.listing.setCurrentItem(item)
|
|
dialog.listing.setFocus()
|
|
QTest.keyClick(dialog.listing, Qt.Key.Key_Space)
|
|
assert dialog.selected_ids() == {1, 2}
|
|
QTest.keyClick(dialog.listing, Qt.Key.Key_Space)
|
|
assert dialog.selected_ids() == {1}
|
|
|
|
|
|
def test_filter_preserves_checks_and_clear_includes_hidden(dialog):
|
|
dialog.search.setText("乙")
|
|
assert item_for(dialog, 1).isHidden()
|
|
assert not item_for(dialog, 2).isHidden()
|
|
assert dialog.selected_ids() == {1}
|
|
dialog.clear_button.click()
|
|
assert dialog.selected_ids() == set()
|
|
assert not dialog.clear_button.isEnabled()
|
|
dialog.search.clear()
|
|
assert not item_for(dialog, 1).isHidden()
|
|
|
|
|
|
def test_checked_row_blue_and_unchecked_white(dialog, application):
|
|
application.processEvents()
|
|
image = dialog.listing.viewport().grab().toImage()
|
|
scale = image.devicePixelRatio()
|
|
colors = []
|
|
for doctor_id in (1, 2):
|
|
rect = dialog.listing.visualItemRect(item_for(dialog, doctor_id))
|
|
colors.append(image.pixelColor(int((rect.right() - 70) * scale),
|
|
int(rect.center().y() * scale)).name())
|
|
assert colors == ["#eaf2ff", "#ffffff"]
|
|
|
|
|
|
def test_accept_commits_cancel_preserves_and_reopen_restores(application):
|
|
selector = DoctorMultiSelect()
|
|
selector.update_options([{"id": 1, "name": "医生甲"}, {"id": 2, "name": "医生乙"}])
|
|
seen = []
|
|
|
|
def choose(accept):
|
|
modal = application.activeModalWidget()
|
|
seen.append(modal.selected_ids())
|
|
item_for(modal, 2).setCheckState(Qt.CheckState.Checked)
|
|
modal.accept() if accept else modal.reject()
|
|
|
|
QTimer.singleShot(0, lambda: choose(False))
|
|
selector._choose()
|
|
assert selector.values() == []
|
|
QTimer.singleShot(0, lambda: choose(True))
|
|
selector._choose()
|
|
assert selector.values() == [2]
|
|
assert selector.button.text() == "医生乙"
|
|
QTimer.singleShot(0, lambda: choose(False))
|
|
selector._choose()
|
|
assert seen == [set(), set(), {2}]
|
|
assert selector.values() == [2]
|
|
selector.deleteLater()
|