feat: scaffold stentor-gateway with FastAPI voice pipeline
Initialize the stentor-gateway project with WebSocket-based voice pipeline orchestrating STT → Agent → TTS via OpenAI-compatible APIs. - Add FastAPI app with WebSocket endpoint for audio streaming - Add pipeline orchestration (stt_client, tts_client, agent_client) - Add Pydantic Settings configuration and message models - Add audio utilities for PCM/WAV conversion and resampling - Add health check endpoints - Add Dockerfile and pyproject.toml with dependencies - Add initial test suite (pipeline, STT, TTS, WebSocket) - Add comprehensive README covering gateway and ESP32 ear design - Clean up .gitignore for Python/uv project
This commit is contained in:
89
stentor-gateway/tests/test_stt_client.py
Normal file
89
stentor-gateway/tests/test_stt_client.py
Normal file
@@ -0,0 +1,89 @@
|
||||
"""Tests for the Speaches STT client."""
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from stentor.audio import pcm_to_wav
|
||||
from stentor.stt_client import STTClient
|
||||
|
||||
|
||||
class TestSTTClient:
|
||||
"""Tests for STTClient."""
|
||||
|
||||
@pytest.fixture
|
||||
def stt_client(self, settings):
|
||||
"""Create an STT client with a mock HTTP client."""
|
||||
http_client = httpx.AsyncClient()
|
||||
return STTClient(settings, http_client)
|
||||
|
||||
async def test_transcribe_success(self, settings, sample_pcm, httpx_mock):
|
||||
"""Test successful transcription."""
|
||||
httpx_mock.add_response(
|
||||
url=f"{settings.stt_url}/v1/audio/transcriptions",
|
||||
method="POST",
|
||||
json={"text": "Hello world"},
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient() as http_client:
|
||||
client = STTClient(settings, http_client)
|
||||
wav_data = pcm_to_wav(sample_pcm)
|
||||
result = await client.transcribe(wav_data)
|
||||
|
||||
assert result == "Hello world"
|
||||
|
||||
async def test_transcribe_with_language(self, settings, sample_pcm, httpx_mock):
|
||||
"""Test transcription with explicit language."""
|
||||
httpx_mock.add_response(
|
||||
url=f"{settings.stt_url}/v1/audio/transcriptions",
|
||||
method="POST",
|
||||
json={"text": "Bonjour le monde"},
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient() as http_client:
|
||||
client = STTClient(settings, http_client)
|
||||
wav_data = pcm_to_wav(sample_pcm)
|
||||
result = await client.transcribe(wav_data, language="fr")
|
||||
|
||||
assert result == "Bonjour le monde"
|
||||
|
||||
async def test_transcribe_empty_result(self, settings, sample_pcm, httpx_mock):
|
||||
"""Test transcription returning empty text."""
|
||||
httpx_mock.add_response(
|
||||
url=f"{settings.stt_url}/v1/audio/transcriptions",
|
||||
method="POST",
|
||||
json={"text": " "},
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient() as http_client:
|
||||
client = STTClient(settings, http_client)
|
||||
wav_data = pcm_to_wav(sample_pcm)
|
||||
result = await client.transcribe(wav_data)
|
||||
|
||||
assert result == ""
|
||||
|
||||
async def test_is_available_success(self, settings, httpx_mock):
|
||||
"""Test availability check when service is up."""
|
||||
httpx_mock.add_response(
|
||||
url=f"{settings.stt_url}/v1/models",
|
||||
method="GET",
|
||||
json={"models": []},
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient() as http_client:
|
||||
client = STTClient(settings, http_client)
|
||||
available = await client.is_available()
|
||||
|
||||
assert available is True
|
||||
|
||||
async def test_is_available_failure(self, settings, httpx_mock):
|
||||
"""Test availability check when service is down."""
|
||||
httpx_mock.add_exception(
|
||||
httpx.ConnectError("Connection refused"),
|
||||
url=f"{settings.stt_url}/v1/models",
|
||||
)
|
||||
|
||||
async with httpx.AsyncClient() as http_client:
|
||||
client = STTClient(settings, http_client)
|
||||
available = await client.is_available()
|
||||
|
||||
assert available is False
|
||||
Reference in New Issue
Block a user