更新
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""Tests for friendly_error's handling of AI upstream error messages.
|
||||
|
||||
These cover the DifyChatService error_code → user-facing copy mapping that
|
||||
the doctor workstation must apply when the server-side AI assistant returns
|
||||
``ok=false`` with a Chinese ``error`` string. The legacy behaviour simply
|
||||
echoed the raw text, which made incidents like ``UPSTREAM_REJECTED`` opaque
|
||||
to clinicians.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from doctor_workstation.core.errors import (
|
||||
ApiBusinessError,
|
||||
ApiHttpError,
|
||||
ApiProtocolError,
|
||||
ApiTimeoutError,
|
||||
ApiTransportError,
|
||||
AuthenticationExpiredError,
|
||||
)
|
||||
from doctor_workstation.ui.widgets import _ai_upstream_hint, friendly_error
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("raw", "expected_fragment"),
|
||||
[
|
||||
# 当上游 Dify 服务 HTTP 4xx 时返回的"UPSTREAM_REJECTED"文案。
|
||||
("模型未能处理本次请求", "稍后重试"),
|
||||
("AI 服务凭据无效或无权限", "联系管理员"),
|
||||
("AI 服务配置无效", "联系管理员"),
|
||||
("AI 报告功能未启用", "联系管理员"),
|
||||
("不支持的 AI 模型", "联系管理员"),
|
||||
("该模型服务尚未完整配置", "联系管理员"),
|
||||
("病例数据编码失败", "联系管理员"),
|
||||
("无法初始化 AI 请求", "联系管理员"),
|
||||
("暂时无法连接 AI 服务,请稍后重试", "网络"),
|
||||
("模型服务繁忙,请稍后重试", "稍后重试"),
|
||||
("模型响应超时,请稍后重试", "稍后重试"),
|
||||
("AI 助手未返回内容,请重试", "稍后重试"),
|
||||
],
|
||||
)
|
||||
def test_friendly_error_translates_ai_upstream_strings(raw: str, expected_fragment: str) -> None:
|
||||
"""Upstream Dify messages should be replaced with actionable copy."""
|
||||
|
||||
rendered = friendly_error(raw)
|
||||
assert expected_fragment in rendered
|
||||
# 上游原文不应该再原样透传。
|
||||
assert rendered != raw
|
||||
|
||||
|
||||
def test_friendly_error_passes_through_unrelated_chinese_text() -> None:
|
||||
"""中文业务文案不属于上游错误时,必须原样透传,避免误伤。"""
|
||||
|
||||
text = "AI 返回的处方草稿格式不符合要求,请重试"
|
||||
assert friendly_error(text) == text
|
||||
|
||||
|
||||
def test_friendly_error_handles_api_business_error_with_upstream_payload() -> None:
|
||||
"""服务端通过 ApiBusinessError(code=0) 透传时仍要触发映射。"""
|
||||
|
||||
err = ApiBusinessError("模型未能处理本次请求", code=0)
|
||||
rendered = friendly_error(err)
|
||||
assert "稍后重试" in rendered
|
||||
assert "联系管理员" in rendered
|
||||
|
||||
|
||||
def test_friendly_error_keeps_existing_transport_mappings() -> None:
|
||||
"""对网络/超时/未授权等既有规则的回归保护。"""
|
||||
|
||||
assert "证书" in friendly_error(Exception("certificate_verify_failed"))
|
||||
assert "网络" in friendly_error(ApiTransportError("connection refused"))
|
||||
assert "重新登录" in friendly_error(AuthenticationExpiredError("expired"))
|
||||
timeout_render = friendly_error(ApiTimeoutError("timed out"))
|
||||
assert "超时" in timeout_render
|
||||
http_render = friendly_error(ApiHttpError("boom", status_code=503))
|
||||
assert "503" in http_render
|
||||
protocol_render = friendly_error(ApiProtocolError("api response envelope invalid"))
|
||||
assert "数据格式" in protocol_render
|
||||
|
||||
|
||||
def test_friendly_error_returns_default_for_empty_string() -> None:
|
||||
"""Fallback 应当落到"操作未完成"而不是崩溃。"""
|
||||
|
||||
assert friendly_error(SimpleNamespace(__str__=lambda self: " ")) == "操作未完成,请稍后重试。"
|
||||
|
||||
|
||||
def test_ai_upstream_hint_returns_none_for_unrelated_text() -> None:
|
||||
assert _ai_upstream_hint("AI 返回的处方草稿格式不符合要求,请重试") is None
|
||||
assert _ai_upstream_hint("connection refused") is None
|
||||
assert _ai_upstream_hint("") is None
|
||||
Reference in New Issue
Block a user