From 09fb043f65b99b60d7dddd0ae55c4d5b3c96bc39 Mon Sep 17 00:00:00 2001 From: Simone Chemelli Date: Tue, 30 Jan 2024 10:28:01 +0100 Subject: [PATCH] Add configure option to Vodafone Station for consider home (#108594) * Add configure option to Vodafone Station for consider home * add test * improve tests * reload on option change --- .../components/vodafone_station/__init__.py | 8 ++++ .../vodafone_station/config_flow.py | 47 +++++++++++++++++-- .../components/vodafone_station/strings.json | 9 ++++ .../vodafone_station/test_config_flow.py | 36 ++++++++++---- 4 files changed, 85 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/vodafone_station/__init__.py b/homeassistant/components/vodafone_station/__init__.py index 66960921750..b4c44ea9130 100644 --- a/homeassistant/components/vodafone_station/__init__.py +++ b/homeassistant/components/vodafone_station/__init__.py @@ -24,6 +24,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator + entry.async_on_unload(entry.add_update_listener(update_listener)) + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True @@ -38,3 +40,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data[DOMAIN].pop(entry.entry_id) return unload_ok + + +async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Update when config_entry options update.""" + if entry.options: + await hass.config_entries.async_reload(entry.entry_id) diff --git a/homeassistant/components/vodafone_station/config_flow.py b/homeassistant/components/vodafone_station/config_flow.py index dc33d0db52b..987d4d71f41 100644 --- a/homeassistant/components/vodafone_station/config_flow.py +++ b/homeassistant/components/vodafone_station/config_flow.py @@ -7,9 +7,18 @@ from typing import Any from aiovodafone import VodafoneStationSercommApi, exceptions as aiovodafone_exceptions import voluptuous as vol -from homeassistant import core -from homeassistant.config_entries import ConfigEntry, ConfigFlow +from homeassistant.components.device_tracker import ( + CONF_CONSIDER_HOME, + DEFAULT_CONSIDER_HOME, +) +from homeassistant.config_entries import ( + ConfigEntry, + ConfigFlow, + OptionsFlow, + OptionsFlowWithConfigEntry, +) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME +from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from .const import _LOGGER, DEFAULT_HOST, DEFAULT_USERNAME, DOMAIN @@ -30,9 +39,7 @@ def user_form_schema(user_input: dict[str, Any] | None) -> vol.Schema: STEP_REAUTH_DATA_SCHEMA = vol.Schema({vol.Required(CONF_PASSWORD): str}) -async def validate_input( - hass: core.HomeAssistant, data: dict[str, Any] -) -> dict[str, str]: +async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, str]: """Validate the user input allows us to connect.""" api = VodafoneStationSercommApi( @@ -54,6 +61,12 @@ class VodafoneStationConfigFlow(ConfigFlow, domain=DOMAIN): VERSION = 1 entry: ConfigEntry | None = None + @staticmethod + @callback + def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow: + """Get the options flow for this handler.""" + return VodafoneStationOptionsFlowHandler(config_entry) + async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> FlowResult: @@ -133,3 +146,27 @@ class VodafoneStationConfigFlow(ConfigFlow, domain=DOMAIN): data_schema=STEP_REAUTH_DATA_SCHEMA, errors=errors, ) + + +class VodafoneStationOptionsFlowHandler(OptionsFlowWithConfigEntry): + """Handle a option flow.""" + + async def async_step_init( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: + """Handle options flow.""" + + if user_input is not None: + return self.async_create_entry(title="", data=user_input) + + data_schema = vol.Schema( + { + vol.Optional( + CONF_CONSIDER_HOME, + default=self.options.get( + CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME.total_seconds() + ), + ): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=900)) + } + ) + return self.async_show_form(step_id="init", data_schema=data_schema) diff --git a/homeassistant/components/vodafone_station/strings.json b/homeassistant/components/vodafone_station/strings.json index fab266ac47f..8910d7178b7 100644 --- a/homeassistant/components/vodafone_station/strings.json +++ b/homeassistant/components/vodafone_station/strings.json @@ -36,6 +36,15 @@ "unknown": "[%key:common::config_flow::error::unknown%]" } }, + "options": { + "step": { + "init": { + "data": { + "consider_home": "Seconds to consider a device at 'home'" + } + } + } + }, "entity": { "button": { "dsl_reconnect": { "name": "DSL reconnect" }, diff --git a/tests/components/vodafone_station/test_config_flow.py b/tests/components/vodafone_station/test_config_flow.py index 00b1ae6e72a..c04b8364f93 100644 --- a/tests/components/vodafone_station/test_config_flow.py +++ b/tests/components/vodafone_station/test_config_flow.py @@ -4,6 +4,8 @@ from unittest.mock import patch from aiovodafone import exceptions as aiovodafone_exceptions import pytest +from homeassistant import data_entry_flow +from homeassistant.components.device_tracker import CONF_CONSIDER_HOME from homeassistant.components.vodafone_station.const import DOMAIN from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME @@ -23,11 +25,7 @@ async def test_user(hass: HomeAssistant) -> None: "homeassistant.components.vodafone_station.config_flow.VodafoneStationSercommApi.logout", ), patch( "homeassistant.components.vodafone_station.async_setup_entry" - ) as mock_setup_entry, patch( - "requests.get", - ) as mock_request_get: - mock_request_get.return_value.status_code = 200 - + ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) @@ -123,11 +121,7 @@ async def test_reauth_successful(hass: HomeAssistant) -> None: "homeassistant.components.vodafone_station.config_flow.VodafoneStationSercommApi.logout", ), patch( "homeassistant.components.vodafone_station.async_setup_entry", - ), patch( - "requests.get", - ) as mock_request_get: - mock_request_get.return_value.status_code = 200 - + ): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_REAUTH, "entry_id": mock_config.entry_id}, @@ -216,3 +210,25 @@ async def test_reauth_not_successful(hass: HomeAssistant, side_effect, error) -> assert result2["type"] == FlowResultType.ABORT assert result2["reason"] == "reauth_successful" + + +async def test_options_flow(hass: HomeAssistant) -> None: + """Test options flow.""" + + mock_config = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) + mock_config.add_to_hass(hass) + + result = await hass.config_entries.options.async_init(mock_config.entry_id) + await hass.async_block_till_done() + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={ + CONF_CONSIDER_HOME: 37, + }, + ) + await hass.async_block_till_done() + + assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY + assert result["data"] == { + CONF_CONSIDER_HOME: 37, + }