1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-20 10:59:24 +00:00
Files
core/tests/components/elevenlabs/conftest.py
ehendrix23 d3a8f3191b Add Speech-to-Text (stt) to elevenlabs (#147838)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-10-10 17:01:22 +02:00

237 lines
6.6 KiB
Python

"""Common fixtures for the ElevenLabs text-to-speech tests."""
from collections.abc import Generator
from typing import Any
from unittest.mock import AsyncMock, patch
from elevenlabs.core import ApiError
from elevenlabs.types import GetVoicesResponse
from httpx import ConnectError
import pytest
from homeassistant.components.elevenlabs.const import (
CONF_MODEL,
CONF_STT_AUTO_LANGUAGE,
CONF_STT_MODEL,
CONF_VOICE,
DEFAULT_SIMILARITY,
DOMAIN,
)
from homeassistant.const import CONF_API_KEY
from homeassistant.core import HomeAssistant
from .const import MOCK_MODELS, MOCK_VOICES
from tests.common import MockConfigEntry
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.elevenlabs.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
def _client_mock():
client_mock = AsyncMock()
client_mock.voices.get_all.return_value = GetVoicesResponse(voices=MOCK_VOICES)
client_mock.models.list.return_value = MOCK_MODELS
return client_mock
@pytest.fixture
def mock_async_client() -> Generator[AsyncMock]:
"""Override async ElevenLabs client."""
with (
patch(
"homeassistant.components.elevenlabs.AsyncElevenLabs",
return_value=_client_mock(),
) as mock_async_client,
patch(
"homeassistant.components.elevenlabs.config_flow.AsyncElevenLabs",
new=mock_async_client,
),
patch(
"homeassistant.components.elevenlabs.tts.AsyncElevenLabs",
new=mock_async_client,
),
):
yield mock_async_client
@pytest.fixture
def mock_async_client_api_error() -> Generator[AsyncMock]:
"""Override async ElevenLabs client with ApiError side effect."""
client_mock = _client_mock()
api_error = ApiError()
api_error.body = {
"detail": {"status": "invalid_api_key", "message": "API key is invalid"}
}
client_mock.models.list.side_effect = api_error
client_mock.voices.get_all.side_effect = api_error
with (
patch(
"homeassistant.components.elevenlabs.AsyncElevenLabs",
return_value=client_mock,
) as mock_async_client,
patch(
"homeassistant.components.elevenlabs.config_flow.AsyncElevenLabs",
new=mock_async_client,
),
):
yield mock_async_client
@pytest.fixture
def mock_async_client_voices_error() -> Generator[AsyncMock]:
"""Override async ElevenLabs client with ApiError side effect."""
client_mock = _client_mock()
api_error = ApiError()
api_error.body = {
"detail": {
"status": "voices_unauthorized",
"message": "API is unauthorized for voices",
}
}
client_mock.voices.get_all.side_effect = api_error
with patch(
"homeassistant.components.elevenlabs.config_flow.AsyncElevenLabs",
return_value=client_mock,
) as mock_async_client:
yield mock_async_client
@pytest.fixture
def mock_async_client_models_error() -> Generator[AsyncMock]:
"""Override async ElevenLabs client with ApiError side effect."""
client_mock = _client_mock()
api_error = ApiError()
api_error.body = {
"detail": {
"status": "models_unauthorized",
"message": "API is unauthorized for models",
}
}
client_mock.models.list.side_effect = api_error
with patch(
"homeassistant.components.elevenlabs.config_flow.AsyncElevenLabs",
return_value=client_mock,
) as mock_async_client:
yield mock_async_client
@pytest.fixture
def mock_async_client_connect_error() -> Generator[AsyncMock]:
"""Override async ElevenLabs client."""
client_mock = _client_mock()
client_mock.models.list.side_effect = ConnectError("Unknown")
client_mock.voices.get_all.side_effect = ConnectError("Unknown")
with (
patch(
"homeassistant.components.elevenlabs.AsyncElevenLabs",
return_value=client_mock,
) as mock_async_client,
patch(
"homeassistant.components.elevenlabs.config_flow.AsyncElevenLabs",
new=mock_async_client,
),
):
yield mock_async_client
async def mock_config_entry_setup(
hass: HomeAssistant, config_data: dict[str, Any], config_options: dict[str, Any]
) -> None:
"""Mock config entry setup."""
default_config_data = {
CONF_API_KEY: "api_key",
}
default_config_options = {
CONF_VOICE: "voice1",
CONF_MODEL: "model1",
CONF_STT_MODEL: "stt_model1",
CONF_STT_AUTO_LANGUAGE: False,
}
config_entry = MockConfigEntry(
domain=DOMAIN,
data=default_config_data | config_data,
options=default_config_options | config_options,
)
config_entry.add_to_hass(hass)
client_mock = AsyncMock()
client_mock.voices.get_all.return_value = GetVoicesResponse(voices=MOCK_VOICES)
client_mock.models.list.return_value = MOCK_MODELS
stt_mock = AsyncMock()
stt_mock.convert.return_value = AsyncMock(
text="hello world", language_code="en", language_probability=0.95
)
client_mock.speech_to_text = stt_mock
with patch(
"homeassistant.components.elevenlabs.AsyncElevenLabs", return_value=client_mock
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
@pytest.fixture(name="setup")
async def setup_fixture(
hass: HomeAssistant,
config_data: dict[str, Any],
config_options: dict[str, Any],
mock_async_client: AsyncMock,
) -> AsyncMock:
"""Set up the test environment."""
await mock_config_entry_setup(hass, config_data, config_options)
await hass.async_block_till_done()
return mock_async_client
@pytest.fixture
def mock_entry() -> MockConfigEntry:
"""Mock a config entry."""
entry = MockConfigEntry(
domain="elevenlabs",
data={
CONF_API_KEY: "api_key",
},
options={
CONF_MODEL: "model1",
CONF_VOICE: "voice1",
CONF_STT_MODEL: "stt_model1",
CONF_STT_AUTO_LANGUAGE: False,
},
)
entry.models = {
"model1": "model1",
}
entry.voices = {"voice1": "voice1"}
entry.stt_models = {"stt_model1": "stt_model1"}
return entry
@pytest.fixture(name="config_data")
def config_data_fixture() -> dict[str, Any]:
"""Return config data."""
return {}
@pytest.fixture(name="config_options")
def config_options_fixture() -> dict[str, Any]:
"""Return config options."""
return {}
@pytest.fixture
def mock_similarity():
"""Mock similarity."""
return DEFAULT_SIMILARITY / 2