diff --git a/homeassistant/components/hue/config_flow.py b/homeassistant/components/hue/config_flow.py index 66b9c97a58a..a46f8816fbb 100644 --- a/homeassistant/components/hue/config_flow.py +++ b/homeassistant/components/hue/config_flow.py @@ -10,6 +10,7 @@ import voluptuous as vol from homeassistant import config_entries, core from homeassistant.components import ssdp +from homeassistant.const import CONF_HOST from homeassistant.helpers import aiohttp_client from .bridge import authenticate_bridge @@ -169,7 +170,8 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): bridge = self._async_get_bridge(host, discovery_info[ssdp.ATTR_UPNP_SERIAL]) await self.async_set_unique_id(bridge.id) - self._abort_if_unique_id_configured() + self._abort_if_unique_id_configured(updates={CONF_HOST: bridge.host}) + self.bridge = bridge return await self.async_step_link() @@ -180,7 +182,8 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) await self.async_set_unique_id(bridge.id) - self._abort_if_unique_id_configured() + self._abort_if_unique_id_configured(updates={CONF_HOST: bridge.host}) + self.bridge = bridge return await self.async_step_link() diff --git a/tests/components/hue/test_config_flow.py b/tests/components/hue/test_config_flow.py index a5bf143775a..b1f6785b0a7 100644 --- a/tests/components/hue/test_config_flow.py +++ b/tests/components/hue/test_config_flow.py @@ -214,6 +214,26 @@ async def test_flow_link_timeout(hass): assert result["errors"] == {"base": "linking"} +async def test_flow_link_unknown_error(hass): + """Test if a unknown error happend during the linking processes.""" + mock_bridge = get_mock_bridge(mock_create_user=CoroutineMock(side_effect=OSError),) + with patch( + "homeassistant.components.hue.config_flow.discover_nupnp", + return_value=[mock_bridge], + ): + result = await hass.config_entries.flow.async_init( + const.DOMAIN, context={"source": "user"} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={} + ) + + assert result["type"] == "form" + assert result["step_id"] == "link" + assert result["errors"] == {"base": "linking"} + + async def test_flow_link_button_not_pressed(hass): """Test config flow .""" mock_bridge = get_mock_bridge( @@ -303,6 +323,36 @@ async def test_bridge_ssdp_emulated_hue(hass): assert result["reason"] == "not_hue_bridge" +async def test_bridge_ssdp_missing_location(hass): + """Test if discovery info is missing a location attribute.""" + result = await hass.config_entries.flow.async_init( + const.DOMAIN, + context={"source": "ssdp"}, + data={ + ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.HUE_MANUFACTURERURL, + ssdp.ATTR_UPNP_SERIAL: "1234", + }, + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_hue_bridge" + + +async def test_bridge_ssdp_missing_serial(hass): + """Test if discovery info is a serial attribute.""" + result = await hass.config_entries.flow.async_init( + const.DOMAIN, + context={"source": "ssdp"}, + data={ + ssdp.ATTR_SSDP_LOCATION: "http://0.0.0.0/", + ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.HUE_MANUFACTURERURL, + }, + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_hue_bridge" + + async def test_bridge_ssdp_espalexa(hass): """Test if discovery info is from an Espalexa based device.""" result = await hass.config_entries.flow.async_init( @@ -417,6 +467,22 @@ async def test_bridge_homekit(hass): assert result["step_id"] == "link" +async def test_bridge_import_already_configured(hass): + """Test if a import flow aborts if host is already configured.""" + MockConfigEntry( + domain="hue", unique_id="aabbccddeeff", data={"host": "0.0.0.0"} + ).add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + const.DOMAIN, + context={"source": "import"}, + data={"host": "0.0.0.0", "properties": {"id": "aa:bb:cc:dd:ee:ff"}}, + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + + async def test_bridge_homekit_already_configured(hass): """Test if a HomeKit discovered bridge has already been configured.""" MockConfigEntry( @@ -431,3 +497,43 @@ async def test_bridge_homekit_already_configured(hass): assert result["type"] == "abort" assert result["reason"] == "already_configured" + + +async def test_ssdp_discovery_update_configuration(hass): + """Test if a discovered bridge is configured and updated with new host.""" + entry = MockConfigEntry( + domain="hue", unique_id="aabbccddeeff", data={"host": "0.0.0.0"} + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + const.DOMAIN, + context={"source": "ssdp"}, + data={ + ssdp.ATTR_SSDP_LOCATION: "http://1.1.1.1/", + ssdp.ATTR_UPNP_MANUFACTURER_URL: config_flow.HUE_MANUFACTURERURL, + ssdp.ATTR_UPNP_SERIAL: "aabbccddeeff", + }, + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + assert entry.data["host"] == "1.1.1.1" + + +async def test_homekit_discovery_update_configuration(hass): + """Test if a discovered bridge is configured and updated with new host.""" + entry = MockConfigEntry( + domain="hue", unique_id="aabbccddeeff", data={"host": "0.0.0.0"} + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + const.DOMAIN, + context={"source": "homekit"}, + data={"host": "1.1.1.1", "properties": {"id": "aa:bb:cc:dd:ee:ff"}}, + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + assert entry.data["host"] == "1.1.1.1"