From 6184fd26d384c96553de8bb62388ae95dec8bf92 Mon Sep 17 00:00:00 2001 From: Sid <27780930+autinerd@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:13:12 +0200 Subject: [PATCH] Add options flow to enigma2 (#115795) Co-authored-by: Franck Nijhof --- .../components/enigma2/config_flow.py | 48 +++++++++++++++++-- homeassistant/components/enigma2/strings.json | 14 ++++++ tests/components/enigma2/conftest.py | 11 +++++ tests/components/enigma2/test_config_flow.py | 33 +++++++++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/enigma2/config_flow.py b/homeassistant/components/enigma2/config_flow.py index b628d10b91a..b9ae6ffbebf 100644 --- a/homeassistant/components/enigma2/config_flow.py +++ b/homeassistant/components/enigma2/config_flow.py @@ -1,6 +1,6 @@ """Config flow for Enigma2.""" -from typing import Any +from typing import Any, cast from aiohttp.client_exceptions import ClientError from openwebif.api import OpenWebIfDevice @@ -8,7 +8,12 @@ from openwebif.error import InvalidAuthError import voluptuous as vol from yarl import URL -from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult +from homeassistant.config_entries import ( + SOURCE_USER, + ConfigEntry, + ConfigFlow, + ConfigFlowResult, +) from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, @@ -17,10 +22,15 @@ from homeassistant.const import ( CONF_USERNAME, CONF_VERIFY_SSL, ) -from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN +from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, callback from homeassistant.helpers import selector from homeassistant.helpers.aiohttp_client import async_create_clientsession from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue +from homeassistant.helpers.schema_config_entry_flow import ( + SchemaCommonFlowHandler, + SchemaFlowFormStep, + SchemaOptionsFlowHandler, +) from .const import ( CONF_DEEP_STANDBY, @@ -55,6 +65,32 @@ CONFIG_SCHEMA = vol.Schema( ) +async def get_options_schema(handler: SchemaCommonFlowHandler) -> vol.Schema: + """Get the options schema.""" + hass = handler.parent_handler.hass + entry = cast(SchemaOptionsFlowHandler, handler.parent_handler).config_entry + device: OpenWebIfDevice = hass.data[DOMAIN][entry.entry_id] + bouquets = [b[1] for b in (await device.get_all_bouquets())["bouquets"]] + + return vol.Schema( + { + vol.Optional(CONF_DEEP_STANDBY): selector.BooleanSelector(), + vol.Optional(CONF_SOURCE_BOUQUET): selector.SelectSelector( + selector.SelectSelectorConfig( + options=bouquets, + mode=selector.SelectSelectorMode.DROPDOWN, + ) + ), + vol.Optional(CONF_USE_CHANNEL_ICON): selector.BooleanSelector(), + } + ) + + +OPTIONS_FLOW = { + "init": SchemaFlowFormStep(get_options_schema), +} + + class Enigma2ConfigFlowHandler(ConfigFlow, domain=DOMAIN): """Handle a config flow for Enigma2.""" @@ -163,3 +199,9 @@ class Enigma2ConfigFlowHandler(ConfigFlow, domain=DOMAIN): return self.async_create_entry( data=data, title=data[CONF_HOST], options=options ) + + @staticmethod + @callback + def async_get_options_flow(config_entry: ConfigEntry) -> SchemaOptionsFlowHandler: + """Get the options flow for this handler.""" + return SchemaOptionsFlowHandler(config_entry, OPTIONS_FLOW) diff --git a/homeassistant/components/enigma2/strings.json b/homeassistant/components/enigma2/strings.json index ddeb59ea6d5..f74806b60a2 100644 --- a/homeassistant/components/enigma2/strings.json +++ b/homeassistant/components/enigma2/strings.json @@ -26,6 +26,20 @@ "unknown": "[%key:common::config_flow::error::unknown%]" } }, + "options": { + "step": { + "init": { + "data": { + "deep_standby": "Turn off to Deep Standby", + "source_bouquet": "Bouquet to use as media source", + "use_channel_icon": "Show channel icon as media image" + }, + "data_description": { + "deep_standby": "Turn off the device to Deep Standby (shutdown) instead of standby mode." + } + } + } + }, "issues": { "deprecated_yaml_import_issue_unknown": { "title": "The Enigma2 YAML configuration import failed", diff --git a/tests/components/enigma2/conftest.py b/tests/components/enigma2/conftest.py index 9bbbda895bd..f879fb327d7 100644 --- a/tests/components/enigma2/conftest.py +++ b/tests/components/enigma2/conftest.py @@ -86,5 +86,16 @@ class MockDevice: """Get mock about endpoint.""" return await self._call_api("/api/about") + async def get_all_bouquets(self) -> dict: + """Get all bouquets.""" + return { + "bouquets": [ + [ + '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet', + "Favourites (TV)", + ] + ] + } + async def close(self): """Mock close.""" diff --git a/tests/components/enigma2/test_config_flow.py b/tests/components/enigma2/test_config_flow.py index b4bcb29f0ac..a1074ed9e34 100644 --- a/tests/components/enigma2/test_config_flow.py +++ b/tests/components/enigma2/test_config_flow.py @@ -23,6 +23,8 @@ from .conftest import ( MockDevice, ) +from tests.common import MockConfigEntry + @pytest.fixture async def user_flow(hass: HomeAssistant) -> str: @@ -164,3 +166,34 @@ async def test_form_import_errors( assert issue.issue_domain == DOMAIN assert result["type"] is FlowResultType.ABORT assert result["reason"] == error_type + + +async def test_options_flow(hass: HomeAssistant, user_flow: str): + """Test the form options.""" + + with patch( + "openwebif.api.OpenWebIfDevice.__new__", + return_value=MockDevice(), + ): + entry = MockConfigEntry(domain=DOMAIN, data=TEST_FULL, options={}, entry_id="1") + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.state is config_entries.ConfigEntryState.LOADED + + result = await hass.config_entries.options.async_init(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={"source_bouquet": "Favourites (TV)"} + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert entry.options == {"source_bouquet": "Favourites (TV)"} + + await hass.async_block_till_done() + + assert entry.state is config_entries.ConfigEntryState.LOADED