Add tests for Microsoft TTS (#92215)
* Add tests for Microsoft TTS * Update requirements_test_all * Update tests/components/microsoft/__init__.py --------- Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
3c7e6bf3cc
commit
3bd6dea63b
3 changed files with 246 additions and 0 deletions
|
@ -1159,6 +1159,9 @@ pycomfoconnect==0.5.1
|
|||
# homeassistant.components.coolmaster
|
||||
pycoolmasternet-async==0.1.5
|
||||
|
||||
# homeassistant.components.microsoft
|
||||
pycsspeechtts==1.0.8
|
||||
|
||||
# homeassistant.components.daikin
|
||||
pydaikin==2.9.0
|
||||
|
||||
|
|
1
tests/components/microsoft/__init__.py
Normal file
1
tests/components/microsoft/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
"""Tests for the Microsoft Text-to-Speech component."""
|
242
tests/components/microsoft/test_tts.py
Normal file
242
tests/components/microsoft/test_tts.py
Normal file
|
@ -0,0 +1,242 @@
|
|||
"""Tests for Microsoft Text-to-Speech."""
|
||||
import os
|
||||
import shutil
|
||||
from unittest.mock import patch
|
||||
|
||||
from pycsspeechtts import pycsspeechtts
|
||||
import pytest
|
||||
from requests import HTTPError
|
||||
|
||||
from homeassistant.components import media_source, tts
|
||||
from homeassistant.components.media_player import (
|
||||
ATTR_MEDIA_CONTENT_ID,
|
||||
DOMAIN as DOMAIN_MP,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
)
|
||||
from homeassistant.components.microsoft.tts import SUPPORTED_LANGUAGES
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceNotFound
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import async_mock_service
|
||||
|
||||
|
||||
async def get_media_source_url(hass: HomeAssistant, media_content_id):
|
||||
"""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
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cleanup_cache(hass: HomeAssistant):
|
||||
"""Clean up TTS cache."""
|
||||
yield
|
||||
default_tts = hass.config.path(tts.DEFAULT_CACHE_DIR)
|
||||
if os.path.isdir(default_tts):
|
||||
shutil.rmtree(default_tts)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def calls(hass: HomeAssistant):
|
||||
"""Mock media player calls."""
|
||||
return async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def setup_internal_url(hass: HomeAssistant):
|
||||
"""Set up internal url."""
|
||||
await async_process_ha_core_config(
|
||||
hass, {"internal_url": "http://example.local:8123"}
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_tts():
|
||||
"""Mock tts."""
|
||||
with patch(
|
||||
"homeassistant.components.microsoft.tts.pycsspeechtts.TTSTranslator"
|
||||
) as mock_tts:
|
||||
mock_tts.return_value.speak.return_value = b""
|
||||
yield mock_tts
|
||||
|
||||
|
||||
async def test_service_say(hass: HomeAssistant, mock_tts, calls) -> None:
|
||||
"""Test service call say."""
|
||||
|
||||
await async_setup_component(
|
||||
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "microsoft", "api_key": ""}}
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"microsoft_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
url = await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID])
|
||||
assert len(mock_tts.mock_calls) == 2
|
||||
assert url.endswith(".mp3")
|
||||
|
||||
assert mock_tts.mock_calls[1][2] == {
|
||||
"language": "en-us",
|
||||
"gender": "Female",
|
||||
"voiceType": "JennyNeural",
|
||||
"output": "audio-24khz-96kbitrate-mono-mp3",
|
||||
"rate": "0%",
|
||||
"volume": "0%",
|
||||
"pitch": "default",
|
||||
"contour": "",
|
||||
"text": "There is a person at the front door.",
|
||||
}
|
||||
|
||||
|
||||
async def test_service_say_en_gb_config(hass: HomeAssistant, mock_tts, calls) -> None:
|
||||
"""Test service call say with en-gb code in the config."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{
|
||||
tts.DOMAIN: {
|
||||
"platform": "microsoft",
|
||||
"api_key": "",
|
||||
"language": "en-gb",
|
||||
"type": "AbbiNeural",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"microsoft_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID])
|
||||
assert len(mock_tts.mock_calls) == 2
|
||||
assert mock_tts.mock_calls[1][2] == {
|
||||
"language": "en-gb",
|
||||
"gender": "Female",
|
||||
"voiceType": "AbbiNeural",
|
||||
"output": "audio-24khz-96kbitrate-mono-mp3",
|
||||
"rate": "0%",
|
||||
"volume": "0%",
|
||||
"pitch": "default",
|
||||
"contour": "",
|
||||
"text": "There is a person at the front door.",
|
||||
}
|
||||
|
||||
|
||||
async def test_service_say_en_gb_service(hass: HomeAssistant, mock_tts, calls) -> None:
|
||||
"""Test service call say with en-gb code in the service."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{tts.DOMAIN: {"platform": "microsoft", "api_key": ""}},
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"microsoft_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
tts.ATTR_LANGUAGE: "en-gb",
|
||||
tts.ATTR_OPTIONS: {"type": "AbbiNeural"},
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID])
|
||||
assert len(mock_tts.mock_calls) == 2
|
||||
assert mock_tts.mock_calls[1][2] == {
|
||||
"language": "en-gb",
|
||||
"gender": "Female",
|
||||
"voiceType": "AbbiNeural",
|
||||
"output": "audio-24khz-96kbitrate-mono-mp3",
|
||||
"rate": "0%",
|
||||
"volume": "0%",
|
||||
"pitch": "default",
|
||||
"contour": "",
|
||||
"text": "There is a person at the front door.",
|
||||
}
|
||||
|
||||
|
||||
def test_supported_languages() -> None:
|
||||
"""Test list of supported languages."""
|
||||
for lang in ["en-us", "en-gb"]:
|
||||
assert lang in SUPPORTED_LANGUAGES
|
||||
assert "en-US" not in SUPPORTED_LANGUAGES
|
||||
for lang in [
|
||||
"en",
|
||||
"en-uk",
|
||||
"english",
|
||||
"english (united states)",
|
||||
"jennyneural",
|
||||
"en-us-jennyneural",
|
||||
]:
|
||||
assert lang not in {s.lower() for s in SUPPORTED_LANGUAGES}
|
||||
assert len(SUPPORTED_LANGUAGES) > 70
|
||||
|
||||
|
||||
async def test_invalid_language(hass: HomeAssistant, mock_tts, calls) -> None:
|
||||
"""Test setup component with invalid language."""
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tts.DOMAIN,
|
||||
{tts.DOMAIN: {"platform": "microsoft", "api_key": "", "language": "en"}},
|
||||
)
|
||||
|
||||
with pytest.raises(ServiceNotFound):
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"microsoft_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 0
|
||||
assert len(mock_tts.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_service_say_error(hass: HomeAssistant, mock_tts, calls) -> None:
|
||||
"""Test service call say with http error."""
|
||||
mock_tts.return_value.speak.side_effect = pycsspeechtts.requests.HTTPError
|
||||
await async_setup_component(
|
||||
hass, tts.DOMAIN, {tts.DOMAIN: {"platform": "microsoft", "api_key": ""}}
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
tts.DOMAIN,
|
||||
"microsoft_say",
|
||||
{
|
||||
"entity_id": "media_player.something",
|
||||
tts.ATTR_MESSAGE: "There is a person at the front door.",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(calls) == 1
|
||||
# Note: the integration currently catches HTTPException instead of HTTPError.
|
||||
with pytest.raises(HTTPError):
|
||||
await get_media_source_url(hass, calls[0].data[ATTR_MEDIA_CONTENT_ID])
|
||||
assert len(mock_tts.mock_calls) == 2
|
Loading…
Add table
Reference in a new issue