diff --git a/homeassistant/components/vodafone_station/config_flow.py b/homeassistant/components/vodafone_station/config_flow.py index fd0683bdacc..6641f5f5711 100644 --- a/homeassistant/components/vodafone_station/config_flow.py +++ b/homeassistant/components/vodafone_station/config_flow.py @@ -139,6 +139,47 @@ class VodafoneStationConfigFlow(ConfigFlow, domain=DOMAIN): errors=errors, ) + async def async_step_reconfigure( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Handle reconfiguration of the device.""" + reconfigure_entry = self._get_reconfigure_entry() + if not user_input: + return self.async_show_form( + step_id="reconfigure", data_schema=user_form_schema(user_input) + ) + + updated_host = user_input[CONF_HOST] + + if reconfigure_entry.data[CONF_HOST] != updated_host: + self._async_abort_entries_match({CONF_HOST: updated_host}) + + errors: dict[str, str] = {} + + errors = {} + + try: + await validate_input(self.hass, user_input) + except aiovodafone_exceptions.AlreadyLogged: + errors["base"] = "already_logged" + except aiovodafone_exceptions.CannotConnect: + errors["base"] = "cannot_connect" + except aiovodafone_exceptions.CannotAuthenticate: + errors["base"] = "invalid_auth" + except Exception: # noqa: BLE001 + _LOGGER.exception("Unexpected exception") + errors["base"] = "unknown" + else: + return self.async_update_reload_and_abort( + reconfigure_entry, data_updates={CONF_HOST: updated_host} + ) + + return self.async_show_form( + step_id="reconfigure", + data_schema=user_form_schema(user_input), + errors=errors, + ) + class VodafoneStationOptionsFlowHandler(OptionsFlow): """Handle a option flow.""" diff --git a/homeassistant/components/vodafone_station/quality_scale.yaml b/homeassistant/components/vodafone_station/quality_scale.yaml index d8476842b53..d60020f5e47 100644 --- a/homeassistant/components/vodafone_station/quality_scale.yaml +++ b/homeassistant/components/vodafone_station/quality_scale.yaml @@ -64,9 +64,7 @@ rules: entity-translations: done exception-translations: done icon-translations: done - reconfiguration-flow: - status: todo - comment: handle host change + reconfiguration-flow: done repair-issues: status: exempt comment: no known use cases for repair issues or flows, yet diff --git a/homeassistant/components/vodafone_station/strings.json b/homeassistant/components/vodafone_station/strings.json index 6e308c35e4f..958b774a485 100644 --- a/homeassistant/components/vodafone_station/strings.json +++ b/homeassistant/components/vodafone_station/strings.json @@ -21,12 +21,25 @@ "username": "The username for your Vodafone Station.", "password": "The password for your Vodafone Station." } + }, + "reconfigure": { + "data": { + "host": "[%key:common::config_flow::data::host%]", + "username": "[%key:common::config_flow::data::username%]", + "password": "[%key:common::config_flow::data::password%]" + }, + "data_description": { + "host": "[%key:component::vodafone_station::config::step::user::data_description::host%]", + "username": "[%key:component::vodafone_station::config::step::user::data_description::username%]", + "password": "[%key:component::vodafone_station::config::step::user::data_description::password%]" + } } }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_service%]", "already_logged": "User already logged-in, please try again later.", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", + "reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", "model_not_supported": "The device model is currently unsupported.", diff --git a/tests/components/vodafone_station/test_config_flow.py b/tests/components/vodafone_station/test_config_flow.py index 68f8247bdf9..0648987eb27 100644 --- a/tests/components/vodafone_station/test_config_flow.py +++ b/tests/components/vodafone_station/test_config_flow.py @@ -228,3 +228,75 @@ async def test_options_flow( assert result["data"] == { CONF_CONSIDER_HOME: 37, } + + +async def test_reconfigure_successful( + hass: HomeAssistant, + mock_vodafone_station_router: AsyncMock, + mock_setup_entry: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test that the host can be reconfigured.""" + mock_config_entry.add_to_hass(hass) + result = await mock_config_entry.start_reconfigure_flow(hass) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + # original entry + assert mock_config_entry.data["host"] == "fake_host" + + reconfigure_result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + "host": "192.168.100.60", + "password": "fake_password", + "username": "fake_username", + }, + ) + + assert reconfigure_result["type"] is FlowResultType.ABORT + assert reconfigure_result["reason"] == "reconfigure_successful" + + # changed entry + assert mock_config_entry.data["host"] == "192.168.100.60" + + +@pytest.mark.parametrize( + ("side_effect", "error"), + [ + (CannotConnect, "cannot_connect"), + (CannotAuthenticate, "invalid_auth"), + (AlreadyLogged, "already_logged"), + (ConnectionResetError, "unknown"), + ], +) +async def test_reconfigure_fails( + hass: HomeAssistant, + mock_vodafone_station_router: AsyncMock, + mock_setup_entry: AsyncMock, + mock_config_entry: MockConfigEntry, + side_effect: Exception, + error: str, +) -> None: + """Test that the host can be reconfigured.""" + mock_config_entry.add_to_hass(hass) + result = await mock_config_entry.start_reconfigure_flow(hass) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + mock_vodafone_station_router.login.side_effect = side_effect + + reconfigure_result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + "host": "192.168.100.60", + "password": "fake_password", + "username": "fake_username", + }, + ) + + assert reconfigure_result["type"] is FlowResultType.FORM + assert reconfigure_result["step_id"] == "reconfigure" + assert reconfigure_result["errors"] == {"base": error}