"""Test the SenseME config flow.""" from unittest.mock import patch from homeassistant import config_entries from homeassistant.components import dhcp from homeassistant.components.senseme.const import DOMAIN from homeassistant.const import CONF_HOST, CONF_ID from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType from . import ( MOCK_ADDRESS, MOCK_DEVICE, MOCK_DEVICE2, MOCK_DEVICE_ALTERNATE_IP, MOCK_DEVICE_NO_UUID, MOCK_MAC, MOCK_UUID, _patch_discovery, ) from tests.common import MockConfigEntry DHCP_DISCOVERY = dhcp.DhcpServiceInfo( hostname="any", ip=MOCK_ADDRESS, macaddress=MOCK_MAC, ) async def test_form_user(hass: HomeAssistant) -> None: """Test we get the form as a user.""" with _patch_discovery(), patch( "homeassistant.components.senseme.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { "device": MOCK_UUID, }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.CREATE_ENTRY assert result2["title"] == "Haiku Fan" assert result2["data"] == { "info": MOCK_DEVICE.get_device_info, } assert len(mock_setup_entry.mock_calls) == 1 async def test_form_user_manual_entry(hass: HomeAssistant) -> None: """Test we get the form as a user with a discovery but user chooses manual.""" with _patch_discovery(): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { "device": None, }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.FORM assert result2["step_id"] == "manual" with patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=MOCK_DEVICE, ), patch( "homeassistant.components.senseme.async_setup_entry", return_value=True, ) as mock_setup_entry: result3 = await hass.config_entries.flow.async_configure( result["flow_id"], { CONF_HOST: MOCK_ADDRESS, }, ) await hass.async_block_till_done() assert result3["type"] == FlowResultType.CREATE_ENTRY assert result3["title"] == "Haiku Fan" assert result3["data"] == { "info": MOCK_DEVICE.get_device_info, } assert len(mock_setup_entry.mock_calls) == 1 async def test_form_user_no_discovery(hass: HomeAssistant) -> None: """Test we get the form as a user with no discovery.""" with _patch_discovery(no_device=True), patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=MOCK_DEVICE, ), patch( "homeassistant.components.senseme.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { CONF_HOST: "not a valid address", }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.FORM assert result2["step_id"] == "manual" assert result2["errors"] == {CONF_HOST: "invalid_host"} result3 = await hass.config_entries.flow.async_configure( result2["flow_id"], { CONF_HOST: MOCK_ADDRESS, }, ) await hass.async_block_till_done() assert result3["type"] == FlowResultType.CREATE_ENTRY assert result3["title"] == "Haiku Fan" assert result3["data"] == { "info": MOCK_DEVICE.get_device_info, } assert len(mock_setup_entry.mock_calls) == 1 async def test_form_user_manual_entry_cannot_connect(hass: HomeAssistant) -> None: """Test we get the form as a user.""" with _patch_discovery(): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { "device": None, }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.FORM assert result2["step_id"] == "manual" with patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=None, ): result3 = await hass.config_entries.flow.async_configure( result["flow_id"], { CONF_HOST: MOCK_ADDRESS, }, ) await hass.async_block_till_done() assert result3["type"] == FlowResultType.FORM assert result3["step_id"] == "manual" assert result3["errors"] == {CONF_HOST: "cannot_connect"} async def test_discovery(hass: HomeAssistant) -> None: """Test we can setup a discovered device.""" entry = MockConfigEntry( domain=DOMAIN, data={ "info": MOCK_DEVICE2.get_device_info, }, unique_id=MOCK_DEVICE2.uuid, ) entry.add_to_hass(hass) with _patch_discovery(), patch( "homeassistant.components.senseme.async_get_device_by_device_info", return_value=(True, MOCK_DEVICE2), ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() with _patch_discovery(), patch( "homeassistant.components.senseme.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY}, data={CONF_ID: MOCK_UUID}, ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { "device": MOCK_UUID, }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.CREATE_ENTRY assert result2["title"] == "Haiku Fan" assert result2["data"] == { "info": MOCK_DEVICE.get_device_info, } assert len(mock_setup_entry.mock_calls) == 1 async def test_discovery_existing_device_no_ip_change(hass: HomeAssistant) -> None: """Test we can setup a discovered device.""" entry = MockConfigEntry( domain=DOMAIN, data={ "info": MOCK_DEVICE.get_device_info, }, unique_id=MOCK_DEVICE.uuid, ) entry.add_to_hass(hass) with _patch_discovery(), patch( "homeassistant.components.senseme.async_get_device_by_device_info", return_value=(True, MOCK_DEVICE), ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() with _patch_discovery(): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY}, data={CONF_ID: MOCK_UUID}, ) assert result["type"] == FlowResultType.ABORT assert result["reason"] == "already_configured" async def test_discovery_existing_device_ip_change(hass: HomeAssistant) -> None: """Test a config entry ips get updated from discovery.""" entry = MockConfigEntry( domain=DOMAIN, data={ "info": MOCK_DEVICE.get_device_info, }, unique_id=MOCK_DEVICE.uuid, ) entry.add_to_hass(hass) with _patch_discovery(device=MOCK_DEVICE_ALTERNATE_IP), patch( "homeassistant.components.senseme.async_get_device_by_device_info", return_value=(True, MOCK_DEVICE), ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY}, data={CONF_ID: MOCK_UUID}, ) await hass.async_block_till_done() assert result["type"] == FlowResultType.ABORT assert result["reason"] == "already_configured" assert entry.data["info"]["address"] == "127.0.0.8" async def test_dhcp_discovery_existing_config_entry(hass: HomeAssistant) -> None: """Test dhcp discovery is aborted if there is an existing config entry.""" entry = MockConfigEntry( domain=DOMAIN, data={ "info": MOCK_DEVICE2.get_device_info, }, unique_id=MOCK_DEVICE2.uuid, ) entry.add_to_hass(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=DHCP_DISCOVERY ) assert result["type"] == FlowResultType.ABORT assert result["reason"] == "already_configured" async def test_dhcp_discovery(hass: HomeAssistant) -> None: """Test we can setup a dhcp discovered device.""" with _patch_discovery(), patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=MOCK_DEVICE, ), patch( "homeassistant.components.senseme.async_setup_entry", return_value=True, ) as mock_setup_entry: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=DHCP_DISCOVERY ) assert result["type"] == FlowResultType.FORM assert not result["errors"] result2 = await hass.config_entries.flow.async_configure( result["flow_id"], { "device": MOCK_UUID, }, ) await hass.async_block_till_done() assert result2["type"] == FlowResultType.CREATE_ENTRY assert result2["title"] == "Haiku Fan" assert result2["data"] == { "info": MOCK_DEVICE.get_device_info, } assert len(mock_setup_entry.mock_calls) == 1 async def test_dhcp_discovery_cannot_connect(hass: HomeAssistant) -> None: """Test we abort if we cannot cannot to a dhcp discovered device.""" with _patch_discovery(), patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=None, ): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=DHCP_DISCOVERY ) assert result["type"] == FlowResultType.ABORT assert result["reason"] == "cannot_connect" async def test_dhcp_discovery_cannot_connect_no_uuid(hass: HomeAssistant) -> None: """Test we abort if the discovered device has no uuid.""" with _patch_discovery(), patch( "homeassistant.components.senseme.config_flow.async_get_device_by_ip_address", return_value=MOCK_DEVICE_NO_UUID, ): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=DHCP_DISCOVERY ) assert result["type"] == FlowResultType.ABORT assert result["reason"] == "cannot_connect"