diff --git a/homeassistant/components/trafikverket_camera/config_flow.py b/homeassistant/components/trafikverket_camera/config_flow.py index 77019f3362f7d..fb6f6feeccfd8 100644 --- a/homeassistant/components/trafikverket_camera/config_flow.py +++ b/homeassistant/components/trafikverket_camera/config_flow.py @@ -29,7 +29,7 @@ class TVCameraConfigFlow(ConfigFlow, domain=DOMAIN): VERSION = 3 - entry: ConfigEntry | None + entry: ConfigEntry cameras: list[CameraInfoModel] api_key: str @@ -58,7 +58,7 @@ async def async_step_reauth( ) -> ConfigFlowResult: """Handle re-authentication with Trafikverket.""" - self.entry = self.hass.config_entries.async_get_entry(self.context["entry_id"]) + self.entry = self._get_reauth_entry() return await self.async_step_reauth_confirm() async def async_step_reauth_confirm( @@ -92,6 +92,57 @@ async def async_step_reauth_confirm( errors=errors, ) + async def async_step_reconfigure( + self, entry_data: Mapping[str, Any] + ) -> ConfigFlowResult: + """Handle re-configuration with Trafikverket.""" + + self.entry = self._get_reconfigure_entry() + return await self.async_step_reconfigure_confirm() + + async def async_step_reconfigure_confirm( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Confirm re-configuration with Trafikverket.""" + errors: dict[str, str] = {} + + if user_input: + api_key = user_input[CONF_API_KEY] + location = user_input[CONF_LOCATION] + + errors, cameras = await self.validate_input(api_key, location) + + if not errors and cameras: + if len(cameras) > 1: + self.cameras = cameras + self.api_key = api_key + return await self.async_step_multiple_cameras() + await self.async_set_unique_id(f"{DOMAIN}-{cameras[0].camera_id}") + self._abort_if_unique_id_configured() + return self.async_update_reload_and_abort( + self.entry, + unique_id=f"{DOMAIN}-{cameras[0].camera_id}", + title=cameras[0].camera_name or "Trafikverket Camera", + data={CONF_API_KEY: api_key, CONF_ID: cameras[0].camera_id}, + reason="reconfigure_successful", + ) + + schema = self.add_suggested_values_to_schema( + vol.Schema( + { + vol.Required(CONF_API_KEY): TextSelector(), + vol.Required(CONF_LOCATION): TextSelector(), + } + ), + {**self.entry.data, **(user_input or {})}, + ) + + return self.async_show_form( + step_id="reconfigure_confirm", + data_schema=schema, + errors=errors, + ) + async def async_step_user( self, user_input: dict[str, str] | None = None ) -> ConfigFlowResult: @@ -138,6 +189,17 @@ async def async_step_multiple_cameras( ) if not errors and cameras: + if hasattr(self, "entry") and self.entry: + return self.async_update_reload_and_abort( + self.entry, + unique_id=f"{DOMAIN}-{cameras[0].camera_id}", + title=cameras[0].camera_name or "Trafikverket Camera", + data={ + CONF_API_KEY: self.api_key, + CONF_ID: cameras[0].camera_id, + }, + reason="reconfigure_successful", + ) await self.async_set_unique_id(f"{DOMAIN}-{cameras[0].camera_id}") self._abort_if_unique_id_configured() return self.async_create_entry( diff --git a/homeassistant/components/trafikverket_camera/strings.json b/homeassistant/components/trafikverket_camera/strings.json index e3a1ceec4c0a3..142dcba5e8542 100644 --- a/homeassistant/components/trafikverket_camera/strings.json +++ b/homeassistant/components/trafikverket_camera/strings.json @@ -2,7 +2,8 @@ "config": { "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", - "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", + "reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]" }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", diff --git a/tests/components/trafikverket_camera/test_config_flow.py b/tests/components/trafikverket_camera/test_config_flow.py index dd75f5e6838d1..a940f31f7f3e7 100644 --- a/tests/components/trafikverket_camera/test_config_flow.py +++ b/tests/components/trafikverket_camera/test_config_flow.py @@ -309,3 +309,150 @@ async def test_reauth_flow_error( "api_key": "1234567891", "id": "1234", } + + +async def test_reconfigure_flow( + hass: HomeAssistant, + get_cameras: list[CameraInfoModel], + get_camera2: CameraInfoModel, +) -> None: + """Test a reconfigure flow.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_API_KEY: "1234567890", + CONF_ID: "1234", + }, + unique_id="1234", + version=3, + ) + entry.add_to_hass(hass) + + result = await entry.start_reconfigure_flow(hass) + assert result["step_id"] == "reconfigure_confirm" + assert result["type"] is FlowResultType.FORM + assert result["errors"] == {} + + with patch( + "homeassistant.components.trafikverket_camera.config_flow.TrafikverketCamera.async_get_cameras", + return_value=get_cameras, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_API_KEY: "1234567890", + CONF_LOCATION: "Test loc", + }, + ) + await hass.async_block_till_done() + + with ( + patch( + "homeassistant.components.trafikverket_camera.config_flow.TrafikverketCamera.async_get_cameras", + return_value=[get_camera2], + ), + patch( + "homeassistant.components.trafikverket_camera.async_setup_entry", + return_value=True, + ), + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_ID: "5678", + }, + ) + await hass.async_block_till_done() + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + assert entry.data == { + "api_key": "1234567890", + "id": "5678", + } + + +@pytest.mark.parametrize( + ("side_effect", "error_key", "p_error"), + [ + ( + InvalidAuthentication, + "base", + "invalid_auth", + ), + ( + NoCameraFound, + "location", + "invalid_location", + ), + ( + UnknownError, + "base", + "cannot_connect", + ), + ], +) +async def test_reconfigure_flow_error( + hass: HomeAssistant, + get_camera: CameraInfoModel, + side_effect: Exception, + error_key: str, + p_error: str, +) -> None: + """Test a reauthentication flow with error.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_API_KEY: "1234567890", + CONF_ID: "1234", + }, + unique_id="1234", + version=3, + ) + entry.add_to_hass(hass) + await hass.async_block_till_done() + + result = await entry.start_reconfigure_flow(hass) + + with patch( + "homeassistant.components.trafikverket_camera.config_flow.TrafikverketCamera.async_get_cameras", + side_effect=side_effect, + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_API_KEY: "1234567890", + CONF_LOCATION: "Test loc", + }, + ) + await hass.async_block_till_done() + + assert result2["step_id"] == "reconfigure_confirm" + assert result2["type"] is FlowResultType.FORM + assert result2["errors"] == {error_key: p_error} + + with ( + patch( + "homeassistant.components.trafikverket_camera.config_flow.TrafikverketCamera.async_get_cameras", + return_value=[get_camera], + ), + patch( + "homeassistant.components.trafikverket_camera.async_setup_entry", + return_value=True, + ), + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_API_KEY: "1234567891", + CONF_LOCATION: "Test loc", + }, + ) + await hass.async_block_till_done() + + assert result2["type"] is FlowResultType.ABORT + assert result2["reason"] == "reconfigure_successful" + assert entry.data == { + CONF_ID: "1234", + CONF_API_KEY: "1234567891", + }