After M6.5 deletion of run_floating_stream and the frame dispatch, WsFrameType.floating_request/floating_domain, WsFloatingRequest, WsFloatingDomain, WsFloatingScope, WsDomain, and the StreamFormatter's floating_domain branch were left as dead protocol surface. Remove them, along with the corresponding test cases in test_schemas_v3.py and test_output_formatter.py.
141 lines
4.3 KiB
Python
141 lines
4.3 KiB
Python
"""Tests for v3 WebSocket frame protocol schemas."""
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from app.schemas import (
|
|
WsFrameType,
|
|
WsHomeRequest,
|
|
WsStreamEnd,
|
|
WsStreamStart,
|
|
WsStreamText,
|
|
)
|
|
|
|
|
|
# ── WsFrameType ───────────────────────────────────────────────────────
|
|
|
|
|
|
def test_v3_frame_types_exist():
|
|
v3_types = [
|
|
"home_request",
|
|
"stream_start",
|
|
"stream_text",
|
|
"stream_end",
|
|
"data_request",
|
|
"data_response",
|
|
"mutation",
|
|
]
|
|
for name in v3_types:
|
|
assert hasattr(WsFrameType, name), f"WsFrameType missing: {name}"
|
|
assert WsFrameType[name].value == name
|
|
|
|
|
|
def test_v2_frame_types_still_exist():
|
|
"""Backward compat: v2 types must remain."""
|
|
v2_types = [
|
|
"chat_request",
|
|
"text_chunk",
|
|
"tool_call",
|
|
"tool_result",
|
|
"final",
|
|
"ping",
|
|
"device_hello",
|
|
]
|
|
for name in v2_types:
|
|
assert hasattr(WsFrameType, name), f"v2 WsFrameType missing: {name}"
|
|
|
|
|
|
# ── WsHomeRequest ─────────────────────────────────────────────────────
|
|
|
|
|
|
def test_home_request_defaults():
|
|
frame = WsHomeRequest(message="Hello")
|
|
assert frame.type == WsFrameType.home_request
|
|
assert frame.message == "Hello"
|
|
assert frame.conversation_history == []
|
|
|
|
|
|
def test_home_request_with_history():
|
|
history = [{"role": "user", "content": "Hi"}, {"role": "assistant", "content": "Hello!"}]
|
|
frame = WsHomeRequest(message="Follow up", conversation_history=history)
|
|
assert frame.conversation_history == history
|
|
|
|
|
|
def test_home_request_serializes():
|
|
frame = WsHomeRequest(message="Test")
|
|
data = frame.model_dump()
|
|
assert data["type"] == "home_request"
|
|
assert data["message"] == "Test"
|
|
assert data["conversation_history"] == []
|
|
|
|
|
|
def test_home_request_deserializes():
|
|
raw = {"type": "home_request", "message": "Hi there"}
|
|
frame = WsHomeRequest.model_validate(raw)
|
|
assert frame.message == "Hi there"
|
|
|
|
|
|
def test_home_request_requires_message():
|
|
with pytest.raises(ValidationError):
|
|
WsHomeRequest.model_validate({"type": "home_request"})
|
|
|
|
|
|
# ── WsStreamStart ─────────────────────────────────────────────────────
|
|
|
|
|
|
def test_stream_start():
|
|
frame = WsStreamStart(request_id="req-abc")
|
|
assert frame.type == WsFrameType.stream_start
|
|
assert frame.request_id == "req-abc"
|
|
|
|
|
|
def test_stream_start_serializes():
|
|
data = WsStreamStart(request_id="r1").model_dump()
|
|
assert data == {"type": "stream_start", "request_id": "r1"}
|
|
|
|
|
|
def test_stream_start_deserializes():
|
|
frame = WsStreamStart.model_validate({"type": "stream_start", "request_id": "r1"})
|
|
assert frame.request_id == "r1"
|
|
|
|
|
|
# ── WsStreamText ──────────────────────────────────────────────────────
|
|
|
|
|
|
def test_stream_text():
|
|
frame = WsStreamText(request_id="r1", chunk="Hello ")
|
|
assert frame.type == WsFrameType.stream_text
|
|
assert frame.chunk == "Hello "
|
|
|
|
|
|
def test_stream_text_serializes():
|
|
data = WsStreamText(request_id="r1", chunk="word").model_dump()
|
|
assert data == {"type": "stream_text", "request_id": "r1", "chunk": "word"}
|
|
|
|
|
|
def test_stream_text_deserializes():
|
|
raw = {"type": "stream_text", "request_id": "r2", "chunk": "test"}
|
|
frame = WsStreamText.model_validate(raw)
|
|
assert frame.chunk == "test"
|
|
|
|
|
|
# ── WsStreamEnd ───────────────────────────────────────────────────────
|
|
|
|
|
|
def test_stream_end_defaults():
|
|
frame = WsStreamEnd(request_id="r1")
|
|
assert frame.type == WsFrameType.stream_end
|
|
|
|
|
|
def test_stream_end_serializes():
|
|
data = WsStreamEnd(request_id="r2").model_dump()
|
|
assert data == {"type": "stream_end", "request_id": "r2"}
|
|
|
|
|
|
def test_stream_end_deserializes():
|
|
raw = {"type": "stream_end", "request_id": "r3"}
|
|
frame = WsStreamEnd.model_validate(raw)
|
|
assert frame.request_id == "r3"
|
|
|
|
|