1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-12 09:07:59 +01:00

Add subentry reconfigure flow to SMTP integration (#176152)

This commit is contained in:
Manu
2026-07-10 20:35:51 +02:00
committed by GitHub
parent f5accf6f02
commit db07a66c60
3 changed files with 204 additions and 3 deletions
+51 -1
View File
@@ -10,6 +10,7 @@ from typing import Any, override
import voluptuous as vol
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
from homeassistant.config_entries import (
SOURCE_USER,
ConfigFlow,
@@ -33,7 +34,7 @@ from homeassistant.const import (
UnitOfTime,
)
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.selector import (
NumberSelector,
NumberSelectorConfig,
@@ -359,6 +360,55 @@ class RecipientSubentryFlowHandler(ConfigSubentryFlow):
),
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> SubentryFlowResult:
"""Reconfigure flow to update a recipient."""
entry = self._get_entry()
subentry = self._get_reconfigure_subentry()
if user_input is not None:
old_unique_id = subentry.unique_id
result = self.async_update_and_abort(
entry,
subentry=subentry,
title=(
user_input[CONF_RECIPIENT]
if subentry.title == old_unique_id
else subentry.title
),
data_updates={},
unique_id=user_input[CONF_RECIPIENT],
)
if result.get("reason") == "reconfigure_successful" and (
entity := er.async_get(self.hass).async_get_entity_id(
NOTIFY_DOMAIN, DOMAIN, f"{entry.entry_id}_{old_unique_id}"
)
):
er.async_get(self.hass).async_update_entity(
entity,
new_unique_id=f"{entry.entry_id}_{user_input[CONF_RECIPIENT]}",
)
return result
return self.async_show_form(
step_id="reconfigure",
data_schema=self.add_suggested_values_to_schema(
data_schema=vol.Schema(
{
vol.Required(CONF_RECIPIENT): TextSelector(
TextSelectorConfig(
type=TextSelectorType.EMAIL,
autocomplete="email",
),
)
}
),
suggested_values={CONF_RECIPIENT: subentry.unique_id},
),
)
class OptionsFlowHandler(OptionsFlow):
"""Handle options flow."""
+12 -1
View File
@@ -74,13 +74,24 @@
"config_subentries": {
"recipient": {
"abort": {
"already_configured": "Recipient is already configured"
"already_configured": "Recipient is already configured",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
},
"entry_type": "Recipient",
"initiate_flow": {
"user": "Add recipient"
},
"step": {
"reconfigure": {
"data": {
"recipient": "[%key:common::config_flow::data::email%]"
},
"data_description": {
"recipient": "[%key:component::smtp::config_subentries::recipient::step::user::data_description::recipient%]"
},
"description": "Update the recipient email address.",
"title": "Reconfigure recipient"
},
"user": {
"data": {
"name": "[%key:common::config_flow::data::name%]",
+141 -1
View File
@@ -13,7 +13,13 @@ from homeassistant.components.smtp.const import (
DOMAIN,
SUBENTRY_TYPE_RECIPIENT,
)
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState, FlowType
from homeassistant.config_entries import (
SOURCE_RECONFIGURE,
SOURCE_USER,
ConfigEntryState,
ConfigSubentryData,
FlowType,
)
from homeassistant.const import (
CONF_NAME,
CONF_PASSWORD,
@@ -24,6 +30,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import entity_registry as er
from .conftest import USER_INPUT
@@ -442,3 +449,136 @@ async def test_form_reauth_errors(
CONF_PASSWORD: "new-password",
}
assert len(hass.config_entries.async_entries()) == 1
@pytest.mark.usefixtures("smtp")
async def test_form_subentry_reconfigure(
hass: HomeAssistant,
config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test subentry reconfigure flow."""
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert (
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
== 1
)
assert (entity := entity_registry.async_get("notify.home_assistant_recipient"))
assert entity.unique_id == "123456789_recipient@example.com"
result = await config_entry.start_subentry_reconfigure_flow(hass, "ABCDEF")
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == SOURCE_RECONFIGURE
result = await hass.config_entries.subentries.async_configure(
result["flow_id"],
user_input={CONF_RECIPIENT: "changed@example.com"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert config_entry.subentries["ABCDEF"].unique_id == "changed@example.com"
assert (
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
== 1
)
assert (entity := entity_registry.async_get("notify.home_assistant_recipient"))
assert entity.unique_id == "123456789_changed@example.com"
@pytest.mark.usefixtures("smtp")
async def test_form_subentry_reconfigure_already_configured(
hass: HomeAssistant,
) -> None:
"""Test we abort subentry reconfigure flow when already configured."""
config_entry = MockConfigEntry(
domain=DOMAIN,
title="Home Assistant",
data=USER_INPUT,
options={
CONF_TIMEOUT: 5,
},
entry_id="123456789",
subentries_data=[
ConfigSubentryData(
data={},
subentry_id="ABCDEF",
subentry_type=SUBENTRY_TYPE_RECIPIENT,
title="Recipient",
unique_id="recipient@example.com",
),
ConfigSubentryData(
data={},
subentry_id="GHIJKL",
subentry_type=SUBENTRY_TYPE_RECIPIENT,
title="Recipient2",
unique_id="changed@example.com",
),
],
)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await config_entry.start_subentry_reconfigure_flow(hass, "ABCDEF")
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == SOURCE_RECONFIGURE
result = await hass.config_entries.subentries.async_configure(
result["flow_id"],
user_input={CONF_RECIPIENT: "changed@example.com"},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.usefixtures("smtp")
async def test_form_subentry_reconfigure_updates_title(
hass: HomeAssistant,
) -> None:
"""Test subentry reconfigure flow updates subentry title if it matches email."""
config_entry = MockConfigEntry(
domain=DOMAIN,
title="Home Assistant",
data=USER_INPUT,
options={
CONF_TIMEOUT: 5,
},
entry_id="123456789",
subentries_data=[
ConfigSubentryData(
data={},
subentry_id="ABCDEF",
subentry_type=SUBENTRY_TYPE_RECIPIENT,
title="recipient@example.com",
unique_id="recipient@example.com",
)
],
)
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
result = await config_entry.start_subentry_reconfigure_flow(hass, "ABCDEF")
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == SOURCE_RECONFIGURE
result = await hass.config_entries.subentries.async_configure(
result["flow_id"],
user_input={CONF_RECIPIENT: "changed@example.com"},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
assert config_entry.subentries["ABCDEF"].unique_id == "changed@example.com"
assert config_entry.subentries["ABCDEF"].title == "changed@example.com"