更新bug
This commit is contained in:
@@ -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"
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() == ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user