diff --git a/homeassistant/components/loqed/coordinator.py b/homeassistant/components/loqed/coordinator.py index 790db6593129..316011b03688 100644 --- a/homeassistant/components/loqed/coordinator.py +++ b/homeassistant/components/loqed/coordinator.py @@ -4,6 +4,7 @@ import asyncio import logging from typing import TypedDict +import aiohttp from aiohttp.web import Request from loqedAPI import loqed @@ -160,14 +161,20 @@ class LoqedDataCoordinator(DataUpdateCoordinator[StatusMessage]): _LOGGER.debug("Webhook URL: %s", webhook_url) - webhooks = await self.lock.getWebhooks() + try: + webhooks = await self.lock.getWebhooks() - webhook_index = next( - (x["id"] for x in webhooks if x["url"] == webhook_url), None - ) + webhook_index = next( + (x["id"] for x in webhooks if x["url"] == webhook_url), None + ) - if webhook_index: - await self.lock.deleteWebhook(webhook_index) + if webhook_index: + await self.lock.deleteWebhook(webhook_index) + except (TimeoutError, aiohttp.ClientError) as err: + _LOGGER.warning( + "Could not remove webhook from LOQED bridge; the bridge may be offline. Continuing to unload the entry anyway: %s", + err, + ) async def async_cloudhook_generate_url( diff --git a/tests/components/loqed/test_init.py b/tests/components/loqed/test_init.py index ab426a3df4f8..b75fc478804a 100644 --- a/tests/components/loqed/test_init.py +++ b/tests/components/loqed/test_init.py @@ -8,6 +8,7 @@ from unittest.mock import AsyncMock, patch import aiohttp from freezegun.api import FrozenDateTimeFactory from loqedAPI import loqed +import pytest from homeassistant.components.loqed.const import DOMAIN from homeassistant.config_entries import ConfigEntryState @@ -214,3 +215,22 @@ async def test_unload_entry_fails( lock.deleteWebhook = AsyncMock(side_effect=Exception) assert not await hass.config_entries.async_unload(integration.entry_id) + + +@pytest.mark.parametrize("error", [aiohttp.ClientError, TimeoutError]) +async def test_unload_entry_with_unreachable_bridge( + hass: HomeAssistant, + integration: MockConfigEntry, + lock: loqed.Lock, + error: type[Exception], + caplog: pytest.LogCaptureFixture, +) -> None: + """Test entry still unloads when the bridge is unreachable.""" + lock.getWebhooks = AsyncMock(side_effect=error) + + assert await hass.config_entries.async_unload(integration.entry_id) + await hass.async_block_till_done() + + assert integration.state is ConfigEntryState.NOT_LOADED + assert not hass.data.get(DOMAIN) + assert "Could not remove webhook from LOQED bridge" in caplog.text