2018-06-14 19:17:54 +00:00
|
|
|
"""Tests for the Config Entry Flow helper."""
|
2023-03-16 10:10:56 +00:00
|
|
|
from collections.abc import Generator
|
2022-01-26 18:57:45 +00:00
|
|
|
from unittest.mock import Mock, PropertyMock, patch
|
2021-01-01 21:31:56 +00:00
|
|
|
|
2018-06-14 19:17:54 +00:00
|
|
|
import pytest
|
|
|
|
|
2019-04-15 02:07:05 +00:00
|
|
|
from homeassistant import config_entries, data_entry_flow, setup
|
2020-05-08 15:52:32 +00:00
|
|
|
from homeassistant.config import async_process_ha_core_config
|
2023-02-20 10:42:56 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
2018-06-14 19:17:54 +00:00
|
|
|
from homeassistant.helpers import config_entry_flow
|
2019-12-09 15:52:24 +00:00
|
|
|
|
2019-04-15 02:07:05 +00:00
|
|
|
from tests.common import (
|
2019-07-31 19:25:30 +00:00
|
|
|
MockConfigEntry,
|
|
|
|
MockModule,
|
|
|
|
mock_entity_platform,
|
2019-12-09 15:52:24 +00:00
|
|
|
mock_integration,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2023-03-16 10:10:56 +00:00
|
|
|
def discovery_flow_conf(hass: HomeAssistant) -> Generator[dict[str, bool], None, None]:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Register a handler."""
|
2019-07-31 19:25:30 +00:00
|
|
|
handler_conf = {"discovered": False}
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def has_discovered_devices(hass: HomeAssistant) -> bool:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Mock if we have discovered devices."""
|
2019-07-31 19:25:30 +00:00
|
|
|
return handler_conf["discovered"]
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
with patch.dict(config_entries.HANDLERS):
|
|
|
|
config_entry_flow.register_discovery_flow(
|
2021-04-29 21:12:58 +00:00
|
|
|
"test", "Test", has_discovered_devices
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2018-06-14 19:17:54 +00:00
|
|
|
yield handler_conf
|
|
|
|
|
|
|
|
|
2018-10-23 09:14:46 +00:00
|
|
|
@pytest.fixture
|
2023-03-16 10:10:56 +00:00
|
|
|
def webhook_flow_conf(hass: HomeAssistant) -> Generator[None, None, None]:
|
2018-10-23 09:14:46 +00:00
|
|
|
"""Register a handler."""
|
|
|
|
with patch.dict(config_entries.HANDLERS):
|
2019-07-31 19:25:30 +00:00
|
|
|
config_entry_flow.register_webhook_flow("test_single", "Test Single", {}, False)
|
2018-10-23 09:14:46 +00:00
|
|
|
config_entry_flow.register_webhook_flow(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test_multiple", "Test Multiple", {}, True
|
|
|
|
)
|
2023-03-16 10:10:56 +00:00
|
|
|
yield
|
2018-10-23 09:14:46 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_single_entry_allowed(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Test only a single entry is allowed."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-06-14 19:17:54 +00:00
|
|
|
flow.hass = hass
|
2020-04-27 06:35:04 +00:00
|
|
|
flow.context = {}
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
MockConfigEntry(domain="test").add_to_hass(hass)
|
2018-08-09 11:24:14 +00:00
|
|
|
result = await flow.async_step_user()
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["reason"] == "single_instance_allowed"
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_user_no_devices_found(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Test if no devices found."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-06-14 19:17:54 +00:00
|
|
|
flow.hass = hass
|
2019-07-31 19:25:30 +00:00
|
|
|
flow.context = {"source": config_entries.SOURCE_USER}
|
2018-09-21 14:34:37 +00:00
|
|
|
result = await flow.async_step_confirm(user_input={})
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["reason"] == "no_devices_found"
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_user_has_confirmation(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2020-06-13 04:43:13 +00:00
|
|
|
"""Test user requires confirmation to setup."""
|
2019-07-31 19:25:30 +00:00
|
|
|
discovery_flow_conf["discovered"] = True
|
2020-06-13 04:43:13 +00:00
|
|
|
mock_entity_platform(hass, "config_flow.test", None)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2020-06-13 04:43:13 +00:00
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test", context={"source": config_entries.SOURCE_USER}, data={}
|
|
|
|
)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2020-06-13 04:43:13 +00:00
|
|
|
assert result["step_id"] == "confirm"
|
|
|
|
|
2021-03-08 18:54:51 +00:00
|
|
|
progress = hass.config_entries.flow.async_progress()
|
|
|
|
assert len(progress) == 1
|
|
|
|
assert progress[0]["flow_id"] == result["flow_id"]
|
|
|
|
assert progress[0]["context"] == {
|
|
|
|
"confirm_only": True,
|
|
|
|
"source": config_entries.SOURCE_USER,
|
|
|
|
"unique_id": "test",
|
|
|
|
}
|
|
|
|
|
2020-06-13 04:43:13 +00:00
|
|
|
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2021-04-25 09:27:40 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"source",
|
|
|
|
[
|
2022-07-08 23:55:31 +00:00
|
|
|
config_entries.SOURCE_BLUETOOTH,
|
2021-04-25 09:27:40 +00:00
|
|
|
config_entries.SOURCE_DISCOVERY,
|
|
|
|
config_entries.SOURCE_MQTT,
|
|
|
|
config_entries.SOURCE_SSDP,
|
|
|
|
config_entries.SOURCE_ZEROCONF,
|
|
|
|
config_entries.SOURCE_DHCP,
|
|
|
|
],
|
|
|
|
)
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_discovery_single_instance(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool], source: str
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2019-05-30 21:08:05 +00:00
|
|
|
"""Test we not allow duplicates."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-06-14 19:17:54 +00:00
|
|
|
flow.hass = hass
|
2019-08-16 23:19:00 +00:00
|
|
|
flow.context = {}
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
MockConfigEntry(domain="test").add_to_hass(hass)
|
2020-01-03 13:47:06 +00:00
|
|
|
result = await getattr(flow, f"async_step_{source}")({})
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["reason"] == "single_instance_allowed"
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2021-04-25 09:27:40 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"source",
|
|
|
|
[
|
2022-07-08 23:55:31 +00:00
|
|
|
config_entries.SOURCE_BLUETOOTH,
|
2021-04-25 09:27:40 +00:00
|
|
|
config_entries.SOURCE_DISCOVERY,
|
|
|
|
config_entries.SOURCE_MQTT,
|
|
|
|
config_entries.SOURCE_SSDP,
|
|
|
|
config_entries.SOURCE_ZEROCONF,
|
|
|
|
config_entries.SOURCE_DHCP,
|
|
|
|
],
|
|
|
|
)
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_discovery_confirmation(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool], source: str
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Test we ask for confirmation via discovery."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-06-14 19:17:54 +00:00
|
|
|
flow.hass = hass
|
2020-04-27 06:35:04 +00:00
|
|
|
flow.context = {"source": source}
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2020-01-03 13:47:06 +00:00
|
|
|
result = await getattr(flow, f"async_step_{source}")({})
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["step_id"] == "confirm"
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
result = await flow.async_step_confirm({})
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2022-06-22 20:37:49 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"source",
|
|
|
|
[
|
2022-07-08 23:55:31 +00:00
|
|
|
config_entries.SOURCE_BLUETOOTH,
|
2022-06-22 20:37:49 +00:00
|
|
|
config_entries.SOURCE_DISCOVERY,
|
|
|
|
config_entries.SOURCE_MQTT,
|
|
|
|
config_entries.SOURCE_SSDP,
|
|
|
|
config_entries.SOURCE_ZEROCONF,
|
|
|
|
config_entries.SOURCE_DHCP,
|
|
|
|
],
|
|
|
|
)
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_discovery_during_onboarding(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool], source: str
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2022-06-22 20:37:49 +00:00
|
|
|
"""Test we create config entry via discovery during onboarding."""
|
|
|
|
flow = config_entries.HANDLERS["test"]()
|
|
|
|
flow.hass = hass
|
|
|
|
flow.context = {"source": source}
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.onboarding.async_is_onboarded", return_value=False
|
|
|
|
):
|
|
|
|
result = await getattr(flow, f"async_step_{source}")({})
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2022-06-22 20:37:49 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_multiple_discoveries(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Test we only create one instance for multiple discoveries."""
|
2019-07-31 19:25:30 +00:00
|
|
|
mock_entity_platform(hass, "config_flow.test", None)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
# Second discovery
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_only_one_in_progress(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-06-14 19:17:54 +00:00
|
|
|
"""Test a user initialized one will finish and cancel discovered one."""
|
2019-07-31 19:25:30 +00:00
|
|
|
mock_entity_platform(hass, "config_flow.test", None)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
# Discovery starts flow
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2018-06-14 19:17:54 +00:00
|
|
|
|
|
|
|
# User starts flow
|
2018-08-13 09:27:18 +00:00
|
|
|
result = await hass.config_entries.flow.async_init(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test", context={"source": config_entries.SOURCE_USER}, data={}
|
|
|
|
)
|
2018-06-14 19:17:54 +00:00
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2018-09-21 14:34:37 +00:00
|
|
|
|
|
|
|
# Discovery flow has not been aborted
|
|
|
|
assert len(hass.config_entries.flow.async_progress()) == 2
|
|
|
|
|
|
|
|
# Discovery should be aborted once user confirms
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2018-06-14 19:17:54 +00:00
|
|
|
assert len(hass.config_entries.flow.async_progress()) == 0
|
2018-07-23 13:08:03 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_import_abort_discovery(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2020-06-10 20:46:14 +00:00
|
|
|
"""Test import will finish and cancel discovered one."""
|
|
|
|
mock_entity_platform(hass, "config_flow.test", None)
|
|
|
|
|
|
|
|
# Discovery starts flow
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2020-06-10 20:46:14 +00:00
|
|
|
|
|
|
|
# Start import flow
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test", context={"source": config_entries.SOURCE_IMPORT}, data={}
|
|
|
|
)
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2020-06-10 20:46:14 +00:00
|
|
|
|
|
|
|
# Discovery flow has been aborted
|
|
|
|
assert len(hass.config_entries.flow.async_progress()) == 0
|
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_import_no_confirmation(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-08-19 20:29:08 +00:00
|
|
|
"""Test import requires no confirmation to set up."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-07-23 13:08:03 +00:00
|
|
|
flow.hass = hass
|
2020-04-27 06:35:04 +00:00
|
|
|
flow.context = {}
|
2019-07-31 19:25:30 +00:00
|
|
|
discovery_flow_conf["discovered"] = True
|
2018-07-23 13:08:03 +00:00
|
|
|
|
|
|
|
result = await flow.async_step_import(None)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2018-07-23 13:08:03 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_import_single_instance(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2018-07-23 13:08:03 +00:00
|
|
|
"""Test import doesn't create second instance."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test"]()
|
2018-07-23 13:08:03 +00:00
|
|
|
flow.hass = hass
|
2020-04-27 06:35:04 +00:00
|
|
|
flow.context = {}
|
2019-07-31 19:25:30 +00:00
|
|
|
discovery_flow_conf["discovered"] = True
|
|
|
|
MockConfigEntry(domain="test").add_to_hass(hass)
|
2018-07-23 13:08:03 +00:00
|
|
|
|
|
|
|
result = await flow.async_step_import(None)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2018-10-23 09:14:46 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_ignored_discoveries(
|
|
|
|
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
|
|
|
) -> None:
|
2020-04-27 06:35:04 +00:00
|
|
|
"""Test we can ignore discovered entries."""
|
|
|
|
mock_entity_platform(hass, "config_flow.test", None)
|
|
|
|
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2020-04-27 06:35:04 +00:00
|
|
|
|
|
|
|
flow = next(
|
|
|
|
(
|
|
|
|
flw
|
|
|
|
for flw in hass.config_entries.flow.async_progress()
|
|
|
|
if flw["flow_id"] == result["flow_id"]
|
|
|
|
),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
|
|
|
|
# Ignore it.
|
|
|
|
await hass.config_entries.flow.async_init(
|
|
|
|
flow["handler"],
|
|
|
|
context={"source": config_entries.SOURCE_IGNORE},
|
2021-01-12 08:26:20 +00:00
|
|
|
data={"unique_id": flow["context"]["unique_id"], "title": "Ignored Entry"},
|
2020-04-27 06:35:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# Second discovery should be aborted
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test", context={"source": config_entries.SOURCE_DISCOVERY}, data={}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2020-04-27 06:35:04 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_webhook_single_entry_allowed(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, webhook_flow_conf: None
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2018-10-23 09:14:46 +00:00
|
|
|
"""Test only a single entry is allowed."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test_single"]()
|
2018-10-23 09:14:46 +00:00
|
|
|
flow.hass = hass
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
MockConfigEntry(domain="test_single").add_to_hass(hass)
|
2018-10-23 09:14:46 +00:00
|
|
|
result = await flow.async_step_user()
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2020-10-01 18:44:13 +00:00
|
|
|
assert result["reason"] == "single_instance_allowed"
|
2018-10-23 09:14:46 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_webhook_multiple_entries_allowed(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, webhook_flow_conf: None
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2018-10-23 09:14:46 +00:00
|
|
|
"""Test multiple entries are allowed when specified."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test_multiple"]()
|
2018-10-23 09:14:46 +00:00
|
|
|
flow.hass = hass
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
MockConfigEntry(domain="test_multiple").add_to_hass(hass)
|
|
|
|
hass.config.api = Mock(base_url="http://example.com")
|
2018-10-23 09:14:46 +00:00
|
|
|
|
|
|
|
result = await flow.async_step_user()
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2018-10-23 09:14:46 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_webhook_config_flow_registers_webhook(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, webhook_flow_conf: None
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2018-10-23 09:14:46 +00:00
|
|
|
"""Test setting up an entry creates a webhook."""
|
2019-07-31 19:25:30 +00:00
|
|
|
flow = config_entries.HANDLERS["test_single"]()
|
2018-10-23 09:14:46 +00:00
|
|
|
flow.hass = hass
|
|
|
|
|
2020-05-08 15:52:32 +00:00
|
|
|
await async_process_ha_core_config(
|
2020-08-27 11:56:20 +00:00
|
|
|
hass,
|
|
|
|
{"external_url": "https://example.com"},
|
2020-05-08 15:52:32 +00:00
|
|
|
)
|
2018-10-23 09:14:46 +00:00
|
|
|
result = await flow.async_step_user(user_input={})
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["data"]["webhook_id"] is not None
|
2019-04-01 12:07:12 +00:00
|
|
|
|
|
|
|
|
2023-03-16 10:10:56 +00:00
|
|
|
async def test_webhook_create_cloudhook(
|
|
|
|
hass: HomeAssistant, webhook_flow_conf: None
|
|
|
|
) -> None:
|
2022-01-26 18:57:45 +00:00
|
|
|
"""Test cloudhook will be created if subscribed."""
|
2019-07-31 19:25:30 +00:00
|
|
|
assert await setup.async_setup_component(hass, "cloud", {})
|
2019-04-01 12:07:12 +00:00
|
|
|
|
2020-04-25 22:52:50 +00:00
|
|
|
async_setup_entry = Mock(return_value=True)
|
|
|
|
async_unload_entry = Mock(return_value=True)
|
2019-04-01 12:07:12 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
mock_integration(
|
|
|
|
hass,
|
|
|
|
MockModule(
|
|
|
|
"test_single",
|
|
|
|
async_setup_entry=async_setup_entry,
|
|
|
|
async_unload_entry=async_unload_entry,
|
|
|
|
async_remove_entry=config_entry_flow.webhook_async_remove_entry,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
mock_entity_platform(hass, "config_flow.test_single", None)
|
2019-04-01 12:07:12 +00:00
|
|
|
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
2019-07-31 19:25:30 +00:00
|
|
|
"test_single", context={"source": config_entries.SOURCE_USER}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2019-07-31 19:25:30 +00:00
|
|
|
|
|
|
|
with patch(
|
2020-04-25 22:52:50 +00:00
|
|
|
"hass_nabucasa.cloudhooks.Cloudhooks.async_create",
|
|
|
|
return_value={"cloudhook_url": "https://example.com"},
|
2019-07-31 19:25:30 +00:00
|
|
|
) as mock_create, patch(
|
2022-01-26 18:57:45 +00:00
|
|
|
"hass_nabucasa.Cloud.subscription_expired",
|
|
|
|
new_callable=PropertyMock(return_value=False),
|
|
|
|
), patch(
|
|
|
|
"hass_nabucasa.Cloud.is_logged_in",
|
|
|
|
new_callable=PropertyMock(return_value=True),
|
2019-07-31 19:25:30 +00:00
|
|
|
), patch(
|
2022-01-26 18:57:45 +00:00
|
|
|
"hass_nabucasa.iot_base.BaseIoT.connected",
|
|
|
|
new_callable=PropertyMock(return_value=True),
|
2019-07-31 19:25:30 +00:00
|
|
|
):
|
|
|
|
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["description_placeholders"]["webhook_url"] == "https://example.com"
|
2019-04-01 12:07:12 +00:00
|
|
|
assert len(mock_create.mock_calls) == 1
|
|
|
|
assert len(async_setup_entry.mock_calls) == 1
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch(
|
2020-04-25 22:52:50 +00:00
|
|
|
"hass_nabucasa.cloudhooks.Cloudhooks.async_delete",
|
|
|
|
return_value={"cloudhook_url": "https://example.com"},
|
2019-07-31 19:25:30 +00:00
|
|
|
) as mock_delete:
|
|
|
|
result = await hass.config_entries.async_remove(result["result"].entry_id)
|
2019-04-01 12:07:12 +00:00
|
|
|
|
|
|
|
assert len(mock_delete.mock_calls) == 1
|
2019-07-31 19:25:30 +00:00
|
|
|
assert result["require_restart"] is False
|
2021-04-29 21:12:58 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_webhook_create_cloudhook_aborts_not_connected(
|
2023-03-16 10:10:56 +00:00
|
|
|
hass: HomeAssistant, webhook_flow_conf: None
|
2023-02-20 10:42:56 +00:00
|
|
|
) -> None:
|
2022-01-26 18:57:45 +00:00
|
|
|
"""Test cloudhook aborts if subscribed but not connected."""
|
|
|
|
assert await setup.async_setup_component(hass, "cloud", {})
|
|
|
|
|
|
|
|
async_setup_entry = Mock(return_value=True)
|
|
|
|
async_unload_entry = Mock(return_value=True)
|
|
|
|
|
|
|
|
mock_integration(
|
|
|
|
hass,
|
|
|
|
MockModule(
|
|
|
|
"test_single",
|
|
|
|
async_setup_entry=async_setup_entry,
|
|
|
|
async_unload_entry=async_unload_entry,
|
|
|
|
async_remove_entry=config_entry_flow.webhook_async_remove_entry,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
mock_entity_platform(hass, "config_flow.test_single", None)
|
|
|
|
|
|
|
|
result = await hass.config_entries.flow.async_init(
|
|
|
|
"test_single", context={"source": config_entries.SOURCE_USER}
|
|
|
|
)
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
2022-01-26 18:57:45 +00:00
|
|
|
|
|
|
|
with patch(
|
|
|
|
"hass_nabucasa.cloudhooks.Cloudhooks.async_create",
|
|
|
|
return_value={"cloudhook_url": "https://example.com"},
|
|
|
|
), patch(
|
|
|
|
"hass_nabucasa.Cloud.subscription_expired",
|
|
|
|
new_callable=PropertyMock(return_value=False),
|
|
|
|
), patch(
|
|
|
|
"hass_nabucasa.Cloud.is_logged_in",
|
|
|
|
new_callable=PropertyMock(return_value=True),
|
|
|
|
), patch(
|
|
|
|
"hass_nabucasa.iot_base.BaseIoT.connected",
|
|
|
|
new_callable=PropertyMock(return_value=False),
|
|
|
|
):
|
|
|
|
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
|
|
|
|
2022-07-07 16:57:36 +00:00
|
|
|
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
2022-01-26 18:57:45 +00:00
|
|
|
assert result["reason"] == "cloud_not_connected"
|