"""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()