mirror of https://github.com/home-assistant/core
151 lines
5.1 KiB
Python
151 lines
5.1 KiB
Python
"""Test the speech-to-text platform for the cloud integration."""
|
|
|
|
from collections.abc import AsyncGenerator
|
|
from copy import deepcopy
|
|
from http import HTTPStatus
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
from hass_nabucasa.voice import STTResponse, VoiceError
|
|
import pytest
|
|
|
|
from homeassistant.components.assist_pipeline.pipeline import STORAGE_KEY
|
|
from homeassistant.components.cloud.const import DOMAIN
|
|
from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from . import PIPELINE_DATA
|
|
|
|
from tests.typing import ClientSessionGenerator
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
async def delay_save_fixture() -> AsyncGenerator[None]:
|
|
"""Load the homeassistant integration."""
|
|
with patch("homeassistant.helpers.collection.SAVE_DELAY", new=0):
|
|
yield
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("mock_process_stt", "expected_response_data"),
|
|
[
|
|
(
|
|
AsyncMock(return_value=STTResponse(True, "Turn the Kitchen Lights on")),
|
|
{"text": "Turn the Kitchen Lights on", "result": "success"},
|
|
),
|
|
(AsyncMock(side_effect=VoiceError("Boom!")), {"text": None, "result": "error"}),
|
|
],
|
|
)
|
|
async def test_cloud_speech(
|
|
hass: HomeAssistant,
|
|
cloud: MagicMock,
|
|
hass_client: ClientSessionGenerator,
|
|
mock_process_stt: AsyncMock,
|
|
expected_response_data: dict[str, Any],
|
|
) -> None:
|
|
"""Test cloud text-to-speech."""
|
|
cloud.voice.process_stt = mock_process_stt
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {"cloud": {}})
|
|
await hass.async_block_till_done()
|
|
|
|
on_start_callback = cloud.register_on_start.call_args[0][0]
|
|
await on_start_callback()
|
|
|
|
state = hass.states.get("stt.home_assistant_cloud")
|
|
assert state
|
|
assert state.state == STATE_UNKNOWN
|
|
|
|
client = await hass_client()
|
|
|
|
response = await client.post(
|
|
"/api/stt/stt.home_assistant_cloud",
|
|
headers={
|
|
"X-Speech-Content": (
|
|
"format=wav; codec=pcm; sample_rate=16000; bit_rate=16; channel=1;"
|
|
" language=de-DE"
|
|
)
|
|
},
|
|
data=b"Test",
|
|
)
|
|
response_data = await response.json()
|
|
|
|
assert mock_process_stt.call_count == 1
|
|
assert (
|
|
mock_process_stt.call_args.kwargs["content_type"]
|
|
== "audio/wav; codecs=audio/pcm; samplerate=16000"
|
|
)
|
|
assert mock_process_stt.call_args.kwargs["language"] == "de-DE"
|
|
assert response.status == HTTPStatus.OK
|
|
assert response_data == expected_response_data
|
|
|
|
state = hass.states.get("stt.home_assistant_cloud")
|
|
assert state
|
|
assert state.state not in (STATE_UNAVAILABLE, STATE_UNKNOWN)
|
|
|
|
|
|
async def test_migrating_pipelines(
|
|
hass: HomeAssistant,
|
|
cloud: MagicMock,
|
|
hass_client: ClientSessionGenerator,
|
|
hass_storage: dict[str, Any],
|
|
) -> None:
|
|
"""Test migrating pipelines when cloud stt entity is added."""
|
|
entity_id = "stt.home_assistant_cloud"
|
|
cloud.voice.process_stt = AsyncMock(
|
|
return_value=STTResponse(True, "Turn the Kitchen Lights on")
|
|
)
|
|
hass_storage[STORAGE_KEY] = {
|
|
"version": 1,
|
|
"minor_version": 1,
|
|
"key": "assist_pipeline.pipelines",
|
|
"data": deepcopy(PIPELINE_DATA),
|
|
}
|
|
|
|
assert await async_setup_component(hass, "assist_pipeline", {})
|
|
assert await async_setup_component(hass, DOMAIN, {"cloud": {}})
|
|
await hass.async_block_till_done()
|
|
|
|
await cloud.login("test-user", "test-pass")
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.state == STATE_UNKNOWN
|
|
|
|
# The stt/tts engines should have been updated to the new cloud engine ids.
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["stt_engine"] == entity_id
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["tts_engine"]
|
|
== "tts.home_assistant_cloud"
|
|
)
|
|
|
|
# The other items should stay the same.
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["conversation_engine"]
|
|
== "conversation_engine_1"
|
|
)
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["conversation_language"]
|
|
== "language_1"
|
|
)
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["id"]
|
|
== "01GX8ZWBAQYWNB1XV3EXEZ75DY"
|
|
)
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["language"] == "language_1"
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["name"] == "Home Assistant Cloud"
|
|
)
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["stt_language"] == "language_1"
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["tts_language"] == "language_1"
|
|
assert (
|
|
hass_storage[STORAGE_KEY]["data"]["items"][0]["tts_voice"]
|
|
== "Arnold Schwarzenegger"
|
|
)
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["wake_word_entity"] is None
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][0]["wake_word_id"] is None
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][1] == PIPELINE_DATA["items"][1]
|
|
assert hass_storage[STORAGE_KEY]["data"]["items"][2] == PIPELINE_DATA["items"][2]
|