Migrate google translate to config entries (#93803)

Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
Martin Hjelmare 2023-06-21 14:58:58 +02:00 committed by GitHub
parent 22e1feb223
commit f9366e5cc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 557 additions and 103 deletions

View file

@ -1 +1,20 @@
"""The google_translate component.""" """The Google Translate text-to-speech integration."""
from __future__ import annotations
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
PLATFORMS: list[Platform] = [Platform.TTS]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Google Translate text-to-speech from a config entry."""
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View file

@ -0,0 +1,49 @@
"""Config flow for Google Translate text-to-speech integration."""
from __future__ import annotations
from typing import Any
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components.tts import CONF_LANG
from homeassistant.data_entry_flow import FlowResult
from .const import (
CONF_TLD,
DEFAULT_LANG,
DEFAULT_TLD,
DOMAIN,
SUPPORT_LANGUAGES,
SUPPORT_TLD,
)
STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES),
vol.Optional(CONF_TLD, default=DEFAULT_TLD): vol.In(SUPPORT_TLD),
}
)
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Google Translate text-to-speech."""
VERSION = 1
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""
if user_input is not None:
self._async_abort_entries_match(
{
CONF_LANG: user_input[CONF_LANG],
CONF_TLD: user_input[CONF_TLD],
}
)
return self.async_create_entry(
title="Google Translate text-to-speech", data=user_input
)
return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA)

View file

@ -1,6 +1,11 @@
"""Constant for google_translate integration.""" """Constants for the Google Translate text-to-speech integration."""
from dataclasses import dataclass from dataclasses import dataclass
CONF_TLD = "tld"
DEFAULT_LANG = "en"
DEFAULT_TLD = "com"
DOMAIN = "google_translate"
SUPPORT_LANGUAGES = [ SUPPORT_LANGUAGES = [
"af", "af",
"ar", "ar",

View file

@ -2,6 +2,8 @@
"domain": "google_translate", "domain": "google_translate",
"name": "Google Translate text-to-speech", "name": "Google Translate text-to-speech",
"codeowners": [], "codeowners": [],
"config_flow": true,
"dependencies": ["repairs"],
"documentation": "https://www.home-assistant.io/integrations/google_translate", "documentation": "https://www.home-assistant.io/integrations/google_translate",
"iot_class": "cloud_push", "iot_class": "cloud_push",
"loggers": ["gtts"], "loggers": ["gtts"],

View file

@ -0,0 +1,15 @@
{
"config": {
"step": {
"user": {
"data": {
"language": "Language",
"tld": "TLD"
}
}
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
}
}
}

View file

@ -1,33 +1,120 @@
"""Support for the Google speech service.""" """Support for the Google speech service."""
from __future__ import annotations
from io import BytesIO from io import BytesIO
import logging import logging
from typing import Any
from gtts import gTTS, gTTSError from gtts import gTTS, gTTSError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.tts import CONF_LANG, PLATFORM_SCHEMA, Provider from homeassistant.components.tts import (
CONF_LANG,
PLATFORM_SCHEMA,
Provider,
TextToSpeechEntity,
TtsAudioType,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import MAP_LANG_TLD, SUPPORT_LANGUAGES, SUPPORT_TLD from .const import (
CONF_TLD,
DEFAULT_LANG,
DEFAULT_TLD,
MAP_LANG_TLD,
SUPPORT_LANGUAGES,
SUPPORT_TLD,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEFAULT_LANG = "en"
SUPPORT_OPTIONS = ["tld"] SUPPORT_OPTIONS = ["tld"]
DEFAULT_TLD = "com"
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES), vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES),
vol.Optional("tld", default=DEFAULT_TLD): vol.In(SUPPORT_TLD), vol.Optional(CONF_TLD, default=DEFAULT_TLD): vol.In(SUPPORT_TLD),
} }
) )
async def async_get_engine(hass, config, discovery_info=None): async def async_get_engine(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> GoogleProvider:
"""Set up Google speech component.""" """Set up Google speech component."""
return GoogleProvider(hass, config[CONF_LANG], config["tld"]) return GoogleProvider(hass, config[CONF_LANG], config[CONF_TLD])
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Google Translate speech platform via config entry."""
default_language = config_entry.data[CONF_LANG]
default_tld = config_entry.data[CONF_TLD]
async_add_entities([GoogleTTSEntity(config_entry, default_language, default_tld)])
class GoogleTTSEntity(TextToSpeechEntity):
"""The Google speech API entity."""
def __init__(self, config_entry: ConfigEntry, lang: str, tld: str) -> None:
"""Init Google TTS service."""
if lang in MAP_LANG_TLD:
self._lang = MAP_LANG_TLD[lang].lang
self._tld = MAP_LANG_TLD[lang].tld
else:
self._lang = lang
self._tld = tld
self._attr_name = f"Google {self._lang} {self._tld}"
self._attr_unique_id = config_entry.entry_id
@property
def default_language(self):
"""Return the default language."""
return self._lang
@property
def supported_languages(self):
"""Return list of supported languages."""
return SUPPORT_LANGUAGES
@property
def supported_options(self):
"""Return a list of supported options."""
return SUPPORT_OPTIONS
def get_tts_audio(
self, message: str, language: str, options: dict[str, Any] | None = None
) -> TtsAudioType:
"""Load TTS from google."""
tld = self._tld
if language in MAP_LANG_TLD:
tld_language = MAP_LANG_TLD[language]
tld = tld_language.tld
language = tld_language.lang
if options is not None and "tld" in options:
tld = options["tld"]
tts = gTTS(text=message, lang=language, tld=tld)
mp3_data = BytesIO()
try:
tts.write_to_fp(mp3_data)
except gTTSError as exc:
_LOGGER.debug(
"Error during processing of TTS request %s", exc, exc_info=True
)
raise HomeAssistantError(exc) from exc
return "mp3", mp3_data.getvalue()
class GoogleProvider(Provider): class GoogleProvider(Provider):

View file

@ -173,6 +173,7 @@ FLOWS = {
"google_generative_ai_conversation", "google_generative_ai_conversation",
"google_mail", "google_mail",
"google_sheets", "google_sheets",
"google_translate",
"google_travel_time", "google_travel_time",
"govee_ble", "govee_ble",
"gpslogger", "gpslogger",

View file

@ -2084,7 +2084,7 @@
}, },
"google_translate": { "google_translate": {
"integration_type": "hub", "integration_type": "hub",
"config_flow": false, "config_flow": true,
"iot_class": "cloud_push", "iot_class": "cloud_push",
"name": "Google Translate text-to-speech" "name": "Google Translate text-to-speech"
}, },

View file

@ -0,0 +1,14 @@
"""Common fixtures for the Google Translate text-to-speech tests."""
from collections.abc import Generator
from unittest.mock import AsyncMock, patch
import pytest
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.google_translate.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry

View file

@ -0,0 +1,68 @@
"""Test the Google Translate text-to-speech config flow."""
from unittest.mock import AsyncMock
import pytest
from homeassistant import config_entries
from homeassistant.components.google_translate.const import CONF_TLD, DOMAIN
from homeassistant.components.tts import CONF_LANG
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
async def test_user_step(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
"""Test user step create entry result."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] is None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LANG: "de",
CONF_TLD: "de",
},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["title"] == "Google Translate text-to-speech"
assert result["data"] == {
CONF_LANG: "de",
CONF_TLD: "de",
}
assert len(mock_setup_entry.mock_calls) == 1
async def test_already_configured(
hass: HomeAssistant, mock_setup_entry: AsyncMock
) -> None:
"""Test user step already configured entry."""
config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_LANG: "de", CONF_TLD: "de"}
)
config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == FlowResultType.FORM
assert result["errors"] is None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LANG: "de",
CONF_TLD: "de",
},
)
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert len(mock_setup_entry.mock_calls) == 0

View file

@ -1,21 +1,27 @@
"""The tests for the Google speech platform.""" """The tests for the Google speech platform."""
from unittest.mock import patch from __future__ import annotations
from collections.abc import Generator
from typing import Any
from unittest.mock import MagicMock, patch
from gtts import gTTSError from gtts import gTTSError
import pytest import pytest
from homeassistant.components import media_source, tts from homeassistant.components import media_source, tts
from homeassistant.components.google_translate.const import CONF_TLD, DOMAIN
from homeassistant.components.media_player import ( from homeassistant.components.media_player import (
ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_ID,
DOMAIN as DOMAIN_MP, DOMAIN as DOMAIN_MP,
SERVICE_PLAY_MEDIA, SERVICE_PLAY_MEDIA,
) )
from homeassistant.config import async_process_ha_core_config from homeassistant.config import async_process_ha_core_config
from homeassistant.core import HomeAssistant from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import async_mock_service from tests.common import MockConfigEntry, async_mock_service
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -29,7 +35,7 @@ def mock_tts_cache_dir_autouse(mock_tts_cache_dir):
return mock_tts_cache_dir return mock_tts_cache_dir
async def get_media_source_url(hass, media_content_id): async def get_media_source_url(hass: HomeAssistant, media_content_id: str) -> str:
"""Get the media source url.""" """Get the media source url."""
if media_source.DOMAIN not in hass.config.components: if media_source.DOMAIN not in hass.config.components:
assert await async_setup_component(hass, media_source.DOMAIN, {}) assert await async_setup_component(hass, media_source.DOMAIN, {})
@ -39,13 +45,13 @@ async def get_media_source_url(hass, media_content_id):
@pytest.fixture @pytest.fixture
async def calls(hass): async def calls(hass: HomeAssistant) -> list[ServiceCall]:
"""Mock media player calls.""" """Mock media player calls."""
return async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) return async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
async def setup_internal_url(hass): async def setup_internal_url(hass: HomeAssistant) -> None:
"""Set up internal url.""" """Set up internal url."""
await async_process_ha_core_config( await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"} hass, {"internal_url": "http://example.local:8123"}
@ -53,26 +59,85 @@ async def setup_internal_url(hass):
@pytest.fixture @pytest.fixture
def mock_gtts(): def mock_gtts() -> Generator[MagicMock, None, None]:
"""Mock gtts.""" """Mock gtts."""
with patch("homeassistant.components.google_translate.tts.gTTS") as mock_gtts: with patch("homeassistant.components.google_translate.tts.gTTS") as mock_gtts:
yield mock_gtts yield mock_gtts
async def test_service_say(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.fixture(name="setup")
"""Test service call say.""" async def setup_fixture(
hass: HomeAssistant,
config: dict[str, Any],
request: pytest.FixtureRequest,
) -> None:
"""Set up the test environment."""
if request.param == "mock_setup":
await mock_setup(hass, config)
elif request.param == "mock_config_entry_setup":
await mock_config_entry_setup(hass, config)
else:
raise RuntimeError("Invalid setup fixture")
await async_setup_component(
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "google_translate"}} @pytest.fixture(name="config")
def config_fixture() -> dict[str, Any]:
"""Return config."""
return {}
async def mock_setup(hass: HomeAssistant, config: dict[str, Any]) -> None:
"""Mock setup."""
assert await async_setup_component(
hass, tts.DOMAIN, {tts.DOMAIN: {CONF_PLATFORM: DOMAIN} | config}
) )
async def mock_config_entry_setup(hass: HomeAssistant, config: dict[str, Any]) -> None:
"""Mock config entry setup."""
default_config = {tts.CONF_LANG: "en", CONF_TLD: "com"}
config_entry = MockConfigEntry(domain=DOMAIN, data=default_config | config)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
@pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
],
indirect=["setup"],
)
async def test_tts_service(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test tts service."""
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
blocking=True, blocking=True,
) )
@ -88,22 +153,43 @@ async def test_service_say(hass: HomeAssistant, mock_gtts, calls) -> None:
} }
async def test_service_say_german_config(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.mark.parametrize("config", [{tts.CONF_LANG: "de"}])
@pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_de_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
],
indirect=["setup"],
)
async def test_service_say_german_config(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test service call say with german code in the config.""" """Test service call say with german code in the config."""
await async_setup_component(
hass,
tts.DOMAIN,
{tts.DOMAIN: {"platform": "google_translate", "language": "de"}},
)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
blocking=True, blocking=True,
) )
@ -117,25 +203,44 @@ async def test_service_say_german_config(hass: HomeAssistant, mock_gtts, calls)
} }
@pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "de",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "de",
},
),
],
indirect=["setup"],
)
async def test_service_say_german_service( async def test_service_say_german_service(
hass: HomeAssistant, mock_gtts, calls hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None: ) -> None:
"""Test service call say with german code in the service.""" """Test service call say with german code in the service."""
config = {
tts.DOMAIN: {"platform": "google_translate", "service_name": "google_say"}
}
await async_setup_component(hass, tts.DOMAIN, config)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "de",
},
blocking=True, blocking=True,
) )
@ -149,22 +254,43 @@ async def test_service_say_german_service(
} }
async def test_service_say_en_uk_config(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.mark.parametrize("config", [{tts.CONF_LANG: "en-uk"}])
@pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_co_uk",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
],
indirect=["setup"],
)
async def test_service_say_en_uk_config(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test service call say with en-uk code in the config.""" """Test service call say with en-uk code in the config."""
await async_setup_component(
hass,
tts.DOMAIN,
{tts.DOMAIN: {"platform": "google_translate", "language": "en-uk"}},
)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
blocking=True, blocking=True,
) )
@ -178,23 +304,44 @@ async def test_service_say_en_uk_config(hass: HomeAssistant, mock_gtts, calls) -
} }
async def test_service_say_en_uk_service(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "en-uk",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "en-uk",
},
),
],
indirect=["setup"],
)
async def test_service_say_en_uk_service(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test service call say with en-uk code in the config.""" """Test service call say with en-uk code in the config."""
await async_setup_component(
hass,
tts.DOMAIN,
{tts.DOMAIN: {"platform": "google_translate"}},
)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_LANGUAGE: "en-uk",
},
blocking=True, blocking=True,
) )
@ -208,21 +355,44 @@ async def test_service_say_en_uk_service(hass: HomeAssistant, mock_gtts, calls)
} }
async def test_service_say_en_couk(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_OPTIONS: {"tld": "co.uk"},
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_OPTIONS: {"tld": "co.uk"},
},
),
],
indirect=["setup"],
)
async def test_service_say_en_couk(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test service call say in co.uk tld accent.""" """Test service call say in co.uk tld accent."""
await async_setup_component(
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "google_translate"}}
)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
tts.ATTR_OPTIONS: {"tld": "co.uk"},
},
blocking=True, blocking=True,
) )
@ -238,20 +408,44 @@ async def test_service_say_en_couk(hass: HomeAssistant, mock_gtts, calls) -> Non
} }
async def test_service_say_error(hass: HomeAssistant, mock_gtts, calls) -> None: @pytest.mark.parametrize(
("setup", "tts_service", "service_data"),
[
(
"mock_setup",
"google_translate_say",
{
ATTR_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
(
"mock_config_entry_setup",
"speak",
{
ATTR_ENTITY_ID: "tts.google_en_com",
tts.ATTR_MEDIA_PLAYER_ENTITY_ID: "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
),
],
indirect=["setup"],
)
async def test_service_say_error(
hass: HomeAssistant,
mock_gtts: MagicMock,
calls: list[ServiceCall],
setup: str,
tts_service: str,
service_data: dict[str, Any],
) -> None:
"""Test service call say with http response 400.""" """Test service call say with http response 400."""
mock_gtts.return_value.write_to_fp.side_effect = gTTSError mock_gtts.return_value.write_to_fp.side_effect = gTTSError
await async_setup_component(
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "google_translate"}}
)
await hass.services.async_call( await hass.services.async_call(
tts.DOMAIN, tts.DOMAIN,
"google_translate_say", tts_service,
{ service_data,
"entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is a person at the front door.",
},
blocking=True, blocking=True,
) )