2023-04-17 17:01:50 +00:00
|
|
|
"""Provide common tests tools for tts."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
import voluptuous as vol
|
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
from homeassistant.components import media_source
|
2023-04-17 17:01:50 +00:00
|
|
|
from homeassistant.components.tts import (
|
|
|
|
CONF_LANG,
|
2023-04-21 02:55:46 +00:00
|
|
|
DOMAIN as TTS_DOMAIN,
|
2023-04-17 17:01:50 +00:00
|
|
|
PLATFORM_SCHEMA,
|
|
|
|
Provider,
|
2023-04-21 02:55:46 +00:00
|
|
|
TextToSpeechEntity,
|
2023-04-17 17:01:50 +00:00
|
|
|
TtsAudioType,
|
2023-04-22 00:41:14 +00:00
|
|
|
Voice,
|
2023-04-17 17:01:50 +00:00
|
|
|
)
|
2023-04-21 02:55:46 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2023-04-19 11:47:49 +00:00
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2023-04-21 02:55:46 +00:00
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2023-04-17 17:01:50 +00:00
|
|
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
2023-04-21 02:55:46 +00:00
|
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
|
|
|
|
from tests.common import (
|
|
|
|
MockConfigEntry,
|
|
|
|
MockModule,
|
|
|
|
MockPlatform,
|
|
|
|
mock_integration,
|
|
|
|
mock_platform,
|
|
|
|
)
|
2023-04-17 17:01:50 +00:00
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
DEFAULT_LANG = "en_US"
|
2023-04-20 12:56:50 +00:00
|
|
|
SUPPORT_LANGUAGES = ["de_CH", "de_DE", "en_GB", "en_US"]
|
2023-04-21 02:55:46 +00:00
|
|
|
TEST_DOMAIN = "test"
|
2023-04-17 17:01:50 +00:00
|
|
|
|
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
async def get_media_source_url(hass: HomeAssistant, media_content_id: str) -> str:
|
|
|
|
"""Get the media source url."""
|
|
|
|
if media_source.DOMAIN not in hass.config.components:
|
|
|
|
assert await async_setup_component(hass, media_source.DOMAIN, {})
|
2023-04-17 17:01:50 +00:00
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
resolved = await media_source.async_resolve_media(hass, media_content_id, None)
|
|
|
|
return resolved.url
|
|
|
|
|
|
|
|
|
|
|
|
class BaseProvider:
|
2023-04-17 17:01:50 +00:00
|
|
|
"""Test speech API provider."""
|
|
|
|
|
|
|
|
def __init__(self, lang: str) -> None:
|
|
|
|
"""Initialize test provider."""
|
|
|
|
self._lang = lang
|
|
|
|
|
|
|
|
@property
|
|
|
|
def default_language(self) -> str:
|
|
|
|
"""Return the default language."""
|
|
|
|
return self._lang
|
|
|
|
|
|
|
|
@property
|
|
|
|
def supported_languages(self) -> list[str]:
|
|
|
|
"""Return list of supported languages."""
|
|
|
|
return SUPPORT_LANGUAGES
|
|
|
|
|
2023-04-19 11:47:49 +00:00
|
|
|
@callback
|
2023-04-22 00:41:14 +00:00
|
|
|
def async_get_supported_voices(self, language: str) -> list[Voice] | None:
|
2023-04-19 11:47:49 +00:00
|
|
|
"""Return list of supported languages."""
|
|
|
|
if language == "en-US":
|
2023-04-22 00:41:14 +00:00
|
|
|
return [
|
|
|
|
Voice("james_earl_jones", "James Earl Jones"),
|
|
|
|
Voice("fran_drescher", "Fran Drescher"),
|
|
|
|
]
|
2023-04-19 11:47:49 +00:00
|
|
|
return None
|
|
|
|
|
2023-04-17 17:01:50 +00:00
|
|
|
@property
|
|
|
|
def supported_options(self) -> list[str]:
|
|
|
|
"""Return list of supported options like voice, emotions."""
|
|
|
|
return ["voice", "age"]
|
|
|
|
|
|
|
|
def get_tts_audio(
|
2023-05-24 19:02:55 +00:00
|
|
|
self, message: str, language: str, options: dict[str, Any]
|
2023-04-17 17:01:50 +00:00
|
|
|
) -> TtsAudioType:
|
|
|
|
"""Load TTS dat."""
|
|
|
|
return ("mp3", b"")
|
|
|
|
|
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
class MockProvider(BaseProvider, Provider):
|
|
|
|
"""Test speech API provider."""
|
|
|
|
|
|
|
|
def __init__(self, lang: str) -> None:
|
|
|
|
"""Initialize test provider."""
|
|
|
|
super().__init__(lang)
|
|
|
|
self.name = "Test"
|
|
|
|
|
|
|
|
|
|
|
|
class MockTTSEntity(BaseProvider, TextToSpeechEntity):
|
|
|
|
"""Test speech API provider."""
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self) -> str:
|
|
|
|
"""Return the name of the entity."""
|
|
|
|
return "Test"
|
|
|
|
|
|
|
|
|
2023-04-17 17:01:50 +00:00
|
|
|
class MockTTS(MockPlatform):
|
|
|
|
"""A mock TTS platform."""
|
|
|
|
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
2023-04-25 15:54:42 +00:00
|
|
|
{vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES)}
|
2023-04-17 17:01:50 +00:00
|
|
|
)
|
|
|
|
|
2023-04-21 02:55:46 +00:00
|
|
|
def __init__(self, provider: MockProvider, **kwargs: Any) -> None:
|
2023-04-17 17:01:50 +00:00
|
|
|
"""Initialize."""
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self._provider = provider
|
|
|
|
|
|
|
|
async def async_get_engine(
|
|
|
|
self,
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config: ConfigType,
|
|
|
|
discovery_info: DiscoveryInfoType | None = None,
|
|
|
|
) -> Provider | None:
|
|
|
|
"""Set up a mock speech component."""
|
2023-04-21 02:55:46 +00:00
|
|
|
return self._provider
|
|
|
|
|
|
|
|
|
|
|
|
async def mock_setup(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
mock_provider: MockProvider,
|
|
|
|
) -> None:
|
|
|
|
"""Set up a test provider."""
|
|
|
|
mock_integration(hass, MockModule(domain=TEST_DOMAIN))
|
|
|
|
mock_platform(hass, f"{TEST_DOMAIN}.{TTS_DOMAIN}", MockTTS(mock_provider))
|
|
|
|
|
|
|
|
await async_setup_component(
|
|
|
|
hass, TTS_DOMAIN, {TTS_DOMAIN: {"platform": TEST_DOMAIN}}
|
|
|
|
)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
|
|
async def mock_config_entry_setup(
|
|
|
|
hass: HomeAssistant, tts_entity: MockTTSEntity
|
|
|
|
) -> MockConfigEntry:
|
|
|
|
"""Set up a test tts platform via config entry."""
|
|
|
|
|
|
|
|
async def async_setup_entry_init(
|
|
|
|
hass: HomeAssistant, config_entry: ConfigEntry
|
|
|
|
) -> bool:
|
|
|
|
"""Set up test config entry."""
|
|
|
|
await hass.config_entries.async_forward_entry_setup(config_entry, TTS_DOMAIN)
|
|
|
|
return True
|
|
|
|
|
|
|
|
async def async_unload_entry_init(
|
|
|
|
hass: HomeAssistant, config_entry: ConfigEntry
|
|
|
|
) -> bool:
|
|
|
|
"""Unload up test config entry."""
|
|
|
|
await hass.config_entries.async_forward_entry_unload(config_entry, TTS_DOMAIN)
|
|
|
|
return True
|
|
|
|
|
|
|
|
mock_integration(
|
|
|
|
hass,
|
|
|
|
MockModule(
|
|
|
|
TEST_DOMAIN,
|
|
|
|
async_setup_entry=async_setup_entry_init,
|
|
|
|
async_unload_entry=async_unload_entry_init,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
async def async_setup_entry_platform(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
|
|
|
"""Set up test tts platform via config entry."""
|
|
|
|
async_add_entities([tts_entity])
|
|
|
|
|
|
|
|
loaded_platform = MockPlatform(async_setup_entry=async_setup_entry_platform)
|
|
|
|
mock_platform(hass, f"{TEST_DOMAIN}.{TTS_DOMAIN}", loaded_platform)
|
|
|
|
|
|
|
|
config_entry = MockConfigEntry(domain=TEST_DOMAIN)
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
return config_entry
|