65 lines
2.1 KiB
Python
65 lines
2.1 KiB
Python
"""errors.py — typed errors with voice-friendly messages (plan §12)."""
|
|
|
|
from mcp_server.errors import (
|
|
AnnotationError,
|
|
ApiError,
|
|
AuthError,
|
|
ClarificationNeededError,
|
|
ErrorKind,
|
|
InsufficientStockError,
|
|
LabVoiceError,
|
|
NotFoundError,
|
|
PermissionDeniedError,
|
|
)
|
|
|
|
|
|
def test_every_error_kind_maps_to_its_class():
|
|
assert AuthError.kind is ErrorKind.AUTH
|
|
assert PermissionDeniedError.kind is ErrorKind.PERMISSION
|
|
assert NotFoundError.kind is ErrorKind.NOT_FOUND
|
|
assert ApiError.kind is ErrorKind.API
|
|
assert AnnotationError.kind is ErrorKind.ANNOTATION
|
|
assert ClarificationNeededError.kind is ErrorKind.CLARIFICATION
|
|
assert InsufficientStockError.kind is ErrorKind.INSUFFICIENT_STOCK
|
|
assert LabVoiceError.kind is ErrorKind.API
|
|
|
|
|
|
def test_kind_values_are_the_wire_strings():
|
|
assert ErrorKind.AUTH == "auth_error"
|
|
assert ErrorKind.PERMISSION == "permission_error"
|
|
assert ErrorKind.NOT_FOUND == "not_found"
|
|
assert ErrorKind.CLARIFICATION == "clarification"
|
|
assert ErrorKind.INSUFFICIENT_STOCK == "insufficient_stock"
|
|
|
|
|
|
def test_message_and_detail_are_preserved():
|
|
err = NotFoundError("Experiment 123 not found.", detail="GET /experiments/123")
|
|
assert str(err) == "Experiment 123 not found."
|
|
assert err.message == "Experiment 123 not found."
|
|
assert err.detail == "GET /experiments/123"
|
|
|
|
|
|
def test_all_labvoice_errors_share_the_base():
|
|
for cls in (
|
|
AuthError,
|
|
PermissionDeniedError,
|
|
NotFoundError,
|
|
ApiError,
|
|
AnnotationError,
|
|
ClarificationNeededError,
|
|
InsufficientStockError,
|
|
):
|
|
assert issubclass(cls, LabVoiceError)
|
|
|
|
|
|
def test_clarification_options_default_empty_and_are_preserved():
|
|
err = ClarificationNeededError("Which ethanol?")
|
|
assert err.options == []
|
|
err = ClarificationNeededError("Which ethanol?", options=["Absolute Ethanol", "96%"])
|
|
assert err.options == ["Absolute Ethanol", "96%"]
|
|
|
|
|
|
def test_error_messages_are_voice_friendly_strings():
|
|
err = PermissionDeniedError("This API key is read-only; I can't finish the step.")
|
|
assert isinstance(err.message, str) and err.message
|