geng
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
@@ -12,7 +12,7 @@ import httpx
|
||||
import pytest
|
||||
from PySide6.QtCore import QDate, QPoint, Qt
|
||||
from PySide6.QtGui import QPalette
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QScrollArea
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QScrollArea, QWidget
|
||||
|
||||
from doctor_workstation.core import PermissionSet
|
||||
from doctor_workstation.services.api_client import ApiClient
|
||||
@@ -283,9 +283,10 @@ def test_queue_uses_admin_same_day_contract(
|
||||
"status": 1,
|
||||
"start_date": date.today().isoformat(),
|
||||
"end_date": date.today().isoformat(),
|
||||
"page_no": 1,
|
||||
"page_size": 15,
|
||||
"patient_name": "王小明",
|
||||
"page_no": 1,
|
||||
"page_size": 15,
|
||||
"patient_name": "王小明",
|
||||
"include_status_counts": 1,
|
||||
}
|
||||
]
|
||||
|
||||
@@ -296,6 +297,167 @@ def test_queue_uses_admin_same_day_contract(
|
||||
application.processEvents()
|
||||
|
||||
|
||||
def test_reception_daily_records_use_backend_matrix_contract(
|
||||
application: QApplication,
|
||||
immediate_async: None,
|
||||
) -> None:
|
||||
today = date.today().isoformat()
|
||||
tracking_calls: list[tuple[int, str, str]] = []
|
||||
note_calls: list[int] = []
|
||||
|
||||
class Repository:
|
||||
fail_tracking = False
|
||||
|
||||
def list_appointments(self, **_kwargs: Any) -> dict[str, Any]:
|
||||
return {
|
||||
"lists": [
|
||||
{
|
||||
"id": 71,
|
||||
"diagnosis_id": 271,
|
||||
# Production appointment.patient_id is the diagnosis id.
|
||||
"patient_id": 271,
|
||||
"patient_name": "日常记录患者",
|
||||
"status": 1,
|
||||
"appointment_time": "09:30:00",
|
||||
}
|
||||
],
|
||||
"count": 1,
|
||||
}
|
||||
|
||||
def get_reception(self, appointment_id: int) -> dict[str, Any]:
|
||||
assert appointment_id == 71
|
||||
return {
|
||||
"appointment": {
|
||||
"id": 71,
|
||||
"patient_id": 271,
|
||||
"patient_name": "日常记录患者",
|
||||
"status": 1,
|
||||
},
|
||||
"diagnosis": {
|
||||
"id": 271,
|
||||
"patient_id": 971,
|
||||
"patient_name": "日常记录患者",
|
||||
"age": 56,
|
||||
},
|
||||
"tracking_notes": [
|
||||
{"note_date": today, "content": "内嵌备注降级数据"}
|
||||
],
|
||||
}
|
||||
|
||||
def get_tracking_window(
|
||||
self,
|
||||
diagnosis_id: int,
|
||||
*,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
) -> dict[str, Any]:
|
||||
tracking_calls.append((diagnosis_id, start_date, end_date))
|
||||
if self.fail_tracking:
|
||||
raise RuntimeError("tracking unavailable")
|
||||
return {
|
||||
"diagnosis_id": diagnosis_id,
|
||||
"start_date": start_date,
|
||||
"end_date": end_date,
|
||||
"blood_records": [
|
||||
{
|
||||
"record_date": today,
|
||||
"record_time": "08:30:00",
|
||||
"fasting_blood_sugar": 9.6,
|
||||
"postprandial_blood_sugar": 11.4,
|
||||
"other_blood_sugar": 8.5,
|
||||
"systolic_pressure": 141,
|
||||
"diastolic_pressure": 90,
|
||||
"western_medicine": "二甲双胍",
|
||||
"insulin": "睡前 8U",
|
||||
"source": 1,
|
||||
}
|
||||
],
|
||||
"diet_records": [
|
||||
{
|
||||
"record_date": today,
|
||||
"breakfast_foods": ["小米粥"],
|
||||
"lunch_foods": ["杂粮饭"],
|
||||
"dinner_foods": ["青菜"],
|
||||
}
|
||||
],
|
||||
"exercise_records": [
|
||||
{
|
||||
"record_date": today,
|
||||
"exercise_type": "快走",
|
||||
"duration": 45,
|
||||
"intensity_text": "中等",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
def list_tracking_notes(self, diagnosis_id: int) -> list[dict[str, Any]]:
|
||||
note_calls.append(diagnosis_id)
|
||||
return [{"note_date": today, "content": "睡眠改善,继续随访"}]
|
||||
|
||||
repository = Repository()
|
||||
page = ReceptionPage(repository, PermissionSet([]))
|
||||
page.refresh()
|
||||
application.processEvents()
|
||||
|
||||
assert [
|
||||
page.detail_tabs.tabText(index) for index in range(page.detail_tabs.count())
|
||||
] == ["问诊信息", "检查报告", "用药记录", "日常记录", "随访记录", "健康数据"]
|
||||
assert tracking_calls == [
|
||||
(271, (date.today() - timedelta(days=6)).isoformat(), today)
|
||||
]
|
||||
assert note_calls == [271]
|
||||
assert page._selection_context()[-1] == 971
|
||||
|
||||
matrix = page.daily_panel.matrix
|
||||
assert matrix.objectName() == "ReceptionDailyRecordsTable"
|
||||
assert matrix.rowCount() == 11
|
||||
assert matrix.columnCount() == 8
|
||||
assert matrix.horizontalHeaderItem(0).text() == "指标"
|
||||
assert matrix.horizontalHeaderItem(1).text() == today[5:]
|
||||
assert [matrix.item(row, 0).text() for row in range(11)] == [
|
||||
"空腹血糖",
|
||||
"餐后2h血糖",
|
||||
"其他血糖",
|
||||
"血压",
|
||||
"西药",
|
||||
"胰岛素",
|
||||
"早餐",
|
||||
"午餐",
|
||||
"晚餐",
|
||||
"运动",
|
||||
"跟踪备注",
|
||||
]
|
||||
assert matrix.item(0, 1).text() == "9.6 · 自录 ↑"
|
||||
assert matrix.item(0, 1).data(Qt.ItemDataRole.UserRole)["high"] is True
|
||||
assert matrix.item(1, 1).text() == "11.4 · 自录 ↑"
|
||||
assert matrix.item(2, 1).text() == "8.5 · 自录"
|
||||
assert matrix.item(2, 1).data(Qt.ItemDataRole.UserRole)["high"] is False
|
||||
assert matrix.item(3, 1).text() == "141/90 · 自录 ↑"
|
||||
assert matrix.item(4, 1).text() == "二甲双胍"
|
||||
assert matrix.item(5, 1).text() == "睡前 8U"
|
||||
assert matrix.item(6, 1).text() == "已记录"
|
||||
assert matrix.item(9, 1).text() == "45min"
|
||||
assert matrix.item(10, 1).text() == "睡眠改善,继续随访"
|
||||
assert "睡眠改善" in page.followup_text.text()
|
||||
|
||||
page.daily_panel.range_buttons["30"].click()
|
||||
assert tracking_calls[-1] == (
|
||||
271,
|
||||
(date.today() - timedelta(days=29)).isoformat(),
|
||||
today,
|
||||
)
|
||||
assert page.daily_panel.matrix.columnCount() == 31
|
||||
|
||||
preserved = page.daily_panel.matrix.item(0, 1).text()
|
||||
repository.fail_tracking = True
|
||||
page.daily_panel.refresh_button.click()
|
||||
assert page.daily_panel.matrix.item(0, 1).text() == preserved
|
||||
assert "已保留上次数据" in page.daily_panel.state.label.text()
|
||||
|
||||
page.close()
|
||||
application.processEvents()
|
||||
|
||||
|
||||
def test_queue_date_picker_filters_the_selected_day(
|
||||
application: QApplication,
|
||||
immediate_async: None,
|
||||
@@ -394,6 +556,69 @@ def test_silent_queue_polls_reuse_rows_and_do_not_restart_detail_or_ai(
|
||||
application.processEvents()
|
||||
|
||||
|
||||
def test_silent_poll_replaces_only_the_queue_row_with_visible_changes(
|
||||
application: QApplication,
|
||||
immediate_async: None,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
original_queue_row = reception_module.QueueRow
|
||||
constructed: list[int] = []
|
||||
|
||||
class CountingQueueRow(original_queue_row):
|
||||
def __init__(self, record: Any, parent: QWidget | None = None) -> None:
|
||||
constructed.append(int(record["id"]))
|
||||
super().__init__(record, parent)
|
||||
|
||||
monkeypatch.setattr(reception_module, "QueueRow", CountingQueueRow)
|
||||
|
||||
class Repository:
|
||||
calls = 0
|
||||
|
||||
def list_appointments(self, **_kwargs: Any) -> dict[str, Any]:
|
||||
self.calls += 1
|
||||
rows = [
|
||||
{
|
||||
"id": index,
|
||||
"diagnosis_id": 200 + index,
|
||||
"patient_id": 100 + index,
|
||||
"patient_name": f"患者{index}",
|
||||
"clinical_diagnosis": "消渴",
|
||||
"status": 1,
|
||||
}
|
||||
for index in range(1, 4)
|
||||
]
|
||||
if self.calls > 1:
|
||||
rows[1]["clinical_diagnosis"] = "消渴 · 气阴两虚"
|
||||
return {"lists": rows, "count": 3}
|
||||
|
||||
def get_reception(self, appointment_id: int) -> dict[str, Any]:
|
||||
return {
|
||||
"appointment": {"id": appointment_id, "patient_id": 100 + appointment_id},
|
||||
"diagnosis": {
|
||||
"id": 200 + appointment_id,
|
||||
"patient_id": 100 + appointment_id,
|
||||
},
|
||||
}
|
||||
|
||||
page = ReceptionPage(Repository(), PermissionSet([]))
|
||||
page.refresh()
|
||||
items = [page.queue_list.item(index) for index in range(3)]
|
||||
widgets = [page.queue_list.itemWidget(item) for item in items]
|
||||
assert constructed == [1, 2, 3]
|
||||
|
||||
page.refresh(silent=True)
|
||||
|
||||
assert all(page.queue_list.item(index) is items[index] for index in range(3))
|
||||
assert page.queue_list.itemWidget(items[0]) is widgets[0]
|
||||
assert page.queue_list.itemWidget(items[1]) is not widgets[1]
|
||||
assert page.queue_list.itemWidget(items[2]) is widgets[2]
|
||||
assert constructed == [1, 2, 3, 2]
|
||||
changed_row = page.queue_list.itemWidget(items[1])
|
||||
assert changed_row.findChild(QLabel, "ReceptionQueueSubline").text() == "消渴 · 气阴两虚"
|
||||
page.close()
|
||||
application.processEvents()
|
||||
|
||||
|
||||
def test_timer_poll_does_not_supersede_an_in_flight_queue_request(
|
||||
application: QApplication,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
@@ -905,9 +1130,10 @@ def test_queue_worker_uses_frozen_widget_snapshot(
|
||||
"status": 1,
|
||||
"start_date": date.today().isoformat(),
|
||||
"end_date": date.today().isoformat(),
|
||||
"page_no": 1,
|
||||
"page_size": 15,
|
||||
"patient_name": "甲患者",
|
||||
"page_no": 1,
|
||||
"page_size": 15,
|
||||
"patient_name": "甲患者",
|
||||
"include_status_counts": 1,
|
||||
}
|
||||
]
|
||||
page.close()
|
||||
@@ -1094,7 +1320,10 @@ 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 470 <= left.height() <= 520
|
||||
assert left.height() < 470
|
||||
assert page.ai_analysis_card.minimumHeight() == 0
|
||||
assert page.ai_analysis_card.maximumHeight() > 520
|
||||
assert page.ai_analysis_card.findChildren(QScrollArea) == []
|
||||
assert left.height() == right.height()
|
||||
assert 0 <= right.left() - left.right() - 1 <= 2
|
||||
assert abs(left.width() * 5 - right.width() * 4) <= 10
|
||||
@@ -1464,7 +1693,6 @@ def test_ai_analysis_dialog_switches_complete_cached_payloads_without_requests(
|
||||
"qwen 风险项目 1",
|
||||
"qwen 风险项目 2",
|
||||
"qwen 风险项目 3",
|
||||
"qwen 风险项目 4",
|
||||
]
|
||||
calls_before_dialog = list(repository.analysis_calls)
|
||||
page.ai_analysis_expand_button.click()
|
||||
|
||||
Reference in New Issue
Block a user