Add tts entity (#91692)

* Add tts entity

* Allow passing engine id to url view

* Update async_resolve_engine

* Add and update more tests

* Fix assist pipeline tests temporarily

* Move fixtures

* Update notify platform

* Complete legacy tests

* Update media source tests

* Update async_get_text_to_speech_languages

* Address comment

---------

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
Martin Hjelmare
2023-04-20 22:55:46 -04:00
committed by GitHub
co-authored by Paulus Schoutsen
parent 458276a6a6
commit 1a18dc7425
14 changed files with 1925 additions and 644 deletions
+12 -9
View File
@@ -1,4 +1,6 @@
"""Test fixtures for voice assistant."""
from __future__ import annotations
from collections.abc import AsyncIterable, Generator
from typing import Any
from unittest.mock import AsyncMock
@@ -23,6 +25,7 @@ from tests.common import (
mock_platform,
)
from tests.components.tts.conftest import ( # noqa: F401, pylint: disable=unused-import
init_cache_dir_side_effect,
mock_get_cache_files,
mock_init_cache_dir,
)
@@ -33,11 +36,10 @@ _TRANSCRIPT = "test transcript"
class BaseProvider:
"""Mock STT provider."""
def __init__(self, hass: HomeAssistant, text: str) -> None:
def __init__(self, text: str) -> None:
"""Init test provider."""
self.hass = hass
self.text = text
self.received = []
self.received: list[bytes] = []
@property
def supported_languages(self) -> list[str]:
@@ -115,7 +117,7 @@ class MockTTSProvider(tts.Provider):
return ("mp3", b"")
class MockTTS:
class MockTTS(MockPlatform):
"""A mock TTS platform."""
PLATFORM_SCHEMA = tts.PLATFORM_SCHEMA
@@ -131,15 +133,15 @@ class MockTTS:
@pytest.fixture
async def mock_stt_provider(hass) -> MockSttProvider:
async def mock_stt_provider() -> MockSttProvider:
"""Mock STT provider."""
return MockSttProvider(hass, _TRANSCRIPT)
return MockSttProvider(_TRANSCRIPT)
@pytest.fixture
def mock_stt_provider_entity(hass) -> MockSttProviderEntity:
def mock_stt_provider_entity() -> MockSttProviderEntity:
"""Test provider entity fixture."""
return MockSttProviderEntity(hass, _TRANSCRIPT)
return MockSttProviderEntity(_TRANSCRIPT)
class MockSttPlatform(MockPlatform):
@@ -170,8 +172,9 @@ async def init_components(
mock_stt_provider: MockSttProvider,
mock_stt_provider_entity: MockSttProviderEntity,
config_flow_fixture,
init_cache_dir_side_effect, # noqa: F811
mock_get_cache_files, # noqa: F811
mock_init_cache_dir, # noqa: F811,
mock_init_cache_dir, # noqa: F811
):
"""Initialize relevant components with empty configs."""
+107 -12
View File
@@ -5,30 +5,50 @@ from typing import Any
import voluptuous as vol
from homeassistant.components import media_source
from homeassistant.components.tts import (
CONF_LANG,
DOMAIN as TTS_DOMAIN,
PLATFORM_SCHEMA,
Provider,
TextToSpeechEntity,
TtsAudioType,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.setup import async_setup_component
from tests.common import MockPlatform
SUPPORT_LANGUAGES = ["de_CH", "de_DE", "en_GB", "en_US"]
TEST_LANGUAGES = ["de", "en"]
from tests.common import (
MockConfigEntry,
MockModule,
MockPlatform,
mock_integration,
mock_platform,
)
DEFAULT_LANG = "en_US"
SUPPORT_LANGUAGES = ["de_CH", "de_DE", "en_GB", "en_US"]
TEST_DOMAIN = "test"
TEST_LANGUAGES = ["de", "en"]
class MockProvider(Provider):
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, {})
resolved = await media_source.async_resolve_media(hass, media_content_id, None)
return resolved.url
class BaseProvider:
"""Test speech API provider."""
def __init__(self, lang: str) -> None:
"""Initialize test provider."""
self._lang = lang
self.name = "Test"
@property
def default_language(self) -> str:
@@ -59,6 +79,24 @@ class MockProvider(Provider):
return ("mp3", b"")
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"
class MockTTS(MockPlatform):
"""A mock TTS platform."""
@@ -70,13 +108,9 @@ class MockTTS(MockPlatform):
}
)
def __init__(
self, provider: type[MockProvider] | None = None, **kwargs: Any
) -> None:
def __init__(self, provider: MockProvider, **kwargs: Any) -> None:
"""Initialize."""
super().__init__(**kwargs)
if provider is None:
provider = MockProvider
self._provider = provider
async def async_get_engine(
@@ -86,4 +120,65 @@ class MockTTS(MockPlatform):
discovery_info: DiscoveryInfoType | None = None,
) -> Provider | None:
"""Set up a mock speech component."""
return self._provider(config.get(CONF_LANG, DEFAULT_LANG))
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
+74 -7
View File
@@ -2,17 +2,28 @@
From http://doc.pytest.org/en/latest/example/simple.html#making-test-result-information-available-in-fixtures
"""
from unittest.mock import patch
from collections.abc import Callable, Generator
from typing import Any
from unittest.mock import MagicMock, patch
import pytest
from homeassistant.components.tts import _get_cache_files
from homeassistant.config import async_process_ha_core_config
from homeassistant.config_entries import ConfigFlow
from homeassistant.core import HomeAssistant
from .common import MockTTS
from .common import (
DEFAULT_LANG,
TEST_DOMAIN,
MockProvider,
MockTTS,
MockTTSEntity,
mock_config_entry_setup,
mock_setup,
)
from tests.common import MockModule, mock_integration, mock_platform
from tests.common import MockModule, mock_config_flow, mock_integration, mock_platform
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
@@ -37,15 +48,30 @@ def mock_get_cache_files():
@pytest.fixture(autouse=True)
def mock_init_cache_dir():
def mock_init_cache_dir(
init_cache_dir_side_effect: Any,
) -> Generator[MagicMock, None, None]:
"""Mock the TTS cache dir in memory."""
with patch(
"homeassistant.components.tts._init_tts_cache_dir",
side_effect=lambda hass, cache_dir: hass.config.path(cache_dir),
side_effect=init_cache_dir_side_effect,
) as mock_cache_dir:
yield mock_cache_dir
@pytest.fixture
def init_cache_dir_side_effect(
hass: HomeAssistant,
) -> Callable[[HomeAssistant, str], str]:
"""Return the cache dir."""
def side_effect(hass: HomeAssistant, cache_dir: str) -> str:
"""Return the cache dir."""
return hass.config.path(cache_dir)
return side_effect
@pytest.fixture
def empty_cache_dir(tmp_path, mock_init_cache_dir, mock_get_cache_files, request):
"""Mock the TTS cache dir with empty dir."""
@@ -89,7 +115,48 @@ async def internal_url_mock(hass: HomeAssistant) -> None:
@pytest.fixture
async def mock_tts(hass: HomeAssistant) -> None:
async def mock_tts(hass: HomeAssistant, mock_provider) -> None:
"""Mock TTS."""
mock_integration(hass, MockModule(domain="test"))
mock_platform(hass, "test.tts", MockTTS())
mock_platform(hass, "test.tts", MockTTS(mock_provider))
@pytest.fixture
def mock_provider() -> MockProvider:
"""Test TTS provider."""
return MockProvider(DEFAULT_LANG)
@pytest.fixture
def mock_tts_entity() -> MockTTSEntity:
"""Test TTS entity."""
return MockTTSEntity(DEFAULT_LANG)
class TTSFlow(ConfigFlow):
"""Test flow."""
@pytest.fixture(autouse=True)
def config_flow_fixture(hass: HomeAssistant) -> Generator[None, None, None]:
"""Mock config flow."""
mock_platform(hass, f"{TEST_DOMAIN}.config_flow")
with mock_config_flow(TEST_DOMAIN, TTSFlow):
yield
@pytest.fixture(name="setup")
async def setup_fixture(
hass: HomeAssistant,
request: pytest.FixtureRequest,
mock_provider: MockProvider,
mock_tts_entity: MockTTSEntity,
) -> None:
"""Set up the test environment."""
if request.param == "mock_setup":
await mock_setup(hass, mock_provider)
elif request.param == "mock_config_entry_setup":
await mock_config_entry_setup(hass, mock_tts_entity)
else:
raise RuntimeError("Invalid setup fixture")
File diff suppressed because it is too large Load Diff
+83 -9
View File
@@ -3,32 +3,51 @@ from __future__ import annotations
import pytest
from homeassistant.components.tts import DOMAIN, Provider
from homeassistant.components.media_player import (
ATTR_MEDIA_CONTENT_ID,
ATTR_MEDIA_CONTENT_TYPE,
DOMAIN as DOMAIN_MP,
SERVICE_PLAY_MEDIA,
MediaType,
)
from homeassistant.components.tts import ATTR_MESSAGE, DOMAIN, Provider
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.setup import async_setup_component
from .common import MockTTS
from .common import SUPPORT_LANGUAGES, MockProvider, MockTTS, get_media_source_url
from tests.common import (
MockModule,
assert_setup_component,
async_mock_service,
mock_integration,
mock_platform,
)
class DefaultProvider(Provider):
"""Test provider."""
@property
def supported_languages(self) -> list[str]:
"""Return a list of supported languages."""
return SUPPORT_LANGUAGES
async def test_default_provider_attributes() -> None:
"""Test default provider properties."""
provider = Provider()
"""Test default provider attributes."""
provider = DefaultProvider()
assert provider.hass is None
assert provider.name is None
assert provider.default_language is None
assert provider.supported_languages is None
assert provider.supported_languages == SUPPORT_LANGUAGES
assert provider.supported_options is None
assert provider.default_options is None
assert provider.async_get_supported_voices("test") is None
async def test_deprecated_platform(hass: HomeAssistant) -> None:
@@ -56,8 +75,7 @@ async def test_invalid_platform(
async def test_platform_setup_without_provider(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mock_provider: MockProvider
) -> None:
"""Test platform setup without provider returned."""
@@ -74,7 +92,7 @@ async def test_platform_setup_without_provider(
return None
mock_integration(hass, MockModule(domain="bad_tts"))
mock_platform(hass, "bad_tts.tts", BadPlatform())
mock_platform(hass, "bad_tts.tts", BadPlatform(mock_provider))
await async_load_platform(
hass,
@@ -91,6 +109,7 @@ async def test_platform_setup_without_provider(
async def test_platform_setup_with_error(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
mock_provider: MockProvider,
) -> None:
"""Test platform setup with an error during setup."""
@@ -107,7 +126,7 @@ async def test_platform_setup_with_error(
raise Exception("Setup error") # pylint: disable=broad-exception-raised
mock_integration(hass, MockModule(domain="bad_tts"))
mock_platform(hass, "bad_tts.tts", BadPlatform())
mock_platform(hass, "bad_tts.tts", BadPlatform(mock_provider))
await async_load_platform(
hass,
@@ -119,3 +138,58 @@ async def test_platform_setup_with_error(
await hass.async_block_till_done()
assert "Error setting up platform: bad_tts" in caplog.text
async def test_service_base_url_set(hass: HomeAssistant, mock_tts) -> None:
"""Set up a TTS platform with ``base_url`` set and call service."""
calls = async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
config = {DOMAIN: {"platform": "test", "base_url": "http://fnord"}}
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(hass, DOMAIN, config)
await hass.services.async_call(
DOMAIN,
"test_say",
{
ATTR_ENTITY_ID: "media_player.something",
ATTR_MESSAGE: "There is someone at the door.",
},
blocking=True,
)
assert len(calls) == 1
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
assert (
await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID])
== "http://fnord"
"/api/tts_proxy/42f18378fd4393d18c8dd11d03fa9563c1e54491"
"_en-us_-_test.mp3"
)
async def test_service_without_cache_config(
hass: HomeAssistant, empty_cache_dir, mock_tts
) -> None:
"""Set up a TTS platform without cache."""
calls = async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
config = {DOMAIN: {"platform": "test", "cache": False}}
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(hass, DOMAIN, config)
await hass.services.async_call(
DOMAIN,
"test_say",
{
ATTR_ENTITY_ID: "media_player.something",
ATTR_MESSAGE: "There is someone at the door.",
},
blocking=True,
)
assert len(calls) == 1
await hass.async_block_till_done()
assert not (
empty_cache_dir / "42f18378fd4393d18c8dd11d03fa9563c1e54491_en-us_-_test.mp3"
).is_file()
+100 -28
View File
@@ -1,5 +1,5 @@
"""Tests for TTS media source."""
from unittest.mock import patch
from unittest.mock import MagicMock
import pytest
@@ -8,33 +8,52 @@ from homeassistant.components.media_player.errors import BrowseError
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .common import (
DEFAULT_LANG,
MockProvider,
MockTTSEntity,
mock_config_entry_setup,
mock_setup,
)
class MSEntity(MockTTSEntity):
"""Test speech API entity."""
get_tts_audio = MagicMock(return_value=("mp3", b""))
class MSProvider(MockProvider):
"""Test speech API provider."""
get_tts_audio = MagicMock(return_value=("mp3", b""))
@pytest.fixture(autouse=True)
async def mock_get_tts_audio(hass):
async def setup_media_source(hass: HomeAssistant) -> None:
"""Set up media source."""
assert await async_setup_component(hass, "media_source", {})
assert await async_setup_component(
hass,
"tts",
{
"tts": {
"platform": "demo",
}
},
)
with patch(
"homeassistant.components.demo.tts.DemoProvider.get_tts_audio",
return_value=("mp3", b""),
) as mock_get_tts:
yield mock_get_tts
async def test_browsing(hass: HomeAssistant) -> None:
@pytest.mark.parametrize(
("mock_provider", "mock_tts_entity"),
[(MSProvider(DEFAULT_LANG), MSEntity(DEFAULT_LANG))],
)
@pytest.mark.parametrize(
"setup",
[
"mock_setup",
"mock_config_entry_setup",
],
indirect=["setup"],
)
async def test_browsing(hass: HomeAssistant, setup: str) -> None:
"""Test browsing TTS media source."""
item = await media_source.async_browse_media(hass, "media-source://tts")
assert item is not None
assert item.title == "Text to Speech"
assert item.children is not None
assert len(item.children) == 1
assert item.can_play is False
assert item.can_expand is True
@@ -42,9 +61,10 @@ async def test_browsing(hass: HomeAssistant) -> None:
item_child = await media_source.async_browse_media(
hass, item.children[0].media_content_id
)
assert item_child is not None
assert item_child.media_content_id == item.children[0].media_content_id
assert item_child.title == "Demo"
assert item_child.title == "Test"
assert item_child.children is None
assert item_child.can_play is False
assert item_child.can_expand is True
@@ -52,12 +72,13 @@ async def test_browsing(hass: HomeAssistant) -> None:
item_child = await media_source.async_browse_media(
hass, item.children[0].media_content_id + "?message=bla"
)
assert item_child is not None
assert (
item_child.media_content_id
== item.children[0].media_content_id + "?message=bla"
)
assert item_child.title == "Demo"
assert item_child.title == "Test"
assert item_child.children is None
assert item_child.can_play is False
assert item_child.can_expand is True
@@ -66,10 +87,14 @@ async def test_browsing(hass: HomeAssistant) -> None:
await media_source.async_browse_media(hass, "media-source://tts/non-existing")
async def test_resolving(hass: HomeAssistant, mock_get_tts_audio) -> None:
"""Test resolving."""
@pytest.mark.parametrize("mock_provider", [MSProvider(DEFAULT_LANG)])
async def test_legacy_resolving(hass: HomeAssistant, mock_provider: MSProvider) -> None:
"""Test resolving legacy provider."""
await mock_setup(hass, mock_provider)
mock_get_tts_audio = mock_provider.get_tts_audio
media = await media_source.async_resolve_media(
hass, "media-source://tts/demo?message=Hello%20World", None
hass, "media-source://tts/test?message=Hello%20World", None
)
assert media.url.startswith("/api/tts_proxy/")
assert media.mime_type == "audio/mpeg"
@@ -77,14 +102,14 @@ async def test_resolving(hass: HomeAssistant, mock_get_tts_audio) -> None:
assert len(mock_get_tts_audio.mock_calls) == 1
message, language = mock_get_tts_audio.mock_calls[0][1]
assert message == "Hello World"
assert language == "en"
assert language == "en_US"
assert mock_get_tts_audio.mock_calls[0][2]["options"] is None
# Pass language and options
mock_get_tts_audio.reset_mock()
media = await media_source.async_resolve_media(
hass,
"media-source://tts/demo?message=Bye%20World&language=de&voice=Paulus",
"media-source://tts/test?message=Bye%20World&language=de&voice=Paulus",
None,
)
assert media.url.startswith("/api/tts_proxy/")
@@ -93,15 +118,62 @@ async def test_resolving(hass: HomeAssistant, mock_get_tts_audio) -> None:
assert len(mock_get_tts_audio.mock_calls) == 1
message, language = mock_get_tts_audio.mock_calls[0][1]
assert message == "Bye World"
assert language == "de"
assert language == "de_DE"
assert mock_get_tts_audio.mock_calls[0][2]["options"] == {"voice": "Paulus"}
async def test_resolving_errors(hass: HomeAssistant) -> None:
@pytest.mark.parametrize("mock_tts_entity", [MSEntity(DEFAULT_LANG)])
async def test_resolving(hass: HomeAssistant, mock_tts_entity: MSEntity) -> None:
"""Test resolving entity."""
await mock_config_entry_setup(hass, mock_tts_entity)
mock_get_tts_audio = mock_tts_entity.get_tts_audio
media = await media_source.async_resolve_media(
hass, "media-source://tts/tts.test?message=Hello%20World", None
)
assert media.url.startswith("/api/tts_proxy/")
assert media.mime_type == "audio/mpeg"
assert len(mock_get_tts_audio.mock_calls) == 1
message, language = mock_get_tts_audio.mock_calls[0][1]
assert message == "Hello World"
assert language == "en_US"
assert mock_get_tts_audio.mock_calls[0][2]["options"] is None
# Pass language and options
mock_get_tts_audio.reset_mock()
media = await media_source.async_resolve_media(
hass,
"media-source://tts/tts.test?message=Bye%20World&language=de&voice=Paulus",
None,
)
assert media.url.startswith("/api/tts_proxy/")
assert media.mime_type == "audio/mpeg"
assert len(mock_get_tts_audio.mock_calls) == 1
message, language = mock_get_tts_audio.mock_calls[0][1]
assert message == "Bye World"
assert language == "de_DE"
assert mock_get_tts_audio.mock_calls[0][2]["options"] == {"voice": "Paulus"}
@pytest.mark.parametrize(
("mock_provider", "mock_tts_entity"),
[(MSProvider(DEFAULT_LANG), MSEntity(DEFAULT_LANG))],
)
@pytest.mark.parametrize(
"setup",
[
"mock_setup",
"mock_config_entry_setup",
],
indirect=["setup"],
)
async def test_resolving_errors(hass: HomeAssistant, setup: str) -> None:
"""Test resolving."""
# No message added
with pytest.raises(media_source.Unresolvable):
await media_source.async_resolve_media(hass, "media-source://tts/demo", None)
await media_source.async_resolve_media(hass, "media-source://tts/test", None)
# Non-existing provider
with pytest.raises(media_source.Unresolvable):
+58 -13
View File
@@ -1,28 +1,22 @@
"""The tests for the TTS component."""
import pytest
import yarl
import homeassistant.components.media_player as media_player
from homeassistant.components import media_player, notify, tts
from homeassistant.components.media_player import (
DOMAIN as DOMAIN_MP,
SERVICE_PLAY_MEDIA,
)
import homeassistant.components.notify as notify
import homeassistant.components.tts as tts
from homeassistant.config import async_process_ha_core_config
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .common import MockTTSEntity, mock_config_entry_setup
from tests.common import assert_setup_component, async_mock_service
def relative_url(url):
"""Convert an absolute url to a relative one."""
return str(yarl.URL(url).relative())
@pytest.fixture(autouse=True)
async def internal_url_mock(hass):
async def internal_url_mock(hass: HomeAssistant) -> None:
"""Mock internal URL of the instance."""
await async_process_ha_core_config(
hass,
@@ -30,8 +24,8 @@ async def internal_url_mock(hass):
)
async def test_setup_platform(hass: HomeAssistant) -> None:
"""Set up the tts platform ."""
async def test_setup_legacy_platform(hass: HomeAssistant) -> None:
"""Set up the tts notify platform ."""
config = {
notify.DOMAIN: {
"platform": "tts",
@@ -46,7 +40,23 @@ async def test_setup_platform(hass: HomeAssistant) -> None:
assert hass.services.has_service(notify.DOMAIN, "tts_test")
async def test_setup_component_and_test_service(hass: HomeAssistant) -> None:
async def test_setup_platform(hass: HomeAssistant) -> None:
"""Set up the tts notify platform ."""
config = {
notify.DOMAIN: {
"platform": "tts",
"name": "tts_test",
"entity_id": "tts.test",
"media_player": "media_player.demo",
}
}
with assert_setup_component(1, notify.DOMAIN):
assert await async_setup_component(hass, notify.DOMAIN, config)
assert hass.services.has_service(notify.DOMAIN, "tts_test")
async def test_setup_legacy_service(hass: HomeAssistant) -> None:
"""Set up the demo platform and call service."""
calls = async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
@@ -80,3 +90,38 @@ async def test_setup_component_and_test_service(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert len(calls) == 1
async def test_setup_service(
hass: HomeAssistant, mock_tts_entity: MockTTSEntity
) -> None:
"""Set up platform and call service."""
calls = async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
config = {
notify.DOMAIN: {
"platform": "tts",
"name": "tts_test",
"entity_id": "tts.test",
"media_player": "media_player.demo",
"language": "en",
},
}
await mock_config_entry_setup(hass, mock_tts_entity)
with assert_setup_component(1, notify.DOMAIN):
assert await async_setup_component(hass, notify.DOMAIN, config)
await hass.services.async_call(
notify.DOMAIN,
"tts_test",
{
tts.ATTR_MESSAGE: "There is someone at the door.",
},
blocking=True,
)
await hass.async_block_till_done()
assert len(calls) == 1