feat: establish voice assistant V1 baseline
This commit is contained in:
194
tests/test_turn_manager.py
Normal file
194
tests/test_turn_manager.py
Normal file
@@ -0,0 +1,194 @@
|
||||
import pytest
|
||||
|
||||
from voice_assistant.turn_manager import (
|
||||
TurnManager,
|
||||
TurnState,
|
||||
)
|
||||
|
||||
|
||||
def test_start_turn():
|
||||
manager = TurnManager()
|
||||
|
||||
turn = manager.start(1)
|
||||
|
||||
assert turn.turn_id == 1
|
||||
assert turn.state == TurnState.LISTENING
|
||||
assert turn.partial_text == ""
|
||||
assert turn.final_text is None
|
||||
|
||||
|
||||
def test_partial_replaces_previous_partial():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
manager.on_partial(1, "Ô Alex")
|
||||
assert manager.active_turn is not None
|
||||
assert manager.active_turn.partial_text == "Ô Alex"
|
||||
|
||||
manager.on_partial(1, "Ô Alex tudo bem")
|
||||
assert manager.active_turn.partial_text == "Ô Alex tudo bem"
|
||||
|
||||
|
||||
def test_final_moves_turn_to_processing():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
manager.on_partial(1, "Ô Alex tudo bem")
|
||||
manager.on_final(1, "Ô Alex tudo bem?")
|
||||
|
||||
assert manager.active_turn is not None
|
||||
assert manager.active_turn.final_text == "Ô Alex tudo bem?"
|
||||
assert manager.active_turn.partial_text == "Ô Alex tudo bem?"
|
||||
assert manager.active_turn.state == TurnState.PROCESSING
|
||||
|
||||
|
||||
def test_cannot_start_second_turn():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match="A turn is already active",
|
||||
):
|
||||
manager.start(2)
|
||||
|
||||
|
||||
def test_cannot_stop_before_completed():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match="final transcript",
|
||||
):
|
||||
manager.stop(1)
|
||||
|
||||
|
||||
def test_interrupt():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
manager.interrupt(1)
|
||||
|
||||
assert manager.active_turn is not None
|
||||
assert (
|
||||
manager.active_turn.state
|
||||
== TurnState.INTERRUPTED
|
||||
)
|
||||
|
||||
|
||||
def test_clear_turn():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
manager.clear(1)
|
||||
|
||||
assert manager.active_turn is None
|
||||
|
||||
|
||||
def test_agent_response_moves_turn_to_speaking():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
manager.on_final(
|
||||
1,
|
||||
"Qual o horário?",
|
||||
)
|
||||
|
||||
manager.on_agent_response(1)
|
||||
|
||||
assert manager.active_turn is not None
|
||||
assert (
|
||||
manager.active_turn.state
|
||||
== TurnState.SPEAKING
|
||||
)
|
||||
|
||||
|
||||
def test_tts_completion_moves_turn_to_completed():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
manager.on_final(
|
||||
1,
|
||||
"Qual o horário?",
|
||||
)
|
||||
|
||||
manager.on_agent_response(1)
|
||||
manager.on_tts_complete(1)
|
||||
|
||||
assert manager.active_turn is not None
|
||||
assert (
|
||||
manager.active_turn.state
|
||||
== TurnState.COMPLETED
|
||||
)
|
||||
|
||||
|
||||
def test_agent_response_requires_processing_state():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match="turn is listening",
|
||||
):
|
||||
manager.on_agent_response(1)
|
||||
|
||||
|
||||
def test_tts_completion_requires_speaking_state():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match="turn is listening",
|
||||
):
|
||||
manager.on_tts_complete(1)
|
||||
|
||||
|
||||
def test_cannot_stop_before_completed():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match="Cannot stop turn while turn is listening",
|
||||
):
|
||||
manager.stop(1)
|
||||
|
||||
|
||||
def test_clear_removes_completed_turn():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
manager.on_final(
|
||||
1,
|
||||
"Olá!",
|
||||
)
|
||||
|
||||
manager.on_agent_response(1)
|
||||
manager.on_tts_complete(1)
|
||||
|
||||
manager.clear(1)
|
||||
|
||||
assert manager.active_turn is None
|
||||
|
||||
|
||||
def test_clear_rejects_unexpected_turn_id():
|
||||
manager = TurnManager()
|
||||
|
||||
manager.start(1)
|
||||
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="Unexpected turn_id=2",
|
||||
):
|
||||
manager.clear(2)
|
||||
Reference in New Issue
Block a user