"""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"