From 04a5a1d18be52bfe354e4109d2f35b9dae2020c4 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Sun, 9 Jun 2024 16:02:58 +0200 Subject: [PATCH] Improve demo config flow and add tests (#118481) Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --- homeassistant/components/demo/__init__.py | 9 +- homeassistant/components/demo/config_flow.py | 3 + tests/components/demo/conftest.py | 14 ++- tests/components/demo/test_config_flow.py | 92 ++++++++++++++++++++ 4 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 tests/components/demo/test_config_flow.py diff --git a/homeassistant/components/demo/__init__.py b/homeassistant/components/demo/__init__.py index 738f6af38dd..371b783b653 100644 --- a/homeassistant/components/demo/__init__.py +++ b/homeassistant/components/demo/__init__.py @@ -65,12 +65,11 @@ CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN) async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the demo environment.""" - if not hass.config_entries.async_entries(DOMAIN): - hass.async_create_task( - hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={} - ) + hass.async_create_task( + hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={} ) + ) if DOMAIN not in config: return True diff --git a/homeassistant/components/demo/config_flow.py b/homeassistant/components/demo/config_flow.py index cc57ed9a460..468d9cb042b 100644 --- a/homeassistant/components/demo/config_flow.py +++ b/homeassistant/components/demo/config_flow.py @@ -39,6 +39,9 @@ class DemoConfigFlow(ConfigFlow, domain=DOMAIN): async def async_step_import(self, import_info: dict[str, Any]) -> ConfigFlowResult: """Set the config entry up from yaml.""" + if self._async_current_entries(): + return self.async_abort(reason="single_instance_allowed") + return self.async_create_entry(title="Demo", data=import_info) diff --git a/tests/components/demo/conftest.py b/tests/components/demo/conftest.py index 731a33360d7..56aabac0280 100644 --- a/tests/components/demo/conftest.py +++ b/tests/components/demo/conftest.py @@ -22,10 +22,16 @@ async def setup_homeassistant(hass: HomeAssistant): @pytest.fixture -async def disable_platforms(hass: HomeAssistant) -> None: +def disable_platforms(hass: HomeAssistant) -> None: """Disable platforms to speed up tests.""" - with patch( - "homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM", - [], + with ( + patch( + "homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM", + [], + ), + patch( + "homeassistant.components.demo.COMPONENTS_WITH_DEMO_PLATFORM", + [], + ), ): yield diff --git a/tests/components/demo/test_config_flow.py b/tests/components/demo/test_config_flow.py new file mode 100644 index 00000000000..a0b687e422a --- /dev/null +++ b/tests/components/demo/test_config_flow.py @@ -0,0 +1,92 @@ +"""Test the Demo config flow.""" + +from unittest.mock import patch + +import pytest + +from homeassistant import config_entries, setup +from homeassistant.components.demo import DOMAIN +from homeassistant.core import HomeAssistant +from homeassistant.data_entry_flow import FlowResultType + +from tests.common import MockConfigEntry + + +@pytest.mark.usefixtures("disable_platforms") +async def test_import(hass: HomeAssistant) -> None: + """Test that we can import a config entry.""" + with patch("homeassistant.components.demo.async_setup_entry", return_value=True): + assert await setup.async_setup_component(hass, DOMAIN, {DOMAIN: {}}) + await hass.async_block_till_done() + + assert len(hass.config_entries.async_entries(DOMAIN)) == 1 + entry = hass.config_entries.async_entries(DOMAIN)[0] + assert entry.data == {} + + +@pytest.mark.usefixtures("disable_platforms") +async def test_import_once(hass: HomeAssistant) -> None: + """Test that we don't create multiple config entries.""" + with patch( + "homeassistant.components.demo.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={}, + ) + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == "Demo" + assert result["data"] == {} + assert result["options"] == {} + mock_setup_entry.assert_called_once() + + # Test importing again doesn't create a 2nd entry + with patch("homeassistant.components.demo.async_setup_entry") as mock_setup_entry: + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={}, + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "single_instance_allowed" + mock_setup_entry.assert_not_called() + + +@pytest.mark.usefixtures("disable_platforms") +async def test_options_flow(hass: HomeAssistant) -> None: + """Test config flow options.""" + config_entry = MockConfigEntry(domain=DOMAIN) + 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 hass.config_entries.options.async_init(config_entry.entry_id) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "options_1" + + result = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={"bool": True, "constant": "Constant Value", "int": 15}, + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "options_2" + + result = await hass.config_entries.options.async_configure( + result["flow_id"], user_input={} + ) + assert result["type"] is FlowResultType.CREATE_ENTRY + assert config_entry.options == { + "bool": True, + "constant": "Constant Value", + "int": 15, + "multi": ["default"], + "select": "default", + "string": "Default", + } + + await hass.async_block_till_done() + assert await hass.config_entries.async_unload(config_entry.entry_id) + await hass.async_block_till_done()