From 0dc681ca7af5aff104eed4e5fe6fa229d8552cde Mon Sep 17 00:00:00 2001 From: Christophe Gagnier Date: Mon, 24 Aug 2026 21:10:55 -0400 Subject: [PATCH] Handle all TechnoVE API errors in config flow (#180061) --- .../components/technove/config_flow.py | 6 +-- tests/components/technove/test_config_flow.py | 49 +++++++++++++++---- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/technove/config_flow.py b/homeassistant/components/technove/config_flow.py index 0d54e9bacb2c..fb4eabff5482 100644 --- a/homeassistant/components/technove/config_flow.py +++ b/homeassistant/components/technove/config_flow.py @@ -2,7 +2,7 @@ from typing import Any, override -from technove import Station as TechnoVEStation, TechnoVE, TechnoVEConnectionError +from technove import Station as TechnoVEStation, TechnoVE, TechnoVEError import voluptuous as vol from homeassistant.components import onboarding @@ -34,7 +34,7 @@ class TechnoVEConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: try: station = await self._async_get_station(user_input[CONF_HOST]) - except TechnoVEConnectionError: + except TechnoVEError: errors["base"] = "cannot_connect" else: await self.async_set_unique_id( @@ -98,7 +98,7 @@ class TechnoVEConfigFlow(ConfigFlow, domain=DOMAIN): self.discovered_host = discovery_info.host try: self.discovered_station = await self._async_get_station(discovery_info.host) - except TechnoVEConnectionError: + except TechnoVEError: return self.async_abort(reason="cannot_connect") await self.async_set_unique_id(self.discovered_station.info.mac_address) diff --git a/tests/components/technove/test_config_flow.py b/tests/components/technove/test_config_flow.py index 1d24f4b60af6..c02232337ec9 100644 --- a/tests/components/technove/test_config_flow.py +++ b/tests/components/technove/test_config_flow.py @@ -5,7 +5,7 @@ from ipaddress import ip_address from unittest.mock import AsyncMock, MagicMock import pytest -from technove import TechnoVEConnectionError +from technove import TechnoVEConnectionError, TechnoVEError from homeassistant.components.technove.const import DOMAIN from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF @@ -63,9 +63,18 @@ async def test_user_device_exists_abort( assert result.get("reason") == "already_configured" -async def test_connection_error(hass: HomeAssistant, mock_technove: MagicMock) -> None: - """Test we show user form on TechnoVE connection error.""" - mock_technove.update.side_effect = TechnoVEConnectionError +@pytest.mark.parametrize( + "error", + [ + TechnoVEConnectionError, + TechnoVEError, + ], +) +async def test_connection_error( + hass: HomeAssistant, mock_technove: MagicMock, error: type[Exception] +) -> None: + """Test we show user form on TechnoVE error.""" + mock_technove.update.side_effect = error result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, @@ -83,12 +92,19 @@ async def test_connection_error(hass: HomeAssistant, mock_technove: MagicMock) - assert result.get("errors") == {"base": "cannot_connect"} +@pytest.mark.parametrize( + "error", + [ + TechnoVEConnectionError, + TechnoVEError, + ], +) @pytest.mark.usefixtures("mock_setup_entry", "mock_technove") async def test_full_user_flow_with_error( - hass: HomeAssistant, mock_technove: MagicMock + hass: HomeAssistant, mock_technove: MagicMock, error: type[Exception] ) -> None: """Test the full manual user flow with some errors in the middle.""" - mock_technove.update.side_effect = TechnoVEConnectionError + mock_technove.update.side_effect = error result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, @@ -187,11 +203,18 @@ async def test_zeroconf_during_onboarding( assert len(mock_onboarding.mock_calls) == 1 +@pytest.mark.parametrize( + "error", + [ + TechnoVEConnectionError, + TechnoVEError, + ], +) async def test_zeroconf_connection_error( - hass: HomeAssistant, mock_technove: MagicMock + hass: HomeAssistant, mock_technove: MagicMock, error: type[Exception] ) -> None: """Test we abort zeroconf flow on TechnoVE connection error.""" - mock_technove.update.side_effect = TechnoVEConnectionError + mock_technove.update.side_effect = error result = await hass.config_entries.flow.async_init( DOMAIN, @@ -333,16 +356,24 @@ async def test_full_reconfigure_flow_unique_id_mismatch( assert result.get("reason") == "unique_id_mismatch" +@pytest.mark.parametrize( + "error", + [ + TechnoVEConnectionError, + TechnoVEError, + ], +) @pytest.mark.usefixtures("mock_setup_entry") async def test_full_reconfigure_flow_connection_error_and_success( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_technove: MagicMock, + error: type[Exception], ) -> None: """Test reconfigure flow with connection error, then successful recovery.""" mock_config_entry.add_to_hass(hass) - mock_technove.update.side_effect = TechnoVEConnectionError + mock_technove.update.side_effect = error result = await mock_config_entry.start_reconfigure_flow(hass)