mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Improve cloud tts tests (#106427)
This commit is contained in:
parent
2cc6fd1afb
commit
59a01da0ed
@ -152,6 +152,11 @@ def mock_tts_cache_dir_autouse(mock_tts_cache_dir):
|
||||
return mock_tts_cache_dir
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def tts_mutagen_mock_fixture_autouse(tts_mutagen_mock):
|
||||
"""Mock writing tags."""
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_user_data():
|
||||
"""Mock os module."""
|
||||
|
@ -1,23 +1,35 @@
|
||||
"""Tests for cloud tts."""
|
||||
from unittest.mock import Mock
|
||||
from collections.abc import Callable, Coroutine
|
||||
from http import HTTPStatus
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
from hass_nabucasa import voice
|
||||
from hass_nabucasa.voice import MAP_VOICE, VoiceError
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.cloud import const, tts
|
||||
from homeassistant.components.cloud import DOMAIN, const, tts
|
||||
from homeassistant.components.tts import DOMAIN as TTS_DOMAIN
|
||||
from homeassistant.components.tts.helper import get_engine_instance
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cloud_with_prefs(cloud_prefs):
|
||||
"""Return a cloud mock with prefs."""
|
||||
return Mock(client=Mock(prefs=cloud_prefs))
|
||||
@pytest.fixture(autouse=True)
|
||||
async def internal_url_mock(hass: HomeAssistant) -> None:
|
||||
"""Mock internal URL of the instance."""
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "http://example.local:8123"},
|
||||
)
|
||||
|
||||
|
||||
def test_default_exists() -> None:
|
||||
"""Test our default language exists."""
|
||||
assert const.DEFAULT_TTS_DEFAULT_VOICE in voice.MAP_VOICE
|
||||
assert const.DEFAULT_TTS_DEFAULT_VOICE in MAP_VOICE
|
||||
|
||||
|
||||
def test_schema() -> None:
|
||||
@ -42,54 +54,138 @@ def test_schema() -> None:
|
||||
tts.PLATFORM_SCHEMA({"platform": "cloud"})
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("engine_id", "platform_config"),
|
||||
[
|
||||
(
|
||||
DOMAIN,
|
||||
None,
|
||||
),
|
||||
(
|
||||
DOMAIN,
|
||||
{
|
||||
"platform": DOMAIN,
|
||||
"service_name": "yaml",
|
||||
"language": "fr-FR",
|
||||
"gender": "female",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_prefs_default_voice(
|
||||
hass: HomeAssistant, cloud_with_prefs, cloud_prefs
|
||||
hass: HomeAssistant,
|
||||
cloud: MagicMock,
|
||||
set_cloud_prefs: Callable[[dict[str, Any]], Coroutine[Any, Any, None]],
|
||||
engine_id: str,
|
||||
platform_config: dict[str, Any] | None,
|
||||
) -> None:
|
||||
"""Test cloud provider uses the preferences."""
|
||||
assert cloud_prefs.tts_default_voice == ("en-US", "female")
|
||||
|
||||
tts_info = {"platform_loaded": Mock()}
|
||||
provider_pref = await tts.async_get_engine(
|
||||
Mock(data={const.DOMAIN: cloud_with_prefs}), None, tts_info
|
||||
)
|
||||
provider_conf = await tts.async_get_engine(
|
||||
Mock(data={const.DOMAIN: cloud_with_prefs}),
|
||||
{"language": "fr-FR", "gender": "female"},
|
||||
None,
|
||||
)
|
||||
|
||||
assert provider_pref.default_language == "en-US"
|
||||
assert provider_pref.default_options == {"gender": "female", "audio_output": "mp3"}
|
||||
assert provider_conf.default_language == "fr-FR"
|
||||
assert provider_conf.default_options == {"gender": "female", "audio_output": "mp3"}
|
||||
|
||||
await cloud_prefs.async_update(tts_default_voice=("nl-NL", "male"))
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, TTS_DOMAIN, {TTS_DOMAIN: platform_config})
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert provider_pref.default_language == "nl-NL"
|
||||
assert provider_pref.default_options == {"gender": "male", "audio_output": "mp3"}
|
||||
assert provider_conf.default_language == "fr-FR"
|
||||
assert provider_conf.default_options == {"gender": "female", "audio_output": "mp3"}
|
||||
assert cloud.client.prefs.tts_default_voice == ("en-US", "female")
|
||||
|
||||
on_start_callback = cloud.register_on_start.call_args[0][0]
|
||||
await on_start_callback()
|
||||
|
||||
engine = get_engine_instance(hass, engine_id)
|
||||
|
||||
assert engine is not None
|
||||
# The platform config provider will be overridden by the discovery info provider.
|
||||
assert engine.default_language == "en-US"
|
||||
assert engine.default_options == {"gender": "female", "audio_output": "mp3"}
|
||||
|
||||
await set_cloud_prefs({"tts_default_voice": ("nl-NL", "male")})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert engine.default_language == "nl-NL"
|
||||
assert engine.default_options == {"gender": "male", "audio_output": "mp3"}
|
||||
|
||||
|
||||
async def test_provider_properties(cloud_with_prefs) -> None:
|
||||
async def test_provider_properties(
|
||||
hass: HomeAssistant,
|
||||
cloud: MagicMock,
|
||||
) -> None:
|
||||
"""Test cloud provider."""
|
||||
tts_info = {"platform_loaded": Mock()}
|
||||
provider = await tts.async_get_engine(
|
||||
Mock(data={const.DOMAIN: cloud_with_prefs}), None, tts_info
|
||||
)
|
||||
assert provider.supported_options == ["gender", "voice", "audio_output"]
|
||||
assert "nl-NL" in provider.supported_languages
|
||||
assert tts.Voice(
|
||||
"ColetteNeural", "ColetteNeural"
|
||||
) in provider.async_get_supported_voices("nl-NL")
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
on_start_callback = cloud.register_on_start.call_args[0][0]
|
||||
await on_start_callback()
|
||||
|
||||
engine = get_engine_instance(hass, DOMAIN)
|
||||
|
||||
assert engine is not None
|
||||
assert engine.supported_options == ["gender", "voice", "audio_output"]
|
||||
assert "nl-NL" in engine.supported_languages
|
||||
supported_voices = engine.async_get_supported_voices("nl-NL")
|
||||
assert supported_voices is not None
|
||||
assert tts.Voice("ColetteNeural", "ColetteNeural") in supported_voices
|
||||
supported_voices = engine.async_get_supported_voices("missing_language")
|
||||
assert supported_voices is None
|
||||
|
||||
|
||||
async def test_get_tts_audio(cloud_with_prefs) -> None:
|
||||
@pytest.mark.parametrize(
|
||||
("data", "expected_url_suffix"),
|
||||
[
|
||||
({"platform": DOMAIN}, DOMAIN),
|
||||
({"engine_id": DOMAIN}, DOMAIN),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("mock_process_tts_return_value", "mock_process_tts_side_effect"),
|
||||
[
|
||||
(b"", None),
|
||||
(None, VoiceError("Boom!")),
|
||||
],
|
||||
)
|
||||
async def test_get_tts_audio(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
cloud: MagicMock,
|
||||
data: dict[str, Any],
|
||||
expected_url_suffix: str,
|
||||
mock_process_tts_return_value: bytes | None,
|
||||
mock_process_tts_side_effect: Exception | None,
|
||||
) -> None:
|
||||
"""Test cloud provider."""
|
||||
tts_info = {"platform_loaded": Mock()}
|
||||
provider = await tts.async_get_engine(
|
||||
Mock(data={const.DOMAIN: cloud_with_prefs}), None, tts_info
|
||||
mock_process_tts = AsyncMock(
|
||||
return_value=mock_process_tts_return_value,
|
||||
side_effect=mock_process_tts_side_effect,
|
||||
)
|
||||
assert provider.supported_options == ["gender", "voice", "audio_output"]
|
||||
assert "nl-NL" in provider.supported_languages
|
||||
cloud.voice.process_tts = mock_process_tts
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
on_start_callback = cloud.register_on_start.call_args[0][0]
|
||||
await on_start_callback()
|
||||
client = await hass_client()
|
||||
|
||||
url = "/api/tts_get_url"
|
||||
data |= {"message": "There is someone at the door."}
|
||||
|
||||
req = await client.post(url, json=data)
|
||||
assert req.status == HTTPStatus.OK
|
||||
response = await req.json()
|
||||
|
||||
assert response == {
|
||||
"url": (
|
||||
"http://example.local:8123/api/tts_proxy/"
|
||||
"42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_e09b5a0968_{expected_url_suffix}.mp3"
|
||||
),
|
||||
"path": (
|
||||
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
|
||||
f"_en-us_e09b5a0968_{expected_url_suffix}.mp3"
|
||||
),
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_process_tts.call_count == 1
|
||||
assert mock_process_tts.call_args is not None
|
||||
assert mock_process_tts.call_args.kwargs["text"] == "There is someone at the door."
|
||||
assert mock_process_tts.call_args.kwargs["language"] == "en-US"
|
||||
assert mock_process_tts.call_args.kwargs["gender"] == "female"
|
||||
assert mock_process_tts.call_args.kwargs["output"] == "mp3"
|
||||
|
Loading…
x
Reference in New Issue
Block a user