mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 08:06:00 +01:00
Google Assistant SDK: improve init tests (#153795)
This commit is contained in:
@@ -6,6 +6,7 @@ import time
|
||||
from unittest.mock import call, patch
|
||||
|
||||
import aiohttp
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from grpc import RpcError
|
||||
import pytest
|
||||
|
||||
@@ -16,7 +17,6 @@ from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import Context, HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from .conftest import ComponentSetup, ExpectedCredentials
|
||||
|
||||
@@ -36,29 +36,25 @@ async def fetch_api_url(hass_client, url):
|
||||
async def test_setup_success(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test successful setup, unload, and re-setup."""
|
||||
# Initial setup
|
||||
await setup_integration()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
assert hass.services.has_service(DOMAIN, "send_text_command")
|
||||
|
||||
# Unload the entry
|
||||
entry_id = entries[0].entry_id
|
||||
await hass.config_entries.async_unload(entry_id)
|
||||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert not hass.data.get(DOMAIN)
|
||||
assert entries[0].state is ConfigEntryState.NOT_LOADED
|
||||
assert config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert hass.services.has_service(DOMAIN, "send_text_command")
|
||||
|
||||
# Re-setup the entry
|
||||
assert await hass.config_entries.async_setup(entry_id)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
assert hass.services.has_service(DOMAIN, "send_text_command")
|
||||
|
||||
|
||||
@@ -67,6 +63,7 @@ async def test_expired_token_refresh_success(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test expired token is refreshed."""
|
||||
|
||||
@@ -82,11 +79,9 @@ async def test_expired_token_refresh_success(
|
||||
|
||||
await setup_integration()
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.LOADED
|
||||
assert entries[0].data["token"]["access_token"] == "updated-access-token"
|
||||
assert entries[0].data["token"]["expires_in"] == 3600
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
assert config_entry.data["token"]["access_token"] == "updated-access-token"
|
||||
assert config_entry.data["token"]["expires_in"] == 3600
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -111,6 +106,7 @@ async def test_expired_token_refresh_failure(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
status: http.HTTPStatus,
|
||||
expected_state: ConfigEntryState,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test failure while refreshing token with a transient error."""
|
||||
|
||||
@@ -122,8 +118,7 @@ async def test_expired_token_refresh_failure(
|
||||
await setup_integration()
|
||||
|
||||
# Verify a transient failure has occurred
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert entries[0].state is expected_state
|
||||
assert config_entry.state is expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expires_at", [time.time() - 3600], ids=["expired"])
|
||||
@@ -131,6 +126,7 @@ async def test_setup_client_error(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test setup handling aiohttp.ClientError."""
|
||||
aioclient_mock.post(
|
||||
@@ -140,9 +136,7 @@ async def test_setup_client_error(
|
||||
|
||||
await setup_integration()
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.SETUP_RETRY
|
||||
assert config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
with pytest.raises(ServiceValidationError) as exc:
|
||||
await hass.services.async_call(
|
||||
@@ -152,26 +146,28 @@ async def test_setup_client_error(
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("configured_language_code", "expected_language_code"),
|
||||
[("", "en-US"), ("en-US", "en-US"), ("es-ES", "es-ES")],
|
||||
("options", "expected_language_code"),
|
||||
[
|
||||
({}, "en-US"),
|
||||
({"language_code": "en-US"}, "en-US"),
|
||||
({"language_code": "es-ES"}, "es-ES"),
|
||||
],
|
||||
ids=["default", "english", "spanish"],
|
||||
)
|
||||
async def test_send_text_command(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
configured_language_code: str,
|
||||
options: dict[str, str],
|
||||
expected_language_code: str,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test service call send_text_command calls TextAssistant."""
|
||||
await setup_integration()
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.LOADED
|
||||
if configured_language_code:
|
||||
hass.config_entries.async_update_entry(
|
||||
entries[0], options={"language_code": configured_language_code}
|
||||
)
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
hass.config_entries.async_update_entry(config_entry, options=options)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
command = "turn on home assistant unsupported device"
|
||||
with patch(
|
||||
@@ -193,13 +189,12 @@ async def test_send_text_command(
|
||||
async def test_send_text_commands(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test service call send_text_command calls TextAssistant."""
|
||||
await setup_integration()
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
command1 = "open the garage door"
|
||||
command2 = "1234"
|
||||
@@ -245,17 +240,15 @@ async def test_send_text_command_expired_token_refresh_failure(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
status: http.HTTPStatus,
|
||||
requires_reauth: ConfigEntryState,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test failure refreshing token in send_text_command."""
|
||||
await async_setup_component(hass, "homeassistant", {})
|
||||
await setup_integration()
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
entry.data["token"]["expires_at"] = time.time() - 3600
|
||||
config_entry.data["token"]["expires_at"] = time.time() - 3600
|
||||
aioclient_mock.post(
|
||||
"https://oauth2.googleapis.com/token",
|
||||
status=status,
|
||||
@@ -269,7 +262,7 @@ async def test_send_text_command_expired_token_refresh_failure(
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert any(entry.async_get_active_flows(hass, {"reauth"})) == requires_reauth
|
||||
assert any(config_entry.async_get_active_flows(hass, {"reauth"})) == requires_reauth
|
||||
|
||||
|
||||
async def test_send_text_command_grpc_error(
|
||||
@@ -300,6 +293,7 @@ async def test_send_text_command_media_player(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
hass_client: ClientSessionGenerator,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test send_text_command with media_player."""
|
||||
await setup_integration()
|
||||
@@ -364,7 +358,8 @@ async def test_send_text_command_media_player(
|
||||
assert status == http.HTTPStatus.NOT_FOUND
|
||||
|
||||
# Assert that both audio responses can still be served before the 5 minutes expiration
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(minutes=4))
|
||||
freezer.tick(timedelta(minutes=4, seconds=59))
|
||||
async_fire_time_changed(hass)
|
||||
status, response = await fetch_api_url(hass_client, audio_url1)
|
||||
assert status == http.HTTPStatus.OK
|
||||
assert response == audio_response1
|
||||
@@ -373,10 +368,11 @@ async def test_send_text_command_media_player(
|
||||
assert response == audio_response2
|
||||
|
||||
# Assert that they cannot be served after the 5 minutes expiration
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(minutes=6))
|
||||
status, response = await fetch_api_url(hass_client, audio_url1)
|
||||
freezer.tick(timedelta(seconds=2))
|
||||
async_fire_time_changed(hass)
|
||||
status, _ = await fetch_api_url(hass_client, audio_url1)
|
||||
assert status == http.HTTPStatus.NOT_FOUND
|
||||
status, response = await fetch_api_url(hass_client, audio_url2)
|
||||
status, _ = await fetch_api_url(hass_client, audio_url2)
|
||||
assert status == http.HTTPStatus.NOT_FOUND
|
||||
|
||||
|
||||
@@ -391,12 +387,9 @@ async def test_conversation_agent(
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, "conversation", {})
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
agent = conversation.get_agent_manager(hass).async_get_agent(entry.entry_id)
|
||||
agent = conversation.get_agent_manager(hass).async_get_agent(config_entry.entry_id)
|
||||
assert agent.supported_languages == SUPPORTED_LANGUAGE_CODES
|
||||
|
||||
text1 = "tell me a joke"
|
||||
@@ -430,10 +423,7 @@ async def test_conversation_agent_refresh_token(
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, "conversation", {})
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
text1 = "tell me a joke"
|
||||
text2 = "tell me another one"
|
||||
@@ -445,7 +435,7 @@ async def test_conversation_agent_refresh_token(
|
||||
)
|
||||
|
||||
# Expire the token between requests
|
||||
entry.data["token"]["expires_at"] = time.time() - 3600
|
||||
config_entry.data["token"]["expires_at"] = time.time() - 3600
|
||||
updated_access_token = "updated-access-token"
|
||||
aioclient_mock.post(
|
||||
"https://oauth2.googleapis.com/token",
|
||||
@@ -482,10 +472,7 @@ async def test_conversation_agent_language_changed(
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
assert await async_setup_component(hass, "conversation", {})
|
||||
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
entry = entries[0]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
text1 = "tell me a joke"
|
||||
text2 = "cuéntame un chiste"
|
||||
|
||||
Reference in New Issue
Block a user