66 lines
2.6 KiB
Python
66 lines
2.6 KiB
Python
"""ActionState 统一响应信封测试."""
|
|
|
|
from src.ai.models.action_state import ActionState, ErrorDetail
|
|
from src.ai.models.chat import ChatData, ChatResponse, Usage
|
|
|
|
|
|
class TestActionState:
|
|
"""ActionState 信封测试."""
|
|
|
|
def test_ok_success(self) -> None:
|
|
"""ok() 返回成功响应."""
|
|
data = ChatData(content="hello", model="gpt-4o", usage=Usage())
|
|
resp = ActionState.ok(data)
|
|
assert resp.success is True
|
|
assert resp.data is not None
|
|
assert resp.data.content == "hello"
|
|
assert resp.error is None
|
|
|
|
def test_error_response(self) -> None:
|
|
"""error_response() 返回错误响应."""
|
|
resp = ActionState.error_response(
|
|
code="AI_LLM_UNAVAILABLE",
|
|
message="all providers failed",
|
|
details={"tried": ["openai"]},
|
|
trace_id="req-123",
|
|
)
|
|
assert resp.success is False
|
|
assert resp.data is None
|
|
assert resp.error is not None
|
|
assert resp.error.code == "AI_LLM_UNAVAILABLE"
|
|
assert resp.error.message == "all providers failed"
|
|
assert resp.error.details == {"tried": ["openai"]}
|
|
assert resp.error.trace_id == "req-123"
|
|
|
|
def test_degraded_sets_flags(self) -> None:
|
|
"""degraded() 在 data 上设置 degraded + degraded_reason."""
|
|
data = ChatData(content="fallback", model="gpt-4o", usage=Usage())
|
|
resp = ActionState.degraded(data, "llm unavailable")
|
|
assert resp.success is True
|
|
assert resp.error is None
|
|
assert resp.data is not None
|
|
assert resp.data.degraded is True
|
|
assert resp.data.degraded_reason == "llm unavailable"
|
|
|
|
def test_error_detail_alias(self) -> None:
|
|
"""ErrorDetail 支持 traceId alias."""
|
|
err = ErrorDetail(code="AI_INTERNAL_ERROR", message="boom", trace_id="t-1")
|
|
assert err.trace_id == "t-1"
|
|
# 序列化使用 alias
|
|
dumped = err.model_dump(by_alias=True)
|
|
assert dumped["traceId"] == "t-1"
|
|
|
|
def test_chat_response_inherits_action_state(self) -> None:
|
|
"""ChatResponse 继承 ActionState[ChatData]."""
|
|
data = ChatData(content="hi", model="m", usage=Usage())
|
|
resp = ChatResponse.ok(data)
|
|
assert resp.success is True
|
|
assert resp.data.content == "hi"
|
|
|
|
def test_error_response_without_optional_fields(self) -> None:
|
|
"""error_response() 可选字段缺省."""
|
|
resp = ActionState.error_response("AI_INTERNAL_ERROR", "fail")
|
|
assert resp.error is not None
|
|
assert resp.error.details is None
|
|
assert resp.error.trace_id is None
|