From 448a24802da4659f73dab33987d82891deac8005 Mon Sep 17 00:00:00 2001 From: Manu <4445816+tr4nt0r@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:08:02 +0100 Subject: [PATCH] Add reconfiguration flow to Bring! integration (#137529) --- homeassistant/components/bring/config_flow.py | 23 ++++ .../components/bring/quality_scale.yaml | 2 +- homeassistant/components/bring/strings.json | 18 +++- tests/components/bring/test_config_flow.py | 101 ++++++++++++++++++ 4 files changed, 141 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bring/config_flow.py b/homeassistant/components/bring/config_flow.py index 94f9e664a60..9e5f4da8356 100644 --- a/homeassistant/components/bring/config_flow.py +++ b/homeassistant/components/bring/config_flow.py @@ -107,6 +107,29 @@ class BringConfigFlow(ConfigFlow, domain=DOMAIN): errors=errors, ) + async def async_step_reconfigure( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Handle reconfiguration of the integration.""" + errors: dict[str, str] = {} + reconf_entry = self._get_reconfigure_entry() + + if user_input: + if not (errors := await self.validate_input(user_input)): + self._abort_if_unique_id_mismatch() + return self.async_update_reload_and_abort( + reconf_entry, data_updates=user_input + ) + + return self.async_show_form( + step_id="reconfigure", + data_schema=self.add_suggested_values_to_schema( + data_schema=STEP_USER_DATA_SCHEMA, + suggested_values={CONF_EMAIL: reconf_entry.data[CONF_EMAIL]}, + ), + errors=errors, + ) + async def validate_input(self, user_input: Mapping[str, Any]) -> dict[str, str]: """Auth Helper.""" diff --git a/homeassistant/components/bring/quality_scale.yaml b/homeassistant/components/bring/quality_scale.yaml index 2714b92680b..58e67ab0e11 100644 --- a/homeassistant/components/bring/quality_scale.yaml +++ b/homeassistant/components/bring/quality_scale.yaml @@ -60,7 +60,7 @@ rules: entity-translations: done exception-translations: done icon-translations: done - reconfiguration-flow: todo + reconfiguration-flow: done repair-issues: status: exempt comment: | diff --git a/homeassistant/components/bring/strings.json b/homeassistant/components/bring/strings.json index 7adf1a6a993..f8c261db3fd 100644 --- a/homeassistant/components/bring/strings.json +++ b/homeassistant/components/bring/strings.json @@ -27,17 +27,31 @@ "email": "[%key:component::bring::config::step::user::data_description::email%]", "password": "[%key:component::bring::config::step::user::data_description::email%]" } + }, + "reconfigure": { + "title": "Bring! configuration", + "description": "Update your credentials if you have changed your Bring! account email or password.", + "data": { + "email": "[%key:common::config_flow::data::email%]", + "password": "[%key:common::config_flow::data::password%]" + }, + "data_description": { + "email": "[%key:component::bring::config::step::user::data_description::email%]", + "password": "[%key:component::bring::config::step::user::data_description::email%]" + } } }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", - "unknown": "[%key:common::config_flow::error::unknown%]" + "unknown": "[%key:common::config_flow::error::unknown%]", + "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]" }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_service%]", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", - "unique_id_mismatch": "The login details correspond to a different account. Please re-authenticate to the previously configured account." + "unique_id_mismatch": "The login details correspond to a different account. Please re-authenticate to the previously configured account.", + "reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]" } }, "entity": { diff --git a/tests/components/bring/test_config_flow.py b/tests/components/bring/test_config_flow.py index 306f63525d1..b9208324c61 100644 --- a/tests/components/bring/test_config_flow.py +++ b/tests/components/bring/test_config_flow.py @@ -210,3 +210,104 @@ async def test_flow_reauth_unique_id_mismatch( assert result["type"] is FlowResultType.ABORT assert result["reason"] == "unique_id_mismatch" + + +@pytest.mark.usefixtures("mock_bring_client") +async def test_flow_reconfigure( + hass: HomeAssistant, bring_config_entry: MockConfigEntry +) -> None: + """Test reconfigure flow.""" + bring_config_entry.add_to_hass(hass) + result = await bring_config_entry.start_reconfigure_flow(hass) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_EMAIL: "new-email", CONF_PASSWORD: "new-password"}, + ) + + await hass.async_block_till_done() + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + assert bring_config_entry.data[CONF_EMAIL] == "new-email" + assert bring_config_entry.data[CONF_PASSWORD] == "new-password" + + assert len(hass.config_entries.async_entries()) == 1 + + +@pytest.mark.parametrize( + ("raise_error", "text_error"), + [ + (BringRequestException(), "cannot_connect"), + (BringAuthException(), "invalid_auth"), + (BringParseException(), "unknown"), + (IndexError(), "unknown"), + ], +) +async def test_flow_reconfigure_errors( + hass: HomeAssistant, + mock_bring_client: AsyncMock, + bring_config_entry: MockConfigEntry, + raise_error: Exception, + text_error: str, +) -> None: + """Test reconfigure flow errors.""" + bring_config_entry.add_to_hass(hass) + result = await bring_config_entry.start_reconfigure_flow(hass) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + mock_bring_client.login.side_effect = raise_error + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_EMAIL: "new-email", CONF_PASSWORD: "new-password"}, + ) + + await hass.async_block_till_done() + + assert result["type"] is FlowResultType.FORM + assert result["errors"] == {"base": text_error} + + mock_bring_client.login.side_effect = None + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_EMAIL: "new-email", CONF_PASSWORD: "new-password"}, + ) + + await hass.async_block_till_done() + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + assert bring_config_entry.data[CONF_EMAIL] == "new-email" + assert bring_config_entry.data[CONF_PASSWORD] == "new-password" + + assert len(hass.config_entries.async_entries()) == 1 + + +async def test_flow_reconfigure_unique_id_mismatch( + hass: HomeAssistant, + bring_config_entry: MockConfigEntry, + mock_bring_client: AsyncMock, +) -> None: + """Test we abort reconfigure if unique id mismatch.""" + + mock_bring_client.uuid = "11111111-11111111-11111111-11111111" + + bring_config_entry.add_to_hass(hass) + + result = await bring_config_entry.start_reconfigure_flow(hass) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {CONF_EMAIL: "new-email", CONF_PASSWORD: "new-password"}, + ) + + await hass.async_block_till_done() + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "unique_id_mismatch"