diff --git a/homeassistant/components/switcher_kis/__init__.py b/homeassistant/components/switcher_kis/__init__.py index 49ac63de87a..abc9091742a 100644 --- a/homeassistant/components/switcher_kis/__init__.py +++ b/homeassistant/components/switcher_kis/__init__.py @@ -10,7 +10,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform from homeassistant.core import Event, HomeAssistant, callback -from .const import DATA_DEVICE, DATA_DISCOVERY, DOMAIN +from .const import DATA_DEVICE, DOMAIN from .coordinator import SwitcherDataUpdateCoordinator from .utils import async_start_bridge, async_stop_bridge @@ -60,12 +60,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Must be ready before dispatcher is called await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - discovery_task = hass.data[DOMAIN].pop(DATA_DISCOVERY, None) - if discovery_task is not None: - discovered_devices = await discovery_task - for device in discovered_devices.values(): - on_device_data_callback(device) - await async_start_bridge(hass, on_device_data_callback) async def stop_bridge(event: Event) -> None: diff --git a/homeassistant/components/switcher_kis/config_flow.py b/homeassistant/components/switcher_kis/config_flow.py index be348916e4f..31764ecf390 100644 --- a/homeassistant/components/switcher_kis/config_flow.py +++ b/homeassistant/components/switcher_kis/config_flow.py @@ -2,40 +2,9 @@ from __future__ import annotations -from typing import Any +from homeassistant.helpers import config_entry_flow -from homeassistant.config_entries import ConfigFlow, ConfigFlowResult +from .const import DOMAIN +from .utils import async_has_devices -from .const import DATA_DISCOVERY, DOMAIN -from .utils import async_discover_devices - - -class SwitcherFlowHandler(ConfigFlow, domain=DOMAIN): - """Handle Switcher config flow.""" - - async def async_step_user( - self, user_input: dict[str, Any] | None = None - ) -> ConfigFlowResult: - """Handle the start of the config flow.""" - if self._async_current_entries(True): - return self.async_abort(reason="single_instance_allowed") - - self.hass.data.setdefault(DOMAIN, {}) - if DATA_DISCOVERY not in self.hass.data[DOMAIN]: - self.hass.data[DOMAIN][DATA_DISCOVERY] = self.hass.async_create_task( - async_discover_devices() - ) - - return self.async_show_form(step_id="confirm") - - async def async_step_confirm( - self, user_input: dict[str, Any] | None = None - ) -> ConfigFlowResult: - """Handle user-confirmation of the config flow.""" - discovered_devices = await self.hass.data[DOMAIN][DATA_DISCOVERY] - - if len(discovered_devices) == 0: - self.hass.data[DOMAIN].pop(DATA_DISCOVERY) - return self.async_abort(reason="no_devices_found") - - return self.async_create_entry(title="Switcher", data={}) +config_entry_flow.register_discovery_flow(DOMAIN, "Switcher", async_has_devices) diff --git a/homeassistant/components/switcher_kis/const.py b/homeassistant/components/switcher_kis/const.py index a7a7129b136..76eb2a3e497 100644 --- a/homeassistant/components/switcher_kis/const.py +++ b/homeassistant/components/switcher_kis/const.py @@ -4,7 +4,6 @@ DOMAIN = "switcher_kis" DATA_BRIDGE = "bridge" DATA_DEVICE = "device" -DATA_DISCOVERY = "discovery" DISCOVERY_TIME_SEC = 12 diff --git a/homeassistant/components/switcher_kis/manifest.json b/homeassistant/components/switcher_kis/manifest.json index 055c92cc2fa..bf236013896 100644 --- a/homeassistant/components/switcher_kis/manifest.json +++ b/homeassistant/components/switcher_kis/manifest.json @@ -7,5 +7,6 @@ "iot_class": "local_push", "loggers": ["aioswitcher"], "quality_scale": "platinum", - "requirements": ["aioswitcher==3.4.1"] + "requirements": ["aioswitcher==3.4.1"], + "single_config_entry": true } diff --git a/homeassistant/components/switcher_kis/utils.py b/homeassistant/components/switcher_kis/utils.py index d95c1122732..79ac565a737 100644 --- a/homeassistant/components/switcher_kis/utils.py +++ b/homeassistant/components/switcher_kis/utils.py @@ -36,7 +36,7 @@ async def async_stop_bridge(hass: HomeAssistant) -> None: hass.data[DOMAIN].pop(DATA_BRIDGE) -async def async_discover_devices() -> dict[str, SwitcherBase]: +async def async_has_devices(hass: HomeAssistant) -> bool: """Discover Switcher devices.""" _LOGGER.debug("Starting discovery") discovered_devices = {} @@ -55,7 +55,7 @@ async def async_discover_devices() -> dict[str, SwitcherBase]: await bridge.stop() _LOGGER.debug("Finished discovery, discovered devices: %s", len(discovered_devices)) - return discovered_devices + return len(discovered_devices) > 0 @singleton.singleton("switcher_breeze_remote_manager") diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 1e41335e778..0955f4157d7 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -5894,7 +5894,8 @@ "name": "Switcher", "integration_type": "hub", "config_flow": true, - "iot_class": "local_push" + "iot_class": "local_push", + "single_config_entry": true }, "switchmate": { "name": "Switchmate SimplySmart Home", diff --git a/tests/components/switcher_kis/conftest.py b/tests/components/switcher_kis/conftest.py index 543f6cad008..5f04df7dc66 100644 --- a/tests/components/switcher_kis/conftest.py +++ b/tests/components/switcher_kis/conftest.py @@ -1,10 +1,20 @@ """Common fixtures and objects for the Switcher integration tests.""" +from collections.abc import Generator from unittest.mock import AsyncMock, Mock, patch import pytest +@pytest.fixture +def mock_setup_entry() -> Generator[AsyncMock, None, None]: + """Override async_setup_entry.""" + with patch( + "homeassistant.components.switcher_kis.async_setup_entry", return_value=True + ) as mock_setup_entry: + yield mock_setup_entry + + @pytest.fixture def mock_bridge(request): """Return a mocked SwitcherBridge.""" diff --git a/tests/components/switcher_kis/test_config_flow.py b/tests/components/switcher_kis/test_config_flow.py index 8d63818a6e0..e42b8ac484d 100644 --- a/tests/components/switcher_kis/test_config_flow.py +++ b/tests/components/switcher_kis/test_config_flow.py @@ -1,11 +1,11 @@ """Test the Switcher config flow.""" -from unittest.mock import patch +from unittest.mock import AsyncMock, patch import pytest from homeassistant import config_entries -from homeassistant.components.switcher_kis.const import DATA_DISCOVERY, DOMAIN +from homeassistant.components.switcher_kis.const import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType @@ -26,52 +26,51 @@ from tests.common import MockConfigEntry ], indirect=True, ) -async def test_user_setup(hass: HomeAssistant, mock_bridge) -> None: +async def test_user_setup( + hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_bridge +) -> None: """Test we can finish a config flow.""" with patch("homeassistant.components.switcher_kis.utils.DISCOVERY_TIME_SEC", 0): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) - await hass.async_block_till_done() - assert mock_bridge.is_running is False - assert len(hass.data[DOMAIN][DATA_DISCOVERY].result()) == 2 + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "confirm" - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "confirm" - assert result["errors"] is None - - with patch( - "homeassistant.components.switcher_kis.async_setup_entry", return_value=True - ): result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) - assert result2["type"] is FlowResultType.CREATE_ENTRY - assert result2["title"] == "Switcher" - assert result2["result"].data == {} + assert mock_bridge.is_running is False + assert result2["type"] is FlowResultType.CREATE_ENTRY + assert result2["title"] == "Switcher" + assert result2["result"].data == {} + + await hass.async_block_till_done() + + assert len(mock_setup_entry.mock_calls) == 1 async def test_user_setup_abort_no_devices_found( - hass: HomeAssistant, mock_bridge + hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_bridge ) -> None: """Test we abort a config flow if no devices found.""" with patch("homeassistant.components.switcher_kis.utils.DISCOVERY_TIME_SEC", 0): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "confirm" + + result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) + + assert mock_bridge.is_running is False + assert result2["type"] is FlowResultType.ABORT + assert result2["reason"] == "no_devices_found" + await hass.async_block_till_done() - assert mock_bridge.is_running is False - assert len(hass.data[DOMAIN][DATA_DISCOVERY].result()) == 0 - - assert result["type"] is FlowResultType.FORM - assert result["step_id"] == "confirm" - assert result["errors"] is None - - result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) - - assert result2["type"] is FlowResultType.ABORT - assert result2["reason"] == "no_devices_found" + assert len(mock_setup_entry.mock_calls) == 0 async def test_single_instance(hass: HomeAssistant) -> None: diff --git a/tests/components/switcher_kis/test_init.py b/tests/components/switcher_kis/test_init.py index 6105119d9a5..70eb518820c 100644 --- a/tests/components/switcher_kis/test_init.py +++ b/tests/components/switcher_kis/test_init.py @@ -1,11 +1,9 @@ """Test cases for the switcher_kis component.""" from datetime import timedelta -from unittest.mock import patch import pytest -from homeassistant import config_entries from homeassistant.components.switcher_kis.const import ( DATA_DEVICE, DOMAIN, @@ -22,23 +20,6 @@ from .consts import DUMMY_SWITCHER_DEVICES from tests.common import async_fire_time_changed -@pytest.mark.parametrize("mock_bridge", [DUMMY_SWITCHER_DEVICES], indirect=True) -async def test_async_setup_user_config_flow(hass: HomeAssistant, mock_bridge) -> None: - """Test setup started by user config flow.""" - with patch("homeassistant.components.switcher_kis.utils.DISCOVERY_TIME_SEC", 0): - result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} - ) - await hass.async_block_till_done() - - await hass.config_entries.flow.async_configure(result["flow_id"], {}) - await hass.async_block_till_done() - - assert mock_bridge.is_running is True - assert len(hass.data[DOMAIN]) == 2 - assert len(hass.data[DOMAIN][DATA_DEVICE]) == 2 - - async def test_update_fail( hass: HomeAssistant, mock_bridge, caplog: pytest.LogCaptureFixture ) -> None: