mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Add OptionsFlow to SMTP integration (#173386)
This commit is contained in:
@@ -22,6 +22,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
CONF_RECIPIENT: [
|
||||
subentry.unique_id for subentry in entry.subentries.values()
|
||||
],
|
||||
**entry.options,
|
||||
},
|
||||
{},
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ from homeassistant.config_entries import (
|
||||
ConfigSubentryData,
|
||||
ConfigSubentryFlow,
|
||||
FlowType,
|
||||
OptionsFlow,
|
||||
SubentryFlowContext,
|
||||
SubentryFlowResult,
|
||||
)
|
||||
@@ -25,12 +26,17 @@ from homeassistant.const import (
|
||||
CONF_PORT,
|
||||
CONF_RECIPIENT,
|
||||
CONF_SENDER,
|
||||
CONF_TIMEOUT,
|
||||
CONF_USERNAME,
|
||||
CONF_VERIFY_SSL,
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.selector import (
|
||||
NumberSelector,
|
||||
NumberSelectorConfig,
|
||||
NumberSelectorMode,
|
||||
SelectSelector,
|
||||
SelectSelectorConfig,
|
||||
SelectSelectorMode,
|
||||
@@ -90,6 +96,23 @@ STEP_USER_DATA_SCHEMA = vol.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
OPTIONS_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.All(
|
||||
NumberSelector(
|
||||
NumberSelectorConfig(
|
||||
min=1,
|
||||
max=1800,
|
||||
step=1,
|
||||
unit_of_measurement=UnitOfTime.SECONDS,
|
||||
mode=NumberSelectorMode.BOX,
|
||||
)
|
||||
),
|
||||
vol.Coerce(int),
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class MailConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for SMTP."""
|
||||
@@ -102,6 +125,12 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Return subentries supported by this integration."""
|
||||
return {SUBENTRY_TYPE_RECIPIENT: RecipientSubentryFlowHandler}
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlowHandler:
|
||||
"""Get the options flow for this handler."""
|
||||
return OptionsFlowHandler()
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@@ -144,6 +173,7 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
async def async_step_import(self, import_info: dict[str, Any]) -> ConfigFlowResult:
|
||||
"""Import config from yaml."""
|
||||
|
||||
options = {CONF_TIMEOUT: import_info.pop(CONF_TIMEOUT, DEFAULT_TIMEOUT)}
|
||||
self._async_abort_entries_match(import_info)
|
||||
|
||||
errors = await self.hass.async_add_executor_job(validate_input, import_info)
|
||||
@@ -156,6 +186,7 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
return self.async_create_entry(
|
||||
title=title,
|
||||
data=import_info,
|
||||
options=options,
|
||||
subentries=[
|
||||
ConfigSubentryData(
|
||||
subentry_type=SUBENTRY_TYPE_RECIPIENT,
|
||||
@@ -238,3 +269,21 @@ class RecipientSubentryFlowHandler(ConfigSubentryFlow):
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class OptionsFlowHandler(OptionsFlow):
|
||||
"""Handle options flow."""
|
||||
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Manage the options."""
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(data=user_input)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
data_schema=self.add_suggested_values_to_schema(
|
||||
OPTIONS_SCHEMA, self.config_entry.options
|
||||
),
|
||||
)
|
||||
|
||||
@@ -70,6 +70,18 @@
|
||||
"title": "Failed to import SMTP YAML configuration"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"timeout": "Connection timeout"
|
||||
},
|
||||
"data_description": {
|
||||
"timeout": "Maximum time to wait for a response from the SMTP server before the connection attempt is aborted."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
"encryption": {
|
||||
"options": {
|
||||
|
||||
@@ -17,6 +17,7 @@ from homeassistant.const import (
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_SENDER,
|
||||
CONF_TIMEOUT,
|
||||
CONF_USERNAME,
|
||||
CONF_VERIFY_SSL,
|
||||
)
|
||||
@@ -74,6 +75,9 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
CONF_PASSWORD: "test-password",
|
||||
CONF_VERIFY_SSL: True,
|
||||
},
|
||||
options={
|
||||
CONF_TIMEOUT: 5,
|
||||
},
|
||||
entry_id="123456789",
|
||||
subentries_data=[
|
||||
ConfigSubentryData(
|
||||
|
||||
@@ -14,13 +14,14 @@ from homeassistant.components.smtp.const import (
|
||||
DOMAIN,
|
||||
SUBENTRY_TYPE_RECIPIENT,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_USER, FlowType
|
||||
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState, FlowType
|
||||
from homeassistant.const import (
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_RECIPIENT,
|
||||
CONF_SENDER,
|
||||
CONF_TIMEOUT,
|
||||
CONF_USERNAME,
|
||||
CONF_VERIFY_SSL,
|
||||
)
|
||||
@@ -221,3 +222,33 @@ async def test_form_recipient_already_configured(
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_options_flow(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test options flow."""
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_TIMEOUT: 10,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert config_entry.options == {
|
||||
CONF_TIMEOUT: 10,
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ async def test_import(
|
||||
CONF_PASSWORD: "test-password",
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_RECIPIENT: "recipient@example.com",
|
||||
CONF_TIMEOUT: 10,
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -98,9 +99,9 @@ async def test_import(
|
||||
CONF_PASSWORD: "test-password",
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_RECIPIENT: ["recipient@example.com"],
|
||||
CONF_TIMEOUT: 5,
|
||||
CONF_DEBUG: False,
|
||||
}
|
||||
assert entries[0].options == {CONF_TIMEOUT: 10}
|
||||
|
||||
assert list(entries[0].subentries.values())[0].unique_id == "recipient@example.com"
|
||||
|
||||
@@ -133,7 +134,6 @@ async def test_import_already_configured(
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_RECIPIENT: ["recipient@example.com"],
|
||||
CONF_DEBUG: False,
|
||||
CONF_TIMEOUT: 5,
|
||||
},
|
||||
entry_id="123456789",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user