Improve cloud tts tests (#106427)

This commit is contained in:
Martin Hjelmare 2023-12-27 08:48:07 +01:00 committed by GitHub
parent 2cc6fd1afb
commit 59a01da0ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 148 additions and 47 deletions

View File

@ -152,6 +152,11 @@ def mock_tts_cache_dir_autouse(mock_tts_cache_dir):
return 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) @pytest.fixture(autouse=True)
def mock_user_data(): def mock_user_data():
"""Mock os module.""" """Mock os module."""

View File

@ -1,23 +1,35 @@
"""Tests for cloud tts.""" """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 pytest
import voluptuous as vol 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.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
@pytest.fixture @pytest.fixture(autouse=True)
def cloud_with_prefs(cloud_prefs): async def internal_url_mock(hass: HomeAssistant) -> None:
"""Return a cloud mock with prefs.""" """Mock internal URL of the instance."""
return Mock(client=Mock(prefs=cloud_prefs)) await async_process_ha_core_config(
hass,
{"internal_url": "http://example.local:8123"},
)
def test_default_exists() -> None: def test_default_exists() -> None:
"""Test our default language exists.""" """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: def test_schema() -> None:
@ -42,54 +54,138 @@ def test_schema() -> None:
tts.PLATFORM_SCHEMA({"platform": "cloud"}) 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( 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: ) -> None:
"""Test cloud provider uses the preferences.""" """Test cloud provider uses the preferences."""
assert cloud_prefs.tts_default_voice == ("en-US", "female") assert await async_setup_component(hass, "homeassistant", {})
assert await async_setup_component(hass, TTS_DOMAIN, {TTS_DOMAIN: platform_config})
tts_info = {"platform_loaded": Mock()} assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
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"))
await hass.async_block_till_done() await hass.async_block_till_done()
assert provider_pref.default_language == "nl-NL" assert cloud.client.prefs.tts_default_voice == ("en-US", "female")
assert provider_pref.default_options == {"gender": "male", "audio_output": "mp3"}
assert provider_conf.default_language == "fr-FR" on_start_callback = cloud.register_on_start.call_args[0][0]
assert provider_conf.default_options == {"gender": "female", "audio_output": "mp3"} 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.""" """Test cloud provider."""
tts_info = {"platform_loaded": Mock()} assert await async_setup_component(hass, "homeassistant", {})
provider = await tts.async_get_engine( assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
Mock(data={const.DOMAIN: cloud_with_prefs}), None, tts_info 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
@pytest.mark.parametrize(
("data", "expected_url_suffix"),
[
({"platform": DOMAIN}, DOMAIN),
({"engine_id": DOMAIN}, DOMAIN),
],
) )
assert provider.supported_options == ["gender", "voice", "audio_output"] @pytest.mark.parametrize(
assert "nl-NL" in provider.supported_languages ("mock_process_tts_return_value", "mock_process_tts_side_effect"),
assert tts.Voice( [
"ColetteNeural", "ColetteNeural" (b"", None),
) in provider.async_get_supported_voices("nl-NL") (None, VoiceError("Boom!")),
],
)
async def test_get_tts_audio(cloud_with_prefs) -> None: 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.""" """Test cloud provider."""
tts_info = {"platform_loaded": Mock()} mock_process_tts = AsyncMock(
provider = await tts.async_get_engine( return_value=mock_process_tts_return_value,
Mock(data={const.DOMAIN: cloud_with_prefs}), None, tts_info side_effect=mock_process_tts_side_effect,
) )
assert provider.supported_options == ["gender", "voice", "audio_output"] cloud.voice.process_tts = mock_process_tts
assert "nl-NL" in provider.supported_languages 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"