Migrate google translate to config entries (#93803)
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
22e1feb223
commit
f9366e5cc7
11 changed files with 557 additions and 103 deletions
|
@ -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)
|
||||
|
|
49
homeassistant/components/google_translate/config_flow.py
Normal file
49
homeassistant/components/google_translate/config_flow.py
Normal 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)
|
|
@ -1,6 +1,11 @@
|
|||
"""Constant for google_translate integration."""
|
||||
"""Constants for the Google Translate text-to-speech integration."""
|
||||
from dataclasses import dataclass
|
||||
|
||||
CONF_TLD = "tld"
|
||||
DEFAULT_LANG = "en"
|
||||
DEFAULT_TLD = "com"
|
||||
DOMAIN = "google_translate"
|
||||
|
||||
SUPPORT_LANGUAGES = [
|
||||
"af",
|
||||
"ar",
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"domain": "google_translate",
|
||||
"name": "Google Translate text-to-speech",
|
||||
"codeowners": [],
|
||||
"config_flow": true,
|
||||
"dependencies": ["repairs"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/google_translate",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["gtts"],
|
||||
|
|
15
homeassistant/components/google_translate/strings.json
Normal file
15
homeassistant/components/google_translate/strings.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"language": "Language",
|
||||
"tld": "TLD"
|
||||
}
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +1,120 @@
|
|||
"""Support for the Google speech service."""
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from gtts import gTTS, gTTSError
|
||||
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__)
|
||||
|
||||
DEFAULT_LANG = "en"
|
||||
|
||||
SUPPORT_OPTIONS = ["tld"]
|
||||
|
||||
DEFAULT_TLD = "com"
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
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."""
|
||||
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):
|
||||
|
|
|
@ -173,6 +173,7 @@ FLOWS = {
|
|||
"google_generative_ai_conversation",
|
||||
"google_mail",
|
||||
"google_sheets",
|
||||
"google_translate",
|
||||
"google_travel_time",
|
||||
"govee_ble",
|
||||
"gpslogger",
|
||||
|
|
|
@ -2084,7 +2084,7 @@
|
|||
},
|
||||
"google_translate": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_push",
|
||||
"name": "Google Translate text-to-speech"
|
||||
},
|
||||
|
|
14
tests/components/google_translate/conftest.py
Normal file
14
tests/components/google_translate/conftest.py
Normal 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
|
68
tests/components/google_translate/test_config_flow.py
Normal file
68
tests/components/google_translate/test_config_flow.py
Normal 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
|
|
@ -1,21 +1,27 @@
|
|||
"""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
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import media_source, tts
|
||||
from homeassistant.components.google_translate.const import CONF_TLD, DOMAIN
|
||||
from homeassistant.components.media_player import (
|
||||
ATTR_MEDIA_CONTENT_ID,
|
||||
DOMAIN as DOMAIN_MP,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
)
|
||||
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.setup import async_setup_component
|
||||
|
||||
from tests.common import async_mock_service
|
||||
from tests.common import MockConfigEntry, async_mock_service
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
@ -29,7 +35,7 @@ def mock_tts_cache_dir_autouse(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."""
|
||||
if media_source.DOMAIN not in hass.config.components:
|
||||
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
|
||||
async def calls(hass):
|
||||
async def calls(hass: HomeAssistant) -> list[ServiceCall]:
|
||||
"""Mock media player calls."""
|
||||
return async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def setup_internal_url(hass):
|
||||
async def setup_internal_url(hass: HomeAssistant) -> None:
|
||||
"""Set up internal url."""
|
||||
await async_process_ha_core_config(
|
||||
hass, {"internal_url": "http://example.local:8123"}
|
||||
|
@ -53,26 +59,85 @@ async def setup_internal_url(hass):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_gtts():
|
||||
def mock_gtts() -> Generator[MagicMock, None, None]:
|
||||
"""Mock gtts."""
|
||||
with patch("homeassistant.components.google_translate.tts.gTTS") as mock_gtts:
|
||||
yield mock_gtts
|
||||
|
||||
|
||||
async def test_service_say(hass: HomeAssistant, mock_gtts, calls) -> None:
|
||||
"""Test service call say."""
|
||||
@pytest.fixture(name="setup")
|
||||
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(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{tts.DOMAIN: {"platform": "google_translate", "language": "de"}},
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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(
|
||||
hass: HomeAssistant, mock_gtts, calls
|
||||
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 service."""
|
||||
|
||||
config = {
|
||||
tts.DOMAIN: {"platform": "google_translate", "service_name": "google_say"}
|
||||
}
|
||||
|
||||
await async_setup_component(hass, tts.DOMAIN, config)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"google_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
tts.ATTR_LANGUAGE: "de",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{tts.DOMAIN: {"platform": "google_translate", "language": "en-uk"}},
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{tts.DOMAIN: {"platform": "google_translate"}},
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
tts.ATTR_LANGUAGE: "en-uk",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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."""
|
||||
|
||||
await async_setup_component(
|
||||
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "google_translate"}}
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
tts.ATTR_OPTIONS: {"tld": "co.uk"},
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
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."""
|
||||
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(
|
||||
tts.DOMAIN,
|
||||
"google_translate_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
tts_service,
|
||||
service_data,
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue