diff --git a/homeassistant/components/holiday/config_flow.py b/homeassistant/components/holiday/config_flow.py index f9108f02bc9..a9b2f3e9772 100644 --- a/homeassistant/components/holiday/config_flow.py +++ b/homeassistant/components/holiday/config_flow.py @@ -8,7 +8,7 @@ from babel import Locale, UnknownLocaleError from holidays import list_supported_countries import voluptuous as vol -from homeassistant.config_entries import ConfigFlow, ConfigFlowResult +from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_COUNTRY from homeassistant.helpers.selector import ( CountrySelector, @@ -27,6 +27,7 @@ class HolidayConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for Holiday.""" VERSION = 1 + config_entry: ConfigEntry | None def __init__(self) -> None: """Initialize the config flow.""" @@ -109,3 +110,64 @@ class HolidayConfigFlow(ConfigFlow, domain=DOMAIN): ) return self.async_show_form(step_id="province", data_schema=province_schema) + + async def async_step_reconfigure( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Handle the re-configuration of a province.""" + self.config_entry = self.hass.config_entries.async_get_entry( + self.context["entry_id"] + ) + return await self.async_step_reconfigure_confirm() + + async def async_step_reconfigure_confirm( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Handle the re-configuration of a province.""" + assert self.config_entry + + if user_input is not None: + combined_input: dict[str, Any] = {**self.config_entry.data, **user_input} + + country = combined_input[CONF_COUNTRY] + province = combined_input.get(CONF_PROVINCE) + + self._async_abort_entries_match( + { + CONF_COUNTRY: country, + CONF_PROVINCE: province, + } + ) + + try: + locale = Locale.parse(self.hass.config.language, sep="-") + except UnknownLocaleError: + # Default to (US) English if language not recognized by babel + # Mainly an issue with English flavors such as "en-GB" + locale = Locale("en") + province_str = f", {province}" if province else "" + name = f"{locale.territories[country]}{province_str}" + + return self.async_update_reload_and_abort( + self.config_entry, + title=name, + data=combined_input, + reason="reconfigure_successful", + ) + + province_schema = vol.Schema( + { + vol.Optional(CONF_PROVINCE): SelectSelector( + SelectSelectorConfig( + options=SUPPORTED_COUNTRIES[ + self.config_entry.data[CONF_COUNTRY] + ], + mode=SelectSelectorMode.DROPDOWN, + ) + ) + } + ) + + return self.async_show_form( + step_id="reconfigure_confirm", data_schema=province_schema + ) diff --git a/homeassistant/components/holiday/strings.json b/homeassistant/components/holiday/strings.json index 53d403e790e..de013f44d60 100644 --- a/homeassistant/components/holiday/strings.json +++ b/homeassistant/components/holiday/strings.json @@ -2,7 +2,8 @@ "title": "Holiday", "config": { "abort": { - "already_configured": "Already configured. Only a single configuration for country/province combination possible." + "already_configured": "Already configured. Only a single configuration for country/province combination possible.", + "reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]" }, "step": { "user": { @@ -14,6 +15,11 @@ "data": { "province": "Province" } + }, + "reconfigure_confirm": { + "data": { + "province": "[%key:component::holiday::config::step::province::data::province%]" + } } } } diff --git a/tests/components/holiday/test_config_flow.py b/tests/components/holiday/test_config_flow.py index eb21480fbb1..44a72f58404 100644 --- a/tests/components/holiday/test_config_flow.py +++ b/tests/components/holiday/test_config_flow.py @@ -219,3 +219,114 @@ async def test_form_babel_replace_dash_with_underscore(hass: HomeAssistant) -> N "country": "DE", "province": "BW", } + + +async def test_reconfigure(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None: + """Test reconfigure flow.""" + entry = MockConfigEntry( + domain=DOMAIN, + title="Germany, BW", + data={"country": "DE", "province": "BW"}, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={ + "source": config_entries.SOURCE_RECONFIGURE, + "entry_id": entry.entry_id, + }, + ) + assert result["type"] == FlowResultType.FORM + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_PROVINCE: "NW", + }, + ) + await hass.async_block_till_done() + + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + entry = hass.config_entries.async_get_entry(entry.entry_id) + assert entry.title == "Germany, NW" + assert entry.data == {"country": "DE", "province": "NW"} + + +async def test_reconfigure_incorrect_language( + hass: HomeAssistant, mock_setup_entry: AsyncMock +) -> None: + """Test reconfigure flow default to English.""" + hass.config.language = "en-XX" + + entry = MockConfigEntry( + domain=DOMAIN, + title="Germany, BW", + data={"country": "DE", "province": "BW"}, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={ + "source": config_entries.SOURCE_RECONFIGURE, + "entry_id": entry.entry_id, + }, + ) + assert result["type"] == FlowResultType.FORM + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_PROVINCE: "NW", + }, + ) + await hass.async_block_till_done() + + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + entry = hass.config_entries.async_get_entry(entry.entry_id) + assert entry.title == "Germany, NW" + assert entry.data == {"country": "DE", "province": "NW"} + + +async def test_reconfigure_entry_exists( + hass: HomeAssistant, mock_setup_entry: AsyncMock +) -> None: + """Test reconfigure flow stops if other entry already exist.""" + entry = MockConfigEntry( + domain=DOMAIN, + title="Germany, BW", + data={"country": "DE", "province": "BW"}, + ) + entry.add_to_hass(hass) + entry2 = MockConfigEntry( + domain=DOMAIN, + title="Germany, NW", + data={"country": "DE", "province": "NW"}, + ) + entry2.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={ + "source": config_entries.SOURCE_RECONFIGURE, + "entry_id": entry.entry_id, + }, + ) + assert result["type"] == FlowResultType.FORM + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_PROVINCE: "NW", + }, + ) + await hass.async_block_till_done() + + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + entry = hass.config_entries.async_get_entry(entry.entry_id) + assert entry.title == "Germany, BW" + assert entry.data == {"country": "DE", "province": "BW"}