diff --git a/homeassistant/components/wled/config_flow.py b/homeassistant/components/wled/config_flow.py index e55c71e4bab4f9..9e91b9445997af 100644 --- a/homeassistant/components/wled/config_flow.py +++ b/homeassistant/components/wled/config_flow.py @@ -3,7 +3,14 @@ from typing import Any import voluptuous as vol -from wled import WLED, Device, WLEDConnectionError, WLEDUnsupportedVersionError +from wled import ( + WLED, + Device, + WLEDConnectionError, + WLEDEmptyResponseError, + WLEDInvalidResponseError, + WLEDUnsupportedVersionError, +) import yarl from homeassistant.components import onboarding @@ -62,6 +69,11 @@ async def async_step_user( errors["base"] = "unsupported_version" except WLEDConnectionError: errors["base"] = "cannot_connect" + except (WLEDInvalidResponseError, WLEDEmptyResponseError) as er: + if "presets" in str(er): + errors["base"] = "invalid_response_presets" + else: + errors["base"] = "invalid_response" else: mac_address = normalize_mac_address(device.info.mac_address) await self.async_set_unique_id(mac_address, raise_on_progress=False) @@ -119,6 +131,14 @@ async def async_step_zeroconf( self.discovered_device = await self._async_get_device(discovery_info.host) except WLEDUnsupportedVersionError: return self.async_abort(reason="unsupported_version") + except (WLEDInvalidResponseError, WLEDEmptyResponseError) as ex: + return self.async_abort( + reason=( + "invalid_response_presets" + if "presets" in str(ex) + else "invalid_response" + ), + ) except WLEDConnectionError: return self.async_abort(reason="cannot_connect") diff --git a/homeassistant/components/wled/coordinator.py b/homeassistant/components/wled/coordinator.py index ec7e07a1cc1408..5e8e749d6d37d1 100644 --- a/homeassistant/components/wled/coordinator.py +++ b/homeassistant/components/wled/coordinator.py @@ -7,7 +7,9 @@ Device as WLEDDevice, Releases, WLEDConnectionClosedError, + WLEDEmptyResponseError, WLEDError, + WLEDInvalidResponseError, WLEDReleases, WLEDUnsupportedVersionError, ) @@ -154,13 +156,23 @@ async def _async_update_data(self) -> WLEDDevice: translation_key="unsupported_version", translation_placeholders={"error": str(error)}, ) from error + except (WLEDInvalidResponseError, WLEDEmptyResponseError) as error: + translation_key = ( + "invalid_response_presets_wled_error" + if "presets" in str(error) + else "invalid_response_wled_error" + ) + raise UpdateFailed( + translation_domain=DOMAIN, + translation_key=translation_key, + translation_placeholders={"error": str(error)}, + ) from error except WLEDError as error: raise UpdateFailed( translation_domain=DOMAIN, translation_key="invalid_response_wled_error", translation_placeholders={"error": str(error)}, ) from error - device_mac_address = normalize_mac_address(device.info.mac_address) if device_mac_address != self.config_mac_address: raise ConfigEntryError( diff --git a/homeassistant/components/wled/helpers.py b/homeassistant/components/wled/helpers.py index 64921e3258de4b..47f7c0f41feec8 100644 --- a/homeassistant/components/wled/helpers.py +++ b/homeassistant/components/wled/helpers.py @@ -3,7 +3,12 @@ from collections.abc import Callable, Coroutine from typing import Any, Concatenate -from wled import WLEDConnectionError, WLEDError +from wled import ( + WLEDConnectionError, + WLEDEmptyResponseError, + WLEDError, + WLEDInvalidResponseError, +) from homeassistant.exceptions import HomeAssistantError @@ -33,6 +38,17 @@ async def handler(self: _WLEDEntityT, *args: _P.args, **kwargs: _P.kwargs) -> No translation_key="connection_error", translation_placeholders={"error": str(error)}, ) from error + except (WLEDInvalidResponseError, WLEDEmptyResponseError) as error: + translation_key = ( + "invalid_response_presets_wled_error" + if "presets" in str(error) + else "invalid_response_wled_error" + ) + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key=translation_key, + translation_placeholders={"error": str(error)}, + ) from error except WLEDError as error: raise HomeAssistantError( translation_domain=DOMAIN, diff --git a/homeassistant/components/wled/strings.json b/homeassistant/components/wled/strings.json index 5a2732c7745478..ab4586657a03de 100644 --- a/homeassistant/components/wled/strings.json +++ b/homeassistant/components/wled/strings.json @@ -12,6 +12,8 @@ }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "invalid_response": "Received an unexpected response from the device. Please check your device and try again.", + "invalid_response_presets": "Failed to download presets from the device. Check preset configurations in WLED UI.", "unsupported_version": "[%key:component::wled::common::unsupported_version%]" }, "flow_title": "{name}", @@ -139,9 +141,15 @@ "connection_error": { "message": "Error communicating with WLED API: {error}" }, + "install_update_wled_error": { + "message": "Error installing WLED update: {error}" + }, "invalid_response_github_error": { "message": "Invalid response from GitHub API: {error}" }, + "invalid_response_presets_wled_error": { + "message": "Failed to download presets from the device. Check preset configurations in WLED UI. Error details: {error}" + }, "invalid_response_wled_error": { "message": "Invalid response from WLED API: {error}" }, diff --git a/homeassistant/components/wled/update.py b/homeassistant/components/wled/update.py index dd68b8cd6a8164..f733394c230881 100644 --- a/homeassistant/components/wled/update.py +++ b/homeassistant/components/wled/update.py @@ -2,15 +2,19 @@ from typing import Any, cast +from wled import WLEDUpgradeError + from homeassistant.components.update import ( UpdateDeviceClass, UpdateEntity, UpdateEntityFeature, ) from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from . import WLED_KEY +from .const import DOMAIN from .coordinator import ( WLEDConfigEntry, WLEDDataUpdateCoordinator, @@ -110,5 +114,12 @@ async def async_install( if version is None: # We cast here, as we know that the latest_version is a string. version = cast(str, self.latest_version) - await self.coordinator.wled.upgrade(version=version) - await self.coordinator.async_refresh() + try: + await self.coordinator.wled.upgrade(version=version) + await self.coordinator.async_refresh() + except WLEDUpgradeError as error: + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key="install_update_wled_error", + translation_placeholders={"error": str(error)}, + ) from error diff --git a/tests/components/wled/test_button.py b/tests/components/wled/test_button.py index 56433c4401d7b7..c96446313afa64 100644 --- a/tests/components/wled/test_button.py +++ b/tests/components/wled/test_button.py @@ -5,7 +5,12 @@ import pytest from syrupy.assertion import SnapshotAssertion -from wled import WLEDConnectionError, WLEDError +from wled import ( + WLEDConnectionError, + WLEDEmptyResponseError, + WLEDError, + WLEDInvalidResponseError, +) from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS from homeassistant.components.wled.const import DOMAIN @@ -87,6 +92,34 @@ async def test_button_restart( ("side_effect", "expected_state", "expected_translation_key"), [ (WLEDError, "2021-11-04T16:37:00+00:00", "invalid_response_wled_error"), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /json" + ), + "2021-11-04T16:37:00+00:00", + "invalid_response_wled_error", + ), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + "2021-11-04T16:37:00+00:00", + "invalid_response_presets_wled_error", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on full update" + ), + "2021-11-04T16:37:00+00:00", + "invalid_response_wled_error", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on presets update" + ), + "2021-11-04T16:37:00+00:00", + "invalid_response_presets_wled_error", + ), (WLEDConnectionError, STATE_UNAVAILABLE, "connection_error"), ], ) @@ -116,3 +149,5 @@ async def test_button_restart_errors( # Ensure this made the entity unavailable assert (state := hass.states.get("button.wled_rgb_light_restart")) assert state.state == expected_state + + mock_wled.reset.assert_called_with() diff --git a/tests/components/wled/test_config_flow.py b/tests/components/wled/test_config_flow.py index f4d3da1b571ef7..5b58ac8a5afef5 100644 --- a/tests/components/wled/test_config_flow.py +++ b/tests/components/wled/test_config_flow.py @@ -4,7 +4,12 @@ from unittest.mock import AsyncMock, MagicMock import pytest -from wled import WLEDConnectionError, WLEDUnsupportedVersionError +from wled import ( + WLEDConnectionError, + WLEDEmptyResponseError, + WLEDInvalidResponseError, + WLEDUnsupportedVersionError, +) from homeassistant.components.wled.const import CONF_KEEP_MAIN_LIGHT, DOMAIN from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF @@ -219,6 +224,30 @@ async def test_zeroconf_during_onboarding( [ (WLEDConnectionError, {"base": "cannot_connect"}), (WLEDUnsupportedVersionError, {"base": "unsupported_version"}), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /json" + ), + {"base": "invalid_response"}, + ), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + {"base": "invalid_response_presets"}, + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on full update" + ), + {"base": "invalid_response"}, + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on presets update" + ), + {"base": "invalid_response_presets"}, + ), ], ) async def test_form_submission_errors( @@ -237,35 +266,45 @@ async def test_form_submission_errors( assert result.get("errors") == errors -async def test_zeroconf_connection_error( - hass: HomeAssistant, mock_wled: MagicMock -) -> None: - """Test we abort zeroconf flow on WLED connection error.""" - mock_wled.update.side_effect = WLEDConnectionError - - result = await hass.config_entries.flow.async_init( - DOMAIN, - context={"source": SOURCE_ZEROCONF}, - data=ZeroconfServiceInfo( - ip_address=ip_address("192.168.1.123"), - ip_addresses=[ip_address("192.168.1.123")], - hostname="example.local.", - name="mock_name", - port=None, - properties={CONF_MAC: "aabbccddeeff"}, - type="mock_type", +@pytest.mark.parametrize( + ("side_effect", "expected_reason"), + [ + (WLEDConnectionError, "cannot_connect"), + (WLEDUnsupportedVersionError, "unsupported_version"), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /json" + ), + "invalid_response", ), - ) - - assert result.get("type") is FlowResultType.ABORT - assert result.get("reason") == "cannot_connect" - - -async def test_zeroconf_unsupported_version_error( - hass: HomeAssistant, mock_wled: MagicMock + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + "invalid_response_presets", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on full update" + ), + "invalid_response", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on presets update" + ), + "invalid_response_presets", + ), + ], +) +async def test_zeroconf_errors( + hass: HomeAssistant, + mock_wled: MagicMock, + side_effect: Exception, + expected_reason: str, ) -> None: - """Test we abort zeroconf flow on WLED unsupported version error.""" - mock_wled.update.side_effect = WLEDUnsupportedVersionError + """Test we abort zeroconf flow on WLED errors.""" + mock_wled.update.side_effect = side_effect result = await hass.config_entries.flow.async_init( DOMAIN, @@ -282,7 +321,7 @@ async def test_zeroconf_unsupported_version_error( ) assert result.get("type") is FlowResultType.ABORT - assert result.get("reason") == "unsupported_version" + assert result.get("reason") == expected_reason @pytest.mark.usefixtures("mock_wled") diff --git a/tests/components/wled/test_coordinator.py b/tests/components/wled/test_coordinator.py index 4e703dd1565d38..544719ec80dcaf 100644 --- a/tests/components/wled/test_coordinator.py +++ b/tests/components/wled/test_coordinator.py @@ -11,7 +11,9 @@ Device as WLEDDevice, WLEDConnectionClosedError, WLEDConnectionError, + WLEDEmptyResponseError, WLEDError, + WLEDInvalidResponseError, WLEDUnsupportedVersionError, ) @@ -258,16 +260,81 @@ async def test_fail_when_other_device( ) -async def test_fail_when_unsupported_version( +@pytest.mark.parametrize( + ( + "exception", + "expected_state", + "expected_error_reason_translation_key", + "expected_log_message", + ), + [ + pytest.param( + WLEDUnsupportedVersionError( + "Unsupported firmware version 0.14.0-b1. Minimum required version is 0.14.0. " + "Please update your WLED device." + ), + ConfigEntryState.SETUP_ERROR, + "unsupported_version", + "Unsupported firmware version 0.14.0-b1. Minimum required version is 0.14.0. Please update your WLED device.", + id="unsupported_version", + ), + pytest.param( + WLEDError, + ConfigEntryState.SETUP_RETRY, + None, + "Invalid response from WLED API:", + id="wled_error", + ), + pytest.param( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /json" + ), + ConfigEntryState.SETUP_RETRY, + None, + "Invalid response from WLED API: ", + id="invalid_response", + ), + pytest.param( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + ConfigEntryState.SETUP_RETRY, + None, + "Failed to download presets from the device. Check preset configurations in WLED UI.", + id="invalid_response_presets", + ), + pytest.param( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on full update" + ), + ConfigEntryState.SETUP_RETRY, + None, + "Invalid response from WLED API:", + id="empty_response_full_update", + ), + pytest.param( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on presets update" + ), + ConfigEntryState.SETUP_RETRY, + None, + "Failed to download presets from the device. Check preset configurations in WLED UI.", + id="empty_response_presets_update", + ), + ], +) +async def test_errors_on_setup( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_wled: MagicMock, + exception: Exception | type[Exception], + expected_state: ConfigEntryState, + expected_error_reason_translation_key: str | None, + expected_log_message: str, + caplog: pytest.LogCaptureFixture, ) -> None: """Ensure entry fails to setup when unsupported version.""" - mock_wled.update.side_effect = WLEDUnsupportedVersionError( - "Unsupported firmware version 0.14.0-b1. Minimum required version is 0.14.0. " - "Please update your WLED device." - ) + mock_wled.update.side_effect = exception mock_config_entry.add_to_hass(hass) @@ -275,10 +342,10 @@ async def test_fail_when_unsupported_version( await hass.async_block_till_done() - assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR - assert mock_config_entry.reason + assert mock_config_entry.state is expected_state + assert ( - "The WLED device's firmware version is not supported:" - in mock_config_entry.reason + mock_config_entry.error_reason_translation_key + == expected_error_reason_translation_key ) - assert "0.14.0-b1" in mock_config_entry.reason + assert expected_log_message in caplog.text diff --git a/tests/components/wled/test_light.py b/tests/components/wled/test_light.py index 5f64a8433eaa32..26a005d1feae03 100644 --- a/tests/components/wled/test_light.py +++ b/tests/components/wled/test_light.py @@ -6,7 +6,13 @@ from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion -from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError +from wled import ( + Device as WLEDDevice, + WLEDConnectionError, + WLEDEmptyResponseError, + WLEDError, + WLEDInvalidResponseError, +) from homeassistant.components.light import ( ATTR_BRIGHTNESS, @@ -285,6 +291,34 @@ async def test_single_segment_behavior( ("side_effect", "expected_state", "expected_translation_key"), [ (WLEDError, STATE_ON, "invalid_response_wled_error"), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /json" + ), + STATE_ON, + "invalid_response_wled_error", + ), + ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + STATE_ON, + "invalid_response_presets_wled_error", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on full update" + ), + STATE_ON, + "invalid_response_wled_error", + ), + ( + WLEDEmptyResponseError( + "WLED device at X returned an empty API response on presets update" + ), + STATE_ON, + "invalid_response_presets_wled_error", + ), (WLEDConnectionError, STATE_UNAVAILABLE, "connection_error"), ], ) diff --git a/tests/components/wled/test_number.py b/tests/components/wled/test_number.py index a99f72d1dd4341..542d71120e2776 100644 --- a/tests/components/wled/test_number.py +++ b/tests/components/wled/test_number.py @@ -6,7 +6,12 @@ from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion -from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError +from wled import ( + Device as WLEDDevice, + WLEDConnectionError, + WLEDError, + WLEDInvalidResponseError, +) from homeassistant.components.number import ( ATTR_VALUE, @@ -100,6 +105,25 @@ async def test_numbers( assert (state := hass.states.get(entity_id)) assert state.state != STATE_UNAVAILABLE + # Test with WLED error + mock_wled.segment.side_effect = WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ) + with pytest.raises( + HomeAssistantError, match="Check preset configurations in WLED UI." + ): + await hass.services.async_call( + NUMBER_DOMAIN, + SERVICE_SET_VALUE, + {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value}, + blocking=True, + ) + assert mock_wled.segment.call_count == 3 + + # Ensure the entity is still available + assert (state := hass.states.get(entity_id)) + assert state.state != STATE_UNAVAILABLE + # Test when a connection error occurs mock_wled.segment.side_effect = WLEDConnectionError with pytest.raises(HomeAssistantError, match="Error communicating with WLED API"): @@ -109,7 +133,7 @@ async def test_numbers( {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value}, blocking=True, ) - assert mock_wled.segment.call_count == 3 + assert mock_wled.segment.call_count == 4 # Ensure the entity became unavailable after the connection error assert (state := hass.states.get(entity_id)) diff --git a/tests/components/wled/test_select.py b/tests/components/wled/test_select.py index fe4f45f9458432..177392758c4f0b 100644 --- a/tests/components/wled/test_select.py +++ b/tests/components/wled/test_select.py @@ -14,6 +14,7 @@ Preset as WLEDPreset, WLEDConnectionError, WLEDError, + WLEDInvalidResponseError, ) from homeassistant.components.select import ATTR_OPTION, DOMAIN as SELECT_DOMAIN @@ -126,6 +127,27 @@ async def test_color_palette_state( assert method_mock.call_count == 2 method_mock.assert_called_with(**called_with) + # Test invalid preset response, not becoming unavailable + method_mock.side_effect = ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + ) + with pytest.raises( + HomeAssistantError, match="Check preset configurations in WLED UI." + ): + await hass.services.async_call( + SELECT_DOMAIN, + SERVICE_SELECT_OPTION, + {ATTR_ENTITY_ID: entity_id, ATTR_OPTION: option}, + blocking=True, + ) + + assert (state := hass.states.get(entity_id)) + assert state.state != STATE_UNAVAILABLE + assert method_mock.call_count == 3 + method_mock.assert_called_with(**called_with) + # Test connection error, leading to becoming unavailable method_mock.side_effect = WLEDConnectionError with pytest.raises(HomeAssistantError, match="Error communicating with WLED API"): @@ -138,7 +160,7 @@ async def test_color_palette_state( assert (state := hass.states.get(state.entity_id)) assert state.state == STATE_UNAVAILABLE - assert method_mock.call_count == 3 + assert method_mock.call_count == 4 method_mock.assert_called_with(**called_with) diff --git a/tests/components/wled/test_switch.py b/tests/components/wled/test_switch.py index 7d834c09efd5c1..d8280c44df9f5d 100644 --- a/tests/components/wled/test_switch.py +++ b/tests/components/wled/test_switch.py @@ -6,7 +6,12 @@ from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion -from wled import Device as WLEDDevice, WLEDConnectionError, WLEDError +from wled import ( + Device as WLEDDevice, + WLEDConnectionError, + WLEDError, + WLEDInvalidResponseError, +) from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.wled.const import DOMAIN, SCAN_INTERVAL @@ -135,6 +140,26 @@ async def test_switch_state( assert (state := hass.states.get(entity_id)) assert state.state != STATE_UNAVAILABLE + # Test invalid preset response, not becoming unavailable + method_mock.side_effect = ( + WLEDInvalidResponseError( + "Received a non-UTF-8 response from request: GET /presets.json" + ), + ) + with pytest.raises( + HomeAssistantError, match="Check preset configurations in WLED UI." + ): + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + + assert method_mock.call_count == 4 + assert (state := hass.states.get(entity_id)) + assert state.state != STATE_UNAVAILABLE + # Test connection error, leading to becoming unavailable method_mock.side_effect = WLEDConnectionError with pytest.raises(HomeAssistantError, match="Error communicating with WLED API"): @@ -145,7 +170,7 @@ async def test_switch_state( blocking=True, ) - assert method_mock.call_count == 4 + assert method_mock.call_count == 5 assert (state := hass.states.get(state.entity_id)) assert state.state == STATE_UNAVAILABLE diff --git a/tests/components/wled/test_update.py b/tests/components/wled/test_update.py index dc0f409ac7d61e..66f527321161d2 100644 --- a/tests/components/wled/test_update.py +++ b/tests/components/wled/test_update.py @@ -6,7 +6,7 @@ from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion -from wled import Releases, WLEDError +from wled import Releases, WLEDConnectionError, WLEDUpgradeError from homeassistant.components.update import ( ATTR_INSTALLED_VERSION, @@ -14,16 +14,16 @@ DOMAIN as UPDATE_DOMAIN, SERVICE_INSTALL, ) -from homeassistant.components.wled.const import RELEASES_SCAN_INTERVAL +from homeassistant.components.wled.const import DOMAIN, RELEASES_SCAN_INTERVAL from homeassistant.const import ( ATTR_ENTITY_ID, STATE_OFF, STATE_ON, - STATE_UNAVAILABLE, STATE_UNKNOWN, Platform, ) from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform @@ -92,24 +92,38 @@ async def test_no_update_available( assert snapshot == state +@pytest.mark.parametrize( + ("exception", "expected_translation_key"), + [ + ( + WLEDConnectionError("Some error"), + "connection_error", + ), + ( + WLEDUpgradeError("Requested firmware file X does not exist"), + "install_update_wled_error", + ), + ], +) async def test_update_error( hass: HomeAssistant, mock_wled: MagicMock, caplog: pytest.LogCaptureFixture, + exception: Exception, + expected_translation_key: str, ) -> None: - """Test error handling of the WLED update.""" - mock_wled.update.side_effect = WLEDError - - await hass.services.async_call( - UPDATE_DOMAIN, - SERVICE_INSTALL, - {ATTR_ENTITY_ID: "update.wled_rgb_light_firmware"}, - blocking=True, - ) - - assert (state := hass.states.get("update.wled_rgb_light_firmware")) - assert state.state == STATE_UNAVAILABLE - assert "Invalid response from WLED API" in caplog.text + """Test error handling of the WLED new firmware installation.""" + mock_wled.upgrade.side_effect = exception + + with pytest.raises(HomeAssistantError) as ex: + await hass.services.async_call( + UPDATE_DOMAIN, + SERVICE_INSTALL, + {ATTR_ENTITY_ID: "update.wled_rgb_light_firmware"}, + blocking=True, + ) + assert ex.value.translation_domain == DOMAIN + assert ex.value.translation_key == expected_translation_key async def test_update_stay_stable(