mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Google Assistant SDK: Support non en-US language code (#84028)
* Support non en-US language code * Get default language_code based on HA config * Revert bumping gassist-text Will be done in a separate PR
This commit is contained in:
parent
ed8aa51c76
commit
d6158c0fcc
@ -23,7 +23,7 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
args:
|
args:
|
||||||
- --ignore-words-list=additionals,alot,ba,bre,bund,datas,dof,dur,ether,farenheit,falsy,fo,haa,hass,hist,iam,iff,iif,incomfort,ines,ist,lightsensor,mut,nam,nd,pres,pullrequests,referer,resset,rime,ser,serie,sur,te,technik,ue,uint,unsecure,visability,wan,wanna,withing,zar
|
- --ignore-words-list=additionals,alle,alot,ba,bre,bund,datas,dof,dur,ether,farenheit,falsy,fo,haa,hass,hist,iam,iff,iif,incomfort,ines,ist,lightsensor,mut,nam,nd,pres,pullrequests,referer,resset,rime,ser,serie,sur,te,technik,ue,uint,unsecure,visability,wan,wanna,withing,zar
|
||||||
- --skip="./.*,*.csv,*.json"
|
- --skip="./.*,*.csv,*.json"
|
||||||
- --quiet-level=2
|
- --quiet-level=2
|
||||||
exclude_types: [csv, json]
|
exclude_types: [csv, json]
|
||||||
|
@ -5,11 +5,16 @@ from collections.abc import Mapping
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import callback
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
from .const import DEFAULT_NAME, DOMAIN
|
from .const import CONF_LANGUAGE_CODE, DEFAULT_NAME, DOMAIN, SUPPORTED_LANGUAGE_CODES
|
||||||
|
from .helpers import default_language_code
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -64,4 +69,45 @@ class OAuth2FlowHandler(
|
|||||||
# Config entry already exists, only one allowed.
|
# Config entry already exists, only one allowed.
|
||||||
return self.async_abort(reason="single_instance_allowed")
|
return self.async_abort(reason="single_instance_allowed")
|
||||||
|
|
||||||
return self.async_create_entry(title=DEFAULT_NAME, data=data)
|
return self.async_create_entry(
|
||||||
|
title=DEFAULT_NAME,
|
||||||
|
data=data,
|
||||||
|
options={
|
||||||
|
CONF_LANGUAGE_CODE: default_language_code(self.hass),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@callback
|
||||||
|
def async_get_options_flow(
|
||||||
|
config_entry: config_entries.ConfigEntry,
|
||||||
|
) -> config_entries.OptionsFlow:
|
||||||
|
"""Create the options flow."""
|
||||||
|
return OptionsFlowHandler(config_entry)
|
||||||
|
|
||||||
|
|
||||||
|
class OptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
|
"""Google Assistant SDK options flow."""
|
||||||
|
|
||||||
|
def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
|
||||||
|
"""Initialize options flow."""
|
||||||
|
self.config_entry = config_entry
|
||||||
|
|
||||||
|
async def async_step_init(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Manage the options."""
|
||||||
|
if user_input is not None:
|
||||||
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="init",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(
|
||||||
|
CONF_LANGUAGE_CODE,
|
||||||
|
default=self.config_entry.options.get(CONF_LANGUAGE_CODE),
|
||||||
|
): vol.In(SUPPORTED_LANGUAGE_CODES),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
"""Constants for Google Assistant SDK integration."""
|
"""Constants for Google Assistant SDK integration."""
|
||||||
from __future__ import annotations
|
from typing import Final
|
||||||
|
|
||||||
DOMAIN = "google_assistant_sdk"
|
DOMAIN: Final = "google_assistant_sdk"
|
||||||
|
|
||||||
DEFAULT_NAME = "Google Assistant SDK"
|
DEFAULT_NAME: Final = "Google Assistant SDK"
|
||||||
|
|
||||||
|
CONF_LANGUAGE_CODE: Final = "language_code"
|
||||||
|
|
||||||
|
# https://developers.google.com/assistant/sdk/reference/rpc/languages
|
||||||
|
SUPPORTED_LANGUAGE_CODES: Final = [
|
||||||
|
"de-DE",
|
||||||
|
"en-AU",
|
||||||
|
"en-CA",
|
||||||
|
"en-GB",
|
||||||
|
"en-IN",
|
||||||
|
"en-US",
|
||||||
|
"es-ES",
|
||||||
|
"es-MX",
|
||||||
|
"fr-CA",
|
||||||
|
"fr-FR",
|
||||||
|
"it-IT",
|
||||||
|
"pt-BR",
|
||||||
|
]
|
||||||
|
@ -10,7 +10,16 @@ from homeassistant.const import CONF_ACCESS_TOKEN
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session
|
from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import CONF_LANGUAGE_CODE, DOMAIN, SUPPORTED_LANGUAGE_CODES
|
||||||
|
|
||||||
|
DEFAULT_LANGUAGE_CODES = {
|
||||||
|
"de": "de-DE",
|
||||||
|
"en": "en-US",
|
||||||
|
"es": "es-ES",
|
||||||
|
"fr": "fr-FR",
|
||||||
|
"it": "it-IT",
|
||||||
|
"pt": "pt-BR",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_send_text_commands(commands: list[str], hass: HomeAssistant) -> None:
|
async def async_send_text_commands(commands: list[str], hass: HomeAssistant) -> None:
|
||||||
@ -27,6 +36,15 @@ async def async_send_text_commands(commands: list[str], hass: HomeAssistant) ->
|
|||||||
raise err
|
raise err
|
||||||
|
|
||||||
credentials = Credentials(session.token[CONF_ACCESS_TOKEN])
|
credentials = Credentials(session.token[CONF_ACCESS_TOKEN])
|
||||||
with TextAssistant(credentials) as assistant:
|
language_code = entry.options.get(CONF_LANGUAGE_CODE, default_language_code(hass))
|
||||||
|
with TextAssistant(credentials, language_code) as assistant:
|
||||||
for command in commands:
|
for command in commands:
|
||||||
assistant.assist(command)
|
assistant.assist(command)
|
||||||
|
|
||||||
|
|
||||||
|
def default_language_code(hass: HomeAssistant):
|
||||||
|
"""Get default language code based on Home Assistant config."""
|
||||||
|
language_code = f"{hass.config.language}-{hass.config.country}"
|
||||||
|
if language_code in SUPPORTED_LANGUAGE_CODES:
|
||||||
|
return language_code
|
||||||
|
return DEFAULT_LANGUAGE_CODES.get(hass.config.language, "en-US")
|
||||||
|
@ -4,10 +4,32 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
|
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from .helpers import async_send_text_commands
|
from .const import CONF_LANGUAGE_CODE, DOMAIN
|
||||||
|
from .helpers import async_send_text_commands, default_language_code
|
||||||
|
|
||||||
|
# https://support.google.com/assistant/answer/9071582?hl=en
|
||||||
|
LANG_TO_BROADCAST_COMMAND = {
|
||||||
|
"en": ("broadcast", "broadcast to"),
|
||||||
|
"de": ("Nachricht an alle", "Nachricht an alle an"),
|
||||||
|
"es": ("Anuncia", "Anuncia en"),
|
||||||
|
"fr": ("Diffuse", "Diffuse dans"),
|
||||||
|
"it": ("Trasmetti", "Trasmetti in"),
|
||||||
|
"pt": ("Transmite", "Transmite para"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def broadcast_commands(language_code: str):
|
||||||
|
"""
|
||||||
|
Get the commands for broadcasting a message for the given language code.
|
||||||
|
|
||||||
|
Return type is a tuple where [0] is for broadcasting to your entire home,
|
||||||
|
while [1] is for broadcasting to a specific target.
|
||||||
|
"""
|
||||||
|
return LANG_TO_BROADCAST_COMMAND.get(language_code.split("-", maxsplit=1)[0])
|
||||||
|
|
||||||
|
|
||||||
async def async_get_service(
|
async def async_get_service(
|
||||||
@ -31,11 +53,19 @@ class BroadcastNotificationService(BaseNotificationService):
|
|||||||
if not message:
|
if not message:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# There can only be 1 entry (config_flow has single_instance_allowed)
|
||||||
|
entry: ConfigEntry = self.hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
language_code = entry.options.get(
|
||||||
|
CONF_LANGUAGE_CODE, default_language_code(self.hass)
|
||||||
|
)
|
||||||
|
|
||||||
commands = []
|
commands = []
|
||||||
targets = kwargs.get(ATTR_TARGET)
|
targets = kwargs.get(ATTR_TARGET)
|
||||||
if not targets:
|
if not targets:
|
||||||
commands.append(f"broadcast {message}")
|
commands.append(f"{broadcast_commands(language_code)[0]} {message}")
|
||||||
else:
|
else:
|
||||||
for target in targets:
|
for target in targets:
|
||||||
commands.append(f"broadcast to {target} {message}")
|
commands.append(
|
||||||
|
f"{broadcast_commands(language_code)[1]} {target} {message}"
|
||||||
|
)
|
||||||
await async_send_text_commands(commands, self.hass)
|
await async_send_text_commands(commands, self.hass)
|
||||||
|
@ -27,6 +27,15 @@
|
|||||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"language_code": "Language code"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"application_credentials": {
|
"application_credentials": {
|
||||||
"description": "Follow the [instructions]({more_info_url}) for [OAuth consent screen]({oauth_consent_url}) to give Home Assistant access to your Google Assistant SDK. You also need to create Application Credentials linked to your account:\n1. Go to [Credentials]({oauth_creds_url}) and click **Create Credentials**.\n1. From the drop-down list select **OAuth client ID**.\n1. Select **Web application** for the Application Type.\n\n"
|
"description": "Follow the [instructions]({more_info_url}) for [OAuth consent screen]({oauth_consent_url}) to give Home Assistant access to your Google Assistant SDK. You also need to create Application Credentials linked to your account:\n1. Go to [Credentials]({oauth_creds_url}) and click **Create Credentials**.\n1. From the drop-down list select **OAuth client ID**.\n1. Select **Web application** for the Application Type.\n\n"
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from collections.abc import Awaitable, Callable, Generator
|
from collections.abc import Awaitable, Callable, Generator
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from google.oauth2.credentials import Credentials
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.application_credentials import (
|
from homeassistant.components.application_credentials import (
|
||||||
@ -18,6 +19,7 @@ ComponentSetup = Callable[[], Awaitable[None]]
|
|||||||
|
|
||||||
CLIENT_ID = "1234"
|
CLIENT_ID = "1234"
|
||||||
CLIENT_SECRET = "5678"
|
CLIENT_SECRET = "5678"
|
||||||
|
ACCESS_TOKEN = "mock-access-token"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -51,7 +53,7 @@ def mock_config_entry(expires_at: int, scopes: list[str]) -> MockConfigEntry:
|
|||||||
data={
|
data={
|
||||||
"auth_implementation": DOMAIN,
|
"auth_implementation": DOMAIN,
|
||||||
"token": {
|
"token": {
|
||||||
"access_token": "mock-access-token",
|
"access_token": ACCESS_TOKEN,
|
||||||
"refresh_token": "mock-refresh-token",
|
"refresh_token": "mock-refresh-token",
|
||||||
"expires_at": expires_at,
|
"expires_at": expires_at,
|
||||||
"scope": " ".join(scopes),
|
"scope": " ".join(scopes),
|
||||||
@ -80,3 +82,11 @@ async def mock_setup_integration(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
yield func
|
yield func
|
||||||
|
|
||||||
|
|
||||||
|
class ExpectedCredentials:
|
||||||
|
"""Assert credentials have the expected access token."""
|
||||||
|
|
||||||
|
def __eq__(self, other: Credentials):
|
||||||
|
"""Return true if credentials have the expected access token."""
|
||||||
|
return other.token == ACCESS_TOKEN
|
||||||
|
@ -8,7 +8,7 @@ from homeassistant.components.google_assistant_sdk.const import DOMAIN
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
from .conftest import CLIENT_ID
|
from .conftest import CLIENT_ID, ComponentSetup
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
@ -205,3 +205,55 @@ async def test_single_instance_allowed(
|
|||||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
assert result.get("type") == "abort"
|
assert result.get("type") == "abort"
|
||||||
assert result.get("reason") == "single_instance_allowed"
|
assert result.get("reason") == "single_instance_allowed"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_options_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test options flow."""
|
||||||
|
await setup_integration()
|
||||||
|
assert not config_entry.options
|
||||||
|
|
||||||
|
# Trigger options flow, first time
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
data_schema = result["data_schema"].schema
|
||||||
|
assert set(data_schema) == {"language_code"}
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={"language_code": "es-ES"},
|
||||||
|
)
|
||||||
|
assert result["type"] == "create_entry"
|
||||||
|
assert config_entry.options == {"language_code": "es-ES"}
|
||||||
|
|
||||||
|
# Retrigger options flow, not change language
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
data_schema = result["data_schema"].schema
|
||||||
|
assert set(data_schema) == {"language_code"}
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={"language_code": "es-ES"},
|
||||||
|
)
|
||||||
|
assert result["type"] == "create_entry"
|
||||||
|
assert config_entry.options == {"language_code": "es-ES"}
|
||||||
|
|
||||||
|
# Retrigger options flow, change language
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] == "form"
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
data_schema = result["data_schema"].schema
|
||||||
|
assert set(data_schema) == {"language_code"}
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={"language_code": "en-US"},
|
||||||
|
)
|
||||||
|
assert result["type"] == "create_entry"
|
||||||
|
assert config_entry.options == {"language_code": "en-US"}
|
||||||
|
47
tests/components/google_assistant_sdk/test_helpers.py
Normal file
47
tests/components/google_assistant_sdk/test_helpers.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
"""Test the Google Assistant SDK helpers."""
|
||||||
|
from homeassistant.components.google_assistant_sdk.const import SUPPORTED_LANGUAGE_CODES
|
||||||
|
from homeassistant.components.google_assistant_sdk.helpers import (
|
||||||
|
DEFAULT_LANGUAGE_CODES,
|
||||||
|
default_language_code,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_language_codes(hass: HomeAssistant) -> None:
|
||||||
|
"""Test all supported languages have a default language_code."""
|
||||||
|
for language_code in SUPPORTED_LANGUAGE_CODES:
|
||||||
|
lang = language_code.split("-", maxsplit=1)[0]
|
||||||
|
assert DEFAULT_LANGUAGE_CODES.get(lang)
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_language_code(hass: HomeAssistant) -> None:
|
||||||
|
"""Test default_language_code."""
|
||||||
|
assert default_language_code(hass) == "en-US"
|
||||||
|
|
||||||
|
hass.config.language = "en"
|
||||||
|
hass.config.country = "US"
|
||||||
|
assert default_language_code(hass) == "en-US"
|
||||||
|
|
||||||
|
hass.config.language = "en"
|
||||||
|
hass.config.country = "GB"
|
||||||
|
assert default_language_code(hass) == "en-GB"
|
||||||
|
|
||||||
|
hass.config.language = "en"
|
||||||
|
hass.config.country = "ES"
|
||||||
|
assert default_language_code(hass) == "en-US"
|
||||||
|
|
||||||
|
hass.config.language = "es"
|
||||||
|
hass.config.country = "ES"
|
||||||
|
assert default_language_code(hass) == "es-ES"
|
||||||
|
|
||||||
|
hass.config.language = "es"
|
||||||
|
hass.config.country = "MX"
|
||||||
|
assert default_language_code(hass) == "es-MX"
|
||||||
|
|
||||||
|
hass.config.language = "es"
|
||||||
|
hass.config.country = None
|
||||||
|
assert default_language_code(hass) == "es-ES"
|
||||||
|
|
||||||
|
hass.config.language = "el"
|
||||||
|
hass.config.country = "GR"
|
||||||
|
assert default_language_code(hass) == "en-US"
|
@ -1,7 +1,7 @@
|
|||||||
"""Tests for Google Assistant SDK."""
|
"""Tests for Google Assistant SDK."""
|
||||||
import http
|
import http
|
||||||
import time
|
import time
|
||||||
from unittest.mock import patch
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import pytest
|
import pytest
|
||||||
@ -10,7 +10,7 @@ from homeassistant.components.google_assistant_sdk import DOMAIN
|
|||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .conftest import ComponentSetup
|
from .conftest import ComponentSetup, ExpectedCredentials
|
||||||
|
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
@ -97,9 +97,16 @@ async def test_expired_token_refresh_failure(
|
|||||||
assert entries[0].state is expected_state
|
assert entries[0].state is expected_state
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"configured_language_code,expected_language_code",
|
||||||
|
[("", "en-US"), ("en-US", "en-US"), ("es-ES", "es-ES")],
|
||||||
|
ids=["default", "english", "spanish"],
|
||||||
|
)
|
||||||
async def test_send_text_command(
|
async def test_send_text_command(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_integration: ComponentSetup,
|
setup_integration: ComponentSetup,
|
||||||
|
configured_language_code: str,
|
||||||
|
expected_language_code: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test service call send_text_command calls TextAssistant."""
|
"""Test service call send_text_command calls TextAssistant."""
|
||||||
await setup_integration()
|
await setup_integration()
|
||||||
@ -107,18 +114,23 @@ async def test_send_text_command(
|
|||||||
entries = hass.config_entries.async_entries(DOMAIN)
|
entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
assert len(entries) == 1
|
assert len(entries) == 1
|
||||||
assert entries[0].state is ConfigEntryState.LOADED
|
assert entries[0].state is ConfigEntryState.LOADED
|
||||||
|
if configured_language_code:
|
||||||
|
entries[0].options = {"language_code": configured_language_code}
|
||||||
|
|
||||||
command = "turn on home assistant unsupported device"
|
command = "turn on home assistant unsupported device"
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant.assist"
|
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant"
|
||||||
) as mock_assist_call:
|
) as mock_text_assistant:
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
"send_text_command",
|
"send_text_command",
|
||||||
{"command": command},
|
{"command": command},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
mock_assist_call.assert_called_once_with(command)
|
mock_text_assistant.assert_called_once_with(
|
||||||
|
ExpectedCredentials(), expected_language_code
|
||||||
|
)
|
||||||
|
mock_text_assistant.assert_has_calls([call().__enter__().assist(command)])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -3,9 +3,11 @@ from unittest.mock import call, patch
|
|||||||
|
|
||||||
from homeassistant.components import notify
|
from homeassistant.components import notify
|
||||||
from homeassistant.components.google_assistant_sdk import DOMAIN
|
from homeassistant.components.google_assistant_sdk import DOMAIN
|
||||||
|
from homeassistant.components.google_assistant_sdk.const import SUPPORTED_LANGUAGE_CODES
|
||||||
|
from homeassistant.components.google_assistant_sdk.notify import broadcast_commands
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .conftest import ComponentSetup
|
from .conftest import ComponentSetup, ExpectedCredentials
|
||||||
|
|
||||||
|
|
||||||
async def test_broadcast_no_targets(
|
async def test_broadcast_no_targets(
|
||||||
@ -17,15 +19,16 @@ async def test_broadcast_no_targets(
|
|||||||
message = "time for dinner"
|
message = "time for dinner"
|
||||||
expected_command = "broadcast time for dinner"
|
expected_command = "broadcast time for dinner"
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant.assist"
|
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant"
|
||||||
) as mock_assist_call:
|
) as mock_text_assistant:
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
notify.DOMAIN,
|
notify.DOMAIN,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
{notify.ATTR_MESSAGE: message},
|
{notify.ATTR_MESSAGE: message},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_assist_call.assert_called_once_with(expected_command)
|
mock_text_assistant.assert_called_once_with(ExpectedCredentials(), "en-US")
|
||||||
|
mock_text_assistant.assert_has_calls([call().__enter__().assist(expected_command)])
|
||||||
|
|
||||||
|
|
||||||
async def test_broadcast_one_target(
|
async def test_broadcast_one_target(
|
||||||
@ -90,3 +93,39 @@ async def test_broadcast_empty_message(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_assist_call.assert_not_called()
|
mock_assist_call.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_broadcast_spanish(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup
|
||||||
|
) -> None:
|
||||||
|
"""Test broadcast in Spanish."""
|
||||||
|
await setup_integration()
|
||||||
|
|
||||||
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
entry.options = {"language_code": "es-ES"}
|
||||||
|
|
||||||
|
message = "comida"
|
||||||
|
expected_command = "Anuncia comida"
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant"
|
||||||
|
) as mock_text_assistant:
|
||||||
|
await hass.services.async_call(
|
||||||
|
notify.DOMAIN,
|
||||||
|
DOMAIN,
|
||||||
|
{notify.ATTR_MESSAGE: message},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
mock_text_assistant.assert_called_once_with(ExpectedCredentials(), "es-ES")
|
||||||
|
mock_text_assistant.assert_has_calls([call().__enter__().assist(expected_command)])
|
||||||
|
|
||||||
|
|
||||||
|
def test_broadcast_language_mapping(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup
|
||||||
|
) -> None:
|
||||||
|
"""Test all supported languages have a mapped broadcast command."""
|
||||||
|
for language_code in SUPPORTED_LANGUAGE_CODES:
|
||||||
|
cmds = broadcast_commands(language_code)
|
||||||
|
assert cmds
|
||||||
|
assert len(cmds) == 2
|
||||||
|
assert cmds[0]
|
||||||
|
assert cmds[1]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user