Handle a missing Alexa link when syncing entities (#179734)

This commit is contained in:
Krisjanis Lejejs
2026-08-21 16:27:07 +02:00
committed by GitHub
parent 32a4846428
commit 1a1b3c39bd
2 changed files with 62 additions and 2 deletions
@@ -383,7 +383,7 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
# State reporting is reported as a property on entities.
# So when we change it, we need to sync all entities.
await self.async_sync_entities()
await self._async_sync_entities_unless_relink_needed()
return
# Nothing to do if no Alexa related things have changed
@@ -396,7 +396,14 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
):
return
await self.async_sync_entities()
await self._async_sync_entities_unless_relink_needed()
async def _async_sync_entities_unless_relink_needed(self) -> None:
"""Sync entities, tolerating an account with no linked Alexa skill."""
try:
await self.async_sync_entities()
except alexa_errors.NoTokenAvailable, alexa_errors.RequireRelink:
await self.set_authorized(False)
@callback
def _async_exposed_entities_updated(self) -> None:
@@ -905,3 +905,56 @@ async def test_alexa_config_migrate_expose_entity_prefs_default(
assert async_get_entity_settings(hass, water_heater.entity_id) == {
"cloud.alexa": {"should_expose": False}
}
@pytest.mark.parametrize(
"lib_exception",
[
pytest.param(
AlexaApiNeedsRelinkError("RefreshTokenNotFound"), id="needs_relink"
),
pytest.param(AlexaApiNoTokenError("OtherReason"), id="no_token"),
],
)
async def test_alexa_config_prefs_update_without_linked_skill(
hass: HomeAssistant,
cloud_prefs: CloudPreferences,
entity_registry: er.EntityRegistry,
caplog: pytest.LogCaptureFixture,
lib_exception: Exception,
) -> None:
"""Test updating prefs when the Alexa skill was never linked.
A freshly registered account has no Alexa refresh token, so syncing
entities must not raise out of the preferences listener.
"""
assert await async_setup_component(hass, "homeassistant", {})
expose_new(hass, True)
entity_entry = entity_registry.async_get_or_create(
"fan", "test", "unique", suggested_object_id="test_fan"
)
hass.states.async_set(entity_entry.entity_id, "off")
await cloud_prefs.async_update(alexa_enabled=False, alexa_report_state=False)
conf = alexa_config.CloudAlexaConfig(
hass,
ALEXA_SCHEMA({}),
"mock-user-id",
cloud_prefs,
Mock(
servicehandlers_server="example",
auth=Mock(async_check_token=AsyncMock()),
websession=async_get_clientsession(hass),
alexa_api=Mock(access_token=AsyncMock(side_effect=lib_exception)),
),
)
await conf.async_initialize()
await conf.set_authorized(True)
assert conf.authorized is True
await cloud_prefs.async_update(alexa_enabled=True)
await hass.async_block_till_done()
# The sync could not authenticate, so the skill is marked as needing a relink.
assert conf.authorized is False
assert "RequireRelink" not in caplog.text