更新bug

This commit is contained in:
Your Name
2026-08-17 09:06:49 +08:00
parent 2fc8048844
commit c1eee2d28a
48 changed files with 3646 additions and 1016 deletions
@@ -191,6 +191,7 @@ def test_saved_history_is_rendered_without_automatic_generation(
assert [len(page._ai_analysis_histories[key]) for key in ("qwen", "openai")] == [2, 2]
assert "第 2 版" in page.ai_analysis_snapshot_meta.text()
assert page.ai_analysis_disclaimer.text() == AI_MEDICAL_DISCLAIMER
assert not page.ai_analysis_disclaimer.isVisibleTo(page)
assert page.ai_analysis_history_button.objectName() == "ReceptionAiHistoryButton"
assert page.ai_analysis_regenerate_button.objectName() == "ReceptionAiRegenerateButton"
+195 -6
View File
@@ -10,7 +10,7 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
import httpx
import pytest
from PySide6.QtCore import QPoint, Qt
from PySide6.QtCore import QDate, QPoint, Qt
from PySide6.QtGui import QPalette
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QScrollArea
@@ -129,7 +129,7 @@ def test_queue_status_badge_is_not_clipped_in_narrow_panel(
{
"patient_name": "张蒙",
"status": 1,
"status_desc": "待接诊",
"status_desc": "问诊中",
"appointment_time": "12:45:00",
"gender": 1,
"age": 36,
@@ -296,6 +296,33 @@ def test_queue_uses_admin_same_day_contract(
application.processEvents()
def test_queue_date_picker_filters_the_selected_day(
application: QApplication,
immediate_async: None,
) -> None:
calls: list[dict[str, Any]] = []
class Repository:
def list_appointments(self, **kwargs: Any) -> dict[str, Any]:
calls.append(kwargs)
return {"lists": [], "count": 0}
page = ReceptionPage(Repository(), PermissionSet([]))
page.show()
application.processEvents()
page.queue_date_button.click()
calendar = page.queue_date_button.calendarWidget()
assert calendar.isVisible()
page.queue_date_button._pick_date(QDate(2026, 8, 1))
assert not calendar.isVisible()
assert page.queue_date_button.text() == "2026-08-01"
assert page._queue_date == "2026-08-01"
assert calls[-1]["start_date"] == "2026-08-01"
assert calls[-1]["end_date"] == "2026-08-01"
page.close()
application.processEvents()
def test_silent_queue_polls_reuse_rows_and_do_not_restart_detail_or_ai(
application: QApplication,
immediate_async: None,
@@ -630,14 +657,164 @@ def test_queue_load_more_accumulates_to_total_boundary(
page = ReceptionPage(Repository(), PermissionSet([]))
page.refresh()
assert page.queue_list.count() == 15
assert page.load_more_button.isVisibleTo(page)
assert page._queue_has_more()
assert not hasattr(page, "load_more_button")
assert not hasattr(page, "add_patient_button")
page._load_more()
assert [call["page_no"] for call in calls] == [1, 2]
assert all(call["page_size"] == 15 for call in calls)
assert page.queue_list.count() == 22
assert page.queue_summary.text() == "已加载 22 / 共 22 位患者"
assert page.load_more_button.isHidden()
assert not page._queue_has_more()
page.close()
application.processEvents()
def test_silent_poll_keeps_already_loaded_queue_pages(
application: QApplication,
immediate_async: None,
) -> None:
calls: list[dict[str, Any]] = []
all_rows = [
{
"id": index,
"patient_id": 1000 + index,
"diagnosis_id": 2000 + index,
"patient_name": f"患者{index:02d}",
"status": 1,
}
for index in range(1, 28)
]
class Repository:
def list_appointments(self, **kwargs: Any) -> dict[str, Any]:
calls.append(dict(kwargs))
start = (kwargs["page_no"] - 1) * kwargs["page_size"]
return {
"lists": all_rows[start : start + kwargs["page_size"]],
"count": len(all_rows),
}
def get_reception(self, appointment_id: int) -> dict[str, Any]:
row = all_rows[appointment_id - 1]
return {
"appointment": row,
"diagnosis": {"id": row["diagnosis_id"], "patient_id": row["patient_id"]},
}
page = ReceptionPage(Repository(), PermissionSet([]))
page.refresh()
page._load_more()
assert page.queue_list.count() == 27
assert page._queue_page == 2
calls.clear()
page.refresh(silent=True)
assert page.queue_list.count() == 27
assert page._queue_page == 2
assert calls[-1]["page_no"] == 1
assert calls[-1]["page_size"] >= 27
page.close()
application.processEvents()
def test_queue_shows_loading_indicator_while_page_request_is_open(
application: QApplication,
queued_async: list[dict[str, Any]],
) -> None:
class Repository:
def list_appointments(self, **_kwargs: Any) -> dict[str, Any]:
return {
"lists": [
{"id": 1, "patient_name": "加载患者", "status": 1},
],
"count": 16,
}
def get_reception(self, appointment_id: int) -> dict[str, Any]:
return {
"appointment": {
"id": appointment_id,
"patient_id": 1001,
"status": 1,
},
"diagnosis": {"id": 2001, "patient_id": 1001},
}
page = ReceptionPage(Repository(), PermissionSet([]))
page.refresh()
assert page.queue_loading_indicator.isVisibleTo(page)
assert page.queue_loading_indicator.label.text() == "正在加载…"
assert page.queue_loading_indicator.spinner._timer.isActive()
queued_async[0]["on_success"](
{
"lists": [{"id": 1, "patient_name": "加载患者", "status": 1}],
"count": 16,
}
)
queued_async[0]["on_finished"]()
assert not page.queue_loading_indicator.isVisibleTo(page)
assert not page.queue_loading_indicator.spinner._timer.isActive()
page._load_more()
assert page.queue_loading_indicator.isVisibleTo(page)
load_more_job = queued_async[-1]
load_more_job["on_success"](
{
"lists": [{"id": 2, "patient_name": "第二页患者", "status": 1}],
"count": 16,
}
)
load_more_job["on_finished"]()
assert not page.queue_loading_indicator.isVisibleTo(page)
page.close()
application.processEvents()
def test_queue_scrolls_to_bottom_loads_next_page(
application: QApplication,
immediate_async: None,
) -> None:
calls: list[dict[str, Any]] = []
all_rows = [
{
"id": index,
"patient_id": 1000 + index,
"diagnosis_id": 2000 + index,
"patient_name": f"患者{index:02d}",
"status": 1,
}
for index in range(1, 23)
]
class Repository:
def list_appointments(self, **kwargs: Any) -> dict[str, Any]:
calls.append(kwargs)
start = (kwargs["page_no"] - 1) * kwargs["page_size"]
return {
"lists": all_rows[start : start + kwargs["page_size"]],
"count": len(all_rows),
}
def get_reception(self, appointment_id: int) -> dict[str, Any]:
row = all_rows[appointment_id - 1]
return {
"appointment": row,
"diagnosis": {"id": row["diagnosis_id"], "patient_id": row["patient_id"]},
}
page = ReceptionPage(Repository(), PermissionSet([]))
page.resize(1280, 640)
page.show()
application.processEvents()
assert page.queue_list.count() == 15
scrollbar = page.queue_list.verticalScrollBar()
assert scrollbar.maximum() > 0
scrollbar.setValue(scrollbar.maximum())
application.processEvents()
assert [call["page_no"] for call in calls] == [1, 2]
assert page.queue_list.count() == 22
page.close()
application.processEvents()
@@ -871,6 +1048,8 @@ def test_reception_auto_loads_structured_ai_analysis_and_matches_reference_geome
] == [("千问", "qwen"), ("OpenAI", "openai")]
assert page.ai_analysis_model_selector.currentData() == "qwen"
assert page._ai_analysis_state == "success"
assert page.ai_analysis_stack.currentWidget() is page.ai_analysis_content_page
assert page.ai_summary_label.isVisible()
assert page.ai_summary_label.text() == "2 型糖尿病,血糖控制不佳"
assert page.ai_treatment_label.text().startswith("建议调整降糖方案")
assert page.ai_summary_label.textFormat() == Qt.TextFormat.PlainText
@@ -887,7 +1066,7 @@ def test_reception_auto_loads_structured_ai_analysis_and_matches_reference_geome
assert [button.text() for button in page.ai_prompt_buttons] == [
"基于当前病史,下一步检查建议?",
"该患者的用药调整建议?",
"糖尿病教育要点?",
"糖尿病教育要点有哪些",
"并发症筛查建议?",
]
assert page.ai_send_button.text() == ""
@@ -915,10 +1094,12 @@ def test_reception_auto_loads_structured_ai_analysis_and_matches_reference_geome
left = page.ai_analysis_card.geometry()
right = page.ai_assistant_card.geometry()
assert 235 <= left.height() <= 260
assert 470 <= left.height() <= 520
assert left.height() == right.height()
assert 0 <= right.left() - left.right() - 1 <= 2
assert abs(left.width() * 5 - right.width() * 4) <= 10
assert page.ai_summary_label.width() <= page.ai_analysis_card.contentsRect().width()
assert page.ai_summary_label.minimumSizeHint().width() <= 48
calls_before_switch = list(analysis_calls)
page.ai_analysis_model_selector.setCurrentIndex(
@@ -931,6 +1112,14 @@ def test_reception_auto_loads_structured_ai_analysis_and_matches_reference_geome
)
assert page.ai_summary_label.text() == "2 型糖尿病,血糖控制不佳"
assert analysis_calls == calls_before_switch
assert page.detail_scroll.objectName() == "ReceptionDetailScroll"
assert (
page.detail_scroll.verticalScrollBarPolicy()
== Qt.ScrollBarPolicy.ScrollBarAsNeeded
)
page.resize(1494, 620)
application.processEvents()
assert page.detail_scroll.verticalScrollBar().maximum() > 0
page.close()
application.processEvents()
+3 -3
View File
@@ -73,7 +73,7 @@ def test_appointments_navigation_is_named_reception_and_always_first() -> None:
)
assert [(item.key, title) for item, title in resolved] == [
("appointments", "接诊台"),
("appointments", "问诊列表"),
("patients", "我的患者"),
]
@@ -86,7 +86,7 @@ def shell_window(
navigation = [
NavigationItem(key, title, glyph, _ShellPageDouble, (permission,))
for key, title, glyph, permission in (
("appointments", "接诊台", "", "doctor.appointment/lists"),
("appointments", "问诊列表", "", "doctor.appointment/lists"),
("reception", "接诊台", "", "doctor.appointment/lists"),
(
"prescription_library",
@@ -164,7 +164,7 @@ def test_reference_shell_has_integrated_search_ai_card_and_window_controls(
)
assert shell_window.assistant_card.isVisible()
assert shell_window.assistant_button.text() == "开始对话"
assert "服务端自动匹配" in shell_window.model_label.text()
assert "GPT-4o 医疗版" in shell_window.model_label.text()
assert shell_window.minimize_button.text() == ""
assert shell_window.close_button.text() == ""