fix: valida mensagens e sequência de eventos WebSocket

This commit is contained in:
alex alves
2026-11-03 10:49:53 -03:00
parent 82553d86c7
commit 153b2986b7
2 changed files with 156 additions and 6 deletions

View File

@@ -1044,7 +1044,7 @@ def test_websocket_interrupt_timeout_preserves_active_turn():
next_response = websocket.receive_json()
assert next_response["type"] == "error"
assert next_response["code"] == "STT_START_FAILED"
assert next_response["code"] == "INVALID_TURN"
def test_websocket_interrupt_during_agent():
@@ -1625,7 +1625,7 @@ def test_websocket_audio_start_abort_failure_is_not_retryable():
next_response = websocket.receive_json()
assert next_response["type"] == "error"
assert next_response["code"] == "STT_START_FAILED"
assert next_response["code"] == "INVALID_TURN"
@@ -2410,3 +2410,121 @@ def test_websocket_interrupt_wins_pending_tts_completion():
assert response["type"] == "interrupted"
assert response["turn_id"] == next_turn["turn_id"]
@pytest.mark.parametrize("session_started", [False, True])
@pytest.mark.parametrize(
"payload",
[
None,
[],
"text",
42,
True,
{},
{"type": None},
{"type": 42},
{"type": ""},
{"type": " "},
],
)
def test_websocket_rejects_invalid_message_and_remains_usable(
payload,
session_started,
):
with client.websocket_connect("/ws/audio") as websocket:
if session_started:
websocket.send_json({"type": "session.start"})
assert websocket.receive_json()["type"] == "session.ready"
websocket.send_json(payload)
error = websocket.receive_json()
assert error["type"] == "error"
assert error["code"] == "INVALID_MESSAGE"
if session_started:
websocket.send_json({"type": "session.end"})
assert websocket.receive_json()["type"] == "session.ended"
else:
websocket.send_json({"type": "session.start"})
assert websocket.receive_json()["type"] == "session.ready"
@pytest.mark.parametrize(
"event_type",
[
"audio.start",
"audio.chunk",
"audio.stop",
"interrupt",
"session.end",
],
)
def test_websocket_requires_session_before_control_events(event_type):
with client.websocket_connect("/ws/audio") as websocket:
websocket.send_json(
{
"type": event_type,
"turn_id": 1,
"sequence_number": 0,
}
)
error = websocket.receive_json()
assert error["type"] == "error"
assert error["code"] == "SESSION_NOT_FOUND"
websocket.send_json({"type": "session.start"})
assert websocket.receive_json()["type"] == "session.ready"
@pytest.mark.parametrize(
"text",
["{", "", '{type: "session.start"}'],
)
def test_websocket_rejects_malformed_json_and_remains_usable(text):
with client.websocket_connect("/ws/audio") as websocket:
websocket.send_text(text)
error = websocket.receive_json()
assert error["type"] == "error"
assert error["code"] == "INVALID_MESSAGE"
websocket.send_json({"type": "session.start"})
assert websocket.receive_json()["type"] == "session.ready"
def test_websocket_duplicate_audio_start_preserves_active_turn():
created_stt.clear()
created_turn_managers.clear()
with client.websocket_connect("/ws/audio") as websocket:
websocket.send_json({"type": "session.start"})
assert websocket.receive_json()["type"] == "session.ready"
websocket.send_json({"type": "audio.start"})
started = websocket.receive_json()
assert started["type"] == "turn.started"
turn_id = started["turn_id"]
stt = created_stt[0]
turn = created_turn_managers[0].active_turn
websocket.send_json({"type": "audio.start"})
error = websocket.receive_json()
assert error["type"] == "error"
assert error["code"] == "INVALID_TURN"
assert error["turn_id"] == turn_id
assert len(created_stt) == 1
assert stt._started is True
assert created_turn_managers[0].active_turn is turn
assert turn.state == TurnState.LISTENING
websocket.send_json(
{"type": "interrupt", "turn_id": turn_id}
)
assert websocket.receive_json()["type"] == "interrupted"
assert stt._started is False
assert created_turn_managers[0].active_turn is None