mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Fix setup timings when config entry platform loads are not awaited (#113959)
* Move setup time logging into the context manager We were fetching the time twice but since the context manager already has the timing, move it there * remove log setup assertions from integration test * tweak logging to give us better data for tracking issues * redundant * adjust * preen * fixes * adjust * make api change internal so nobody uses it * coverage * fix test * fix more tests * coverage * more tests assuming internal calls * fix more * adjust * adjust * fix axis tests * fix broadlink -- it does not call async_forward_entry_setup * missed some * remove useless patch * rename, detect it both ways * clear * debug * try to fix * handle phase finishing out while paused * where its set does not need to know its late as that is an implemenation detail of setup * where its set does not need to know its late as that is an implemenation detail of setup * tweak * simplify * reduce complexity * revert order change as it makes review harder * revert naming changes as it makes review harder * improve comment * improve debug * late dispatch test * test the other way as well * Update setup.py * Update setup.py * Update setup.py * simplify * reduce
This commit is contained in:
parent
a4f52cc622
commit
4f18f0d902
@ -1858,7 +1858,7 @@ class ConfigEntries:
|
||||
await asyncio.gather(
|
||||
*(
|
||||
create_eager_task(
|
||||
self.async_forward_entry_setup(entry, platform),
|
||||
self._async_forward_entry_setup(entry, platform, False),
|
||||
name=f"config entry forward setup {entry.title} {entry.domain} {entry.entry_id} {platform}",
|
||||
)
|
||||
for platform in platforms
|
||||
@ -1874,6 +1874,12 @@ class ConfigEntries:
|
||||
component also has related platforms, the component will have to
|
||||
forward the entry to be setup by that component.
|
||||
"""
|
||||
return await self._async_forward_entry_setup(entry, domain, True)
|
||||
|
||||
async def _async_forward_entry_setup(
|
||||
self, entry: ConfigEntry, domain: Platform | str, preload_platform: bool
|
||||
) -> bool:
|
||||
"""Forward the setup of an entry to a different component."""
|
||||
# Setup Component if not set up yet
|
||||
if domain not in self.hass.config.components:
|
||||
with async_pause_setup(self.hass, SetupPhases.WAIT_BASE_PLATFORM_SETUP):
|
||||
@ -1884,8 +1890,16 @@ class ConfigEntries:
|
||||
if not result:
|
||||
return False
|
||||
|
||||
integration = await loader.async_get_integration(self.hass, domain)
|
||||
if preload_platform:
|
||||
# If this is a late setup, we need to make sure the platform is loaded
|
||||
# so we do not end up waiting for when the EntityComponent calls
|
||||
# async_prepare_setup_platform
|
||||
integration = await loader.async_get_integration(self.hass, entry.domain)
|
||||
if not integration.platforms_are_loaded((domain,)):
|
||||
with async_pause_setup(self.hass, SetupPhases.WAIT_IMPORT_PLATFORMS):
|
||||
await integration.async_get_platform(domain)
|
||||
|
||||
integration = await loader.async_get_integration(self.hass, domain)
|
||||
await entry.async_setup(self.hass, integration=integration)
|
||||
return True
|
||||
|
||||
|
@ -10,7 +10,6 @@ import contextvars
|
||||
from enum import StrEnum
|
||||
import logging.handlers
|
||||
import time
|
||||
from timeit import default_timer as timer
|
||||
from types import ModuleType
|
||||
from typing import Any, Final, TypedDict
|
||||
|
||||
@ -351,7 +350,6 @@ async def _async_setup_component( # noqa: C901
|
||||
},
|
||||
)
|
||||
|
||||
start = timer()
|
||||
_LOGGER.info("Setting up %s", domain)
|
||||
integration_set = {domain}
|
||||
|
||||
@ -412,11 +410,8 @@ async def _async_setup_component( # noqa: C901
|
||||
async_notify_setup_error(hass, domain, integration.documentation)
|
||||
return False
|
||||
finally:
|
||||
end = timer()
|
||||
if warn_task:
|
||||
warn_task.cancel()
|
||||
_LOGGER.info("Setup of domain %s took %.1f seconds", domain, end - start)
|
||||
|
||||
if result is False:
|
||||
log_error("Integration failed to initialize.")
|
||||
return False
|
||||
@ -663,6 +658,15 @@ class SetupPhases(StrEnum):
|
||||
"""Wait time for the packages to import."""
|
||||
|
||||
|
||||
def _setup_started(
|
||||
hass: core.HomeAssistant,
|
||||
) -> dict[tuple[str, str | None], float]:
|
||||
"""Return the setup started dict."""
|
||||
if DATA_SETUP_STARTED not in hass.data:
|
||||
hass.data[DATA_SETUP_STARTED] = {}
|
||||
return hass.data[DATA_SETUP_STARTED] # type: ignore[no-any-return]
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def async_pause_setup(
|
||||
hass: core.HomeAssistant, phase: SetupPhases
|
||||
@ -673,7 +677,9 @@ def async_pause_setup(
|
||||
setting up the base components so we can subtract it
|
||||
from the total setup time.
|
||||
"""
|
||||
if not (running := current_setup_group.get()):
|
||||
if not (running := current_setup_group.get()) or running not in _setup_started(
|
||||
hass
|
||||
):
|
||||
# This means we are likely in a late platform setup
|
||||
# that is running in a task so we do not want
|
||||
# to subtract out the time later as nothing is waiting
|
||||
@ -689,6 +695,13 @@ def async_pause_setup(
|
||||
integration, group = running
|
||||
# Add negative time for the time we waited
|
||||
_setup_times(hass)[integration][group][phase] = -time_taken
|
||||
_LOGGER.debug(
|
||||
"Adding wait for %s for %s (%s) of %.2f",
|
||||
phase,
|
||||
integration,
|
||||
group,
|
||||
time_taken,
|
||||
)
|
||||
|
||||
|
||||
def _setup_times(
|
||||
@ -726,8 +739,7 @@ def async_start_setup(
|
||||
yield
|
||||
return
|
||||
|
||||
setup_started: dict[tuple[str, str | None], float]
|
||||
setup_started = hass.data.setdefault(DATA_SETUP_STARTED, {})
|
||||
setup_started = _setup_started(hass)
|
||||
current = (integration, group)
|
||||
if current in setup_started:
|
||||
# We are already inside another async_start_setup, this like means we
|
||||
@ -745,7 +757,26 @@ def async_start_setup(
|
||||
finally:
|
||||
time_taken = time.monotonic() - started
|
||||
del setup_started[current]
|
||||
_setup_times(hass)[integration][group][phase] = time_taken
|
||||
group_setup_times = _setup_times(hass)[integration][group]
|
||||
# We may see the phase multiple times if there are multiple
|
||||
# platforms, but we only care about the longest time.
|
||||
group_setup_times[phase] = max(group_setup_times[phase], time_taken)
|
||||
if group is None:
|
||||
_LOGGER.info(
|
||||
"Setup of domain %s took %.2f seconds", integration, time_taken
|
||||
)
|
||||
elif _LOGGER.isEnabledFor(logging.DEBUG):
|
||||
wait_time = -sum(value for value in group_setup_times.values() if value < 0)
|
||||
calculated_time = time_taken - wait_time
|
||||
_LOGGER.debug(
|
||||
"Phase %s for %s (%s) took %.2fs (elapsed=%.2fs) (wait_time=%.2fs)",
|
||||
phase,
|
||||
integration,
|
||||
group,
|
||||
calculated_time,
|
||||
time_taken,
|
||||
wait_time,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -35,16 +35,18 @@ from tests.common import async_fire_mqtt_message
|
||||
from tests.typing import MqttMockHAClient
|
||||
|
||||
|
||||
@pytest.fixture(name="forward_entry_setup")
|
||||
@pytest.fixture(name="forward_entry_setups")
|
||||
def hass_mock_forward_entry_setup(hass):
|
||||
"""Mock async_forward_entry_setup."""
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
"""Mock async_forward_entry_setups."""
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
yield forward_mock
|
||||
|
||||
|
||||
async def test_device_setup(
|
||||
hass: HomeAssistant,
|
||||
forward_entry_setup,
|
||||
forward_entry_setups,
|
||||
config_entry_data,
|
||||
setup_config_entry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
@ -57,11 +59,9 @@ async def test_device_setup(
|
||||
assert hub.api.vapix.product_type == "Network Camera"
|
||||
assert hub.api.vapix.serial_number == "00408C123456"
|
||||
|
||||
assert len(forward_entry_setup.mock_calls) == 4
|
||||
assert forward_entry_setup.mock_calls[0][1][1] == "binary_sensor"
|
||||
assert forward_entry_setup.mock_calls[1][1][1] == "camera"
|
||||
assert forward_entry_setup.mock_calls[2][1][1] == "light"
|
||||
assert forward_entry_setup.mock_calls[3][1][1] == "switch"
|
||||
assert len(forward_entry_setups.mock_calls) == 1
|
||||
platforms = set(forward_entry_setups.mock_calls[0][1][1])
|
||||
assert platforms == {"binary_sensor", "camera", "light", "switch"}
|
||||
|
||||
assert hub.config.host == config_entry_data[CONF_HOST]
|
||||
assert hub.config.model == config_entry_data[CONF_MODEL]
|
||||
|
@ -21,7 +21,7 @@ async def test_device_setup(hass: HomeAssistant) -> None:
|
||||
device = get_device("Office")
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -32,9 +32,9 @@ async def test_device_setup(hass: HomeAssistant) -> None:
|
||||
assert mock_setup.api.get_fwversion.call_count == 1
|
||||
assert mock_setup.factory.call_count == 1
|
||||
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
domains = get_domains(mock_setup.api.type)
|
||||
assert mock_forward.call_count == len(domains)
|
||||
assert mock_forward.call_count == 1
|
||||
assert forward_entries == domains
|
||||
assert mock_init.call_count == 0
|
||||
|
||||
@ -46,7 +46,7 @@ async def test_device_setup_authentication_error(hass: HomeAssistant) -> None:
|
||||
mock_api.auth.side_effect = blke.AuthenticationError()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -70,7 +70,7 @@ async def test_device_setup_network_timeout(hass: HomeAssistant) -> None:
|
||||
mock_api.auth.side_effect = blke.NetworkTimeoutError()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -89,7 +89,7 @@ async def test_device_setup_os_error(hass: HomeAssistant) -> None:
|
||||
mock_api.auth.side_effect = OSError()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -108,7 +108,7 @@ async def test_device_setup_broadlink_exception(hass: HomeAssistant) -> None:
|
||||
mock_api.auth.side_effect = blke.BroadlinkException()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -127,7 +127,7 @@ async def test_device_setup_update_network_timeout(hass: HomeAssistant) -> None:
|
||||
mock_api.check_sensors.side_effect = blke.NetworkTimeoutError()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -150,7 +150,7 @@ async def test_device_setup_update_authorization_error(hass: HomeAssistant) -> N
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -160,9 +160,9 @@ async def test_device_setup_update_authorization_error(hass: HomeAssistant) -> N
|
||||
assert mock_setup.api.auth.call_count == 2
|
||||
assert mock_setup.api.check_sensors.call_count == 2
|
||||
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
domains = get_domains(mock_api.type)
|
||||
assert mock_forward.call_count == len(domains)
|
||||
assert mock_forward.call_count == 1
|
||||
assert forward_entries == domains
|
||||
assert mock_init.call_count == 0
|
||||
|
||||
@ -175,7 +175,7 @@ async def test_device_setup_update_authentication_error(hass: HomeAssistant) ->
|
||||
mock_api.auth.side_effect = (None, blke.AuthenticationError())
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -200,7 +200,7 @@ async def test_device_setup_update_broadlink_exception(hass: HomeAssistant) -> N
|
||||
mock_api.check_sensors.side_effect = blke.BroadlinkException()
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward, patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
) as mock_init:
|
||||
@ -221,13 +221,15 @@ async def test_device_setup_get_fwversion_broadlink_exception(
|
||||
mock_api = device.get_mock_api()
|
||||
mock_api.get_fwversion.side_effect = blke.BroadlinkException()
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as mock_forward:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
mock_setup = await device.setup_entry(hass, mock_api=mock_api)
|
||||
|
||||
assert mock_setup.entry.state is ConfigEntryState.LOADED
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
domains = get_domains(mock_setup.api.type)
|
||||
assert mock_forward.call_count == len(domains)
|
||||
assert mock_forward.call_count == 1
|
||||
assert forward_entries == domains
|
||||
|
||||
|
||||
@ -237,13 +239,15 @@ async def test_device_setup_get_fwversion_os_error(hass: HomeAssistant) -> None:
|
||||
mock_api = device.get_mock_api()
|
||||
mock_api.get_fwversion.side_effect = OSError()
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as mock_forward:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
mock_setup = await device.setup_entry(hass, mock_api=mock_api)
|
||||
|
||||
assert mock_setup.entry.state is ConfigEntryState.LOADED
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
domains = get_domains(mock_setup.api.type)
|
||||
assert mock_forward.call_count == len(domains)
|
||||
assert mock_forward.call_count == 1
|
||||
assert forward_entries == domains
|
||||
|
||||
|
||||
@ -281,7 +285,7 @@ async def test_device_unload_works(hass: HomeAssistant) -> None:
|
||||
"""Test we unload the device."""
|
||||
device = get_device("Office")
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup"):
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setups"):
|
||||
mock_setup = await device.setup_entry(hass)
|
||||
|
||||
with patch.object(
|
||||
@ -302,7 +306,7 @@ async def test_device_unload_authentication_error(hass: HomeAssistant) -> None:
|
||||
mock_api = device.get_mock_api()
|
||||
mock_api.auth.side_effect = blke.AuthenticationError()
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup"), patch.object(
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setups"), patch.object(
|
||||
hass.config_entries.flow, "async_init"
|
||||
):
|
||||
mock_setup = await device.setup_entry(hass, mock_api=mock_api)
|
||||
@ -322,7 +326,7 @@ async def test_device_unload_update_failed(hass: HomeAssistant) -> None:
|
||||
mock_api = device.get_mock_api()
|
||||
mock_api.check_sensors.side_effect = blke.NetworkTimeoutError()
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup"):
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setups"):
|
||||
mock_setup = await device.setup_entry(hass, mock_api=mock_api)
|
||||
|
||||
with patch.object(
|
||||
|
@ -142,7 +142,7 @@ async def test_gateway_setup(
|
||||
) -> None:
|
||||
"""Successful setup."""
|
||||
with patch(
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setup",
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setups",
|
||||
return_value=True,
|
||||
) as forward_entry_setup:
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
@ -158,24 +158,23 @@ async def test_gateway_setup(
|
||||
|
||||
assert forward_entry_setup.mock_calls[0][1] == (
|
||||
config_entry,
|
||||
ALARM_CONTROL_PANEL_DOMAIN,
|
||||
[
|
||||
ALARM_CONTROL_PANEL_DOMAIN,
|
||||
BINARY_SENSOR_DOMAIN,
|
||||
BUTTON_DOMAIN,
|
||||
CLIMATE_DOMAIN,
|
||||
COVER_DOMAIN,
|
||||
FAN_DOMAIN,
|
||||
LIGHT_DOMAIN,
|
||||
LOCK_DOMAIN,
|
||||
NUMBER_DOMAIN,
|
||||
SCENE_DOMAIN,
|
||||
SELECT_DOMAIN,
|
||||
SENSOR_DOMAIN,
|
||||
SIREN_DOMAIN,
|
||||
SWITCH_DOMAIN,
|
||||
],
|
||||
)
|
||||
assert forward_entry_setup.mock_calls[1][1] == (
|
||||
config_entry,
|
||||
BINARY_SENSOR_DOMAIN,
|
||||
)
|
||||
assert forward_entry_setup.mock_calls[2][1] == (config_entry, BUTTON_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[3][1] == (config_entry, CLIMATE_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[4][1] == (config_entry, COVER_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[5][1] == (config_entry, FAN_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[6][1] == (config_entry, LIGHT_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[7][1] == (config_entry, LOCK_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[8][1] == (config_entry, NUMBER_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[9][1] == (config_entry, SCENE_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[10][1] == (config_entry, SELECT_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[11][1] == (config_entry, SENSOR_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[12][1] == (config_entry, SIREN_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[13][1] == (config_entry, SWITCH_DOMAIN)
|
||||
|
||||
gateway_entry = device_registry.async_get_device(
|
||||
identifiers={(DECONZ_DOMAIN, gateway.bridgeid)}
|
||||
|
@ -80,7 +80,9 @@ async def test_async_setup_entry_loads_platforms(
|
||||
) -> None:
|
||||
"""Test load connects to heos, retrieves players, and loads platforms."""
|
||||
config_entry.add_to_hass(hass)
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
assert await async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
@ -107,7 +109,9 @@ async def test_async_setup_entry_not_signed_in_loads_platforms(
|
||||
config_entry.add_to_hass(hass)
|
||||
controller.is_signed_in = False
|
||||
controller.signed_in_username = None
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
assert await async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
|
@ -30,7 +30,7 @@ async def test_bridge_setup_v1(hass: HomeAssistant, mock_api_v1) -> None:
|
||||
)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -38,8 +38,8 @@ async def test_bridge_setup_v1(hass: HomeAssistant, mock_api_v1) -> None:
|
||||
assert hue_bridge.api is mock_api_v1
|
||||
assert isinstance(hue_bridge.api, HueBridgeV1)
|
||||
assert hue_bridge.api_version == 1
|
||||
assert len(mock_forward.mock_calls) == 3
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
assert len(mock_forward.mock_calls) == 1
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
assert forward_entries == {"light", "binary_sensor", "sensor"}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ async def test_bridge_setup_v2(hass: HomeAssistant, mock_api_v2) -> None:
|
||||
)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV2", return_value=mock_api_v2), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -59,8 +59,8 @@ async def test_bridge_setup_v2(hass: HomeAssistant, mock_api_v2) -> None:
|
||||
assert hue_bridge.api is mock_api_v2
|
||||
assert isinstance(hue_bridge.api, HueBridgeV2)
|
||||
assert hue_bridge.api_version == 2
|
||||
assert len(mock_forward.mock_calls) == 6
|
||||
forward_entries = {c[1][1] for c in mock_forward.mock_calls}
|
||||
assert len(mock_forward.mock_calls) == 1
|
||||
forward_entries = set(mock_forward.mock_calls[0][1][1])
|
||||
assert forward_entries == {
|
||||
"light",
|
||||
"binary_sensor",
|
||||
@ -115,7 +115,7 @@ async def test_reset_unloads_entry_if_setup(hass: HomeAssistant, mock_api_v1) ->
|
||||
)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -123,7 +123,7 @@ async def test_reset_unloads_entry_if_setup(hass: HomeAssistant, mock_api_v1) ->
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert len(hass.services.async_services()) == 0
|
||||
assert len(mock_forward.mock_calls) == 3
|
||||
assert len(mock_forward.mock_calls) == 1
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_unload", return_value=True
|
||||
|
@ -63,7 +63,7 @@ async def test_hue_activate_scene(hass: HomeAssistant, mock_api_v1) -> None:
|
||||
mock_api_v1.mock_scene_responses.append(SCENE_RESPONSE)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
):
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -100,7 +100,7 @@ async def test_hue_activate_scene_transition(hass: HomeAssistant, mock_api_v1) -
|
||||
mock_api_v1.mock_scene_responses.append(SCENE_RESPONSE)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
):
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -139,7 +139,7 @@ async def test_hue_activate_scene_group_not_found(
|
||||
mock_api_v1.mock_scene_responses.append(SCENE_RESPONSE)
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
):
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
@ -173,7 +173,7 @@ async def test_hue_activate_scene_scene_not_found(
|
||||
mock_api_v1.mock_scene_responses.append({})
|
||||
|
||||
with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1), patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
):
|
||||
hue_bridge = bridge.HueBridge(hass, config_entry)
|
||||
assert await hue_bridge.async_initialize_bridge() is True
|
||||
|
@ -76,8 +76,6 @@ async def test_minio_services(
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "Setup of domain minio took" in caplog.text
|
||||
|
||||
# Call services
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@ -141,8 +139,6 @@ async def test_minio_listen(
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "Setup of domain minio took" in caplog.text
|
||||
|
||||
while not events:
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
@ -126,7 +126,7 @@ async def test_unload(hass: HomeAssistant) -> None:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setup"
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setups"
|
||||
) as mock_forward:
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}, data={}
|
||||
@ -135,8 +135,7 @@ async def test_unload(hass: HomeAssistant) -> None:
|
||||
assert len(mock_forward.mock_calls) == 1
|
||||
entry = result["result"]
|
||||
|
||||
assert mock_forward.mock_calls[0][1][0] is entry
|
||||
assert mock_forward.mock_calls[0][1][1] == "device_tracker"
|
||||
mock_forward.assert_called_once_with(entry, ["device_tracker"])
|
||||
assert entry.data["webhook_id"] in hass.data["webhook"]
|
||||
|
||||
with patch(
|
||||
@ -146,8 +145,7 @@ async def test_unload(hass: HomeAssistant) -> None:
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
|
||||
assert len(mock_unload.mock_calls) == 1
|
||||
assert mock_forward.mock_calls[0][1][0] is entry
|
||||
assert mock_forward.mock_calls[0][1][1] == "device_tracker"
|
||||
mock_forward.assert_called_once_with(entry, ["device_tracker"])
|
||||
assert entry.data["webhook_id"] not in hass.data["webhook"]
|
||||
|
||||
|
||||
|
@ -179,11 +179,13 @@ async def test_scenes_unauthorized_loads_platforms(
|
||||
]
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == len(PLATFORMS)
|
||||
forward_mock.assert_called_once_with(config_entry, PLATFORMS)
|
||||
|
||||
|
||||
async def test_config_entry_loads_platforms(
|
||||
@ -211,11 +213,13 @@ async def test_config_entry_loads_platforms(
|
||||
]
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == len(PLATFORMS)
|
||||
forward_mock.assert_called_once_with(config_entry, PLATFORMS)
|
||||
|
||||
|
||||
async def test_config_entry_loads_unconnected_cloud(
|
||||
@ -243,10 +247,12 @@ async def test_config_entry_loads_unconnected_cloud(
|
||||
subscription_factory(capability) for capability in device.capabilities
|
||||
]
|
||||
smartthings_mock.subscriptions.return_value = subscriptions
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setup") as forward_mock:
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as forward_mock:
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == len(PLATFORMS)
|
||||
forward_mock.assert_called_once_with(config_entry, PLATFORMS)
|
||||
|
||||
|
||||
async def test_unload_entry(hass: HomeAssistant, config_entry) -> None:
|
||||
|
@ -148,6 +148,7 @@ async def test_service_without_cache_config(
|
||||
|
||||
with assert_setup_component(1, DOMAIN):
|
||||
assert await async_setup_component(hass, DOMAIN, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
@ -24,11 +24,11 @@ from homeassistant.components.unifi.const import (
|
||||
DEFAULT_TRACK_DEVICES,
|
||||
DEFAULT_TRACK_WIRED_CLIENTS,
|
||||
DOMAIN as UNIFI_DOMAIN,
|
||||
PLATFORMS,
|
||||
UNIFI_WIRELESS_CLIENTS,
|
||||
)
|
||||
from homeassistant.components.unifi.errors import AuthenticationRequired, CannotConnect
|
||||
from homeassistant.components.unifi.hub import get_unifi_api
|
||||
from homeassistant.components.update import DOMAIN as UPDATE_DOMAIN
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PASSWORD,
|
||||
@ -248,7 +248,7 @@ async def test_hub_setup(
|
||||
) -> None:
|
||||
"""Successful setup."""
|
||||
with patch(
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setup",
|
||||
"homeassistant.config_entries.ConfigEntries.async_forward_entry_setups",
|
||||
return_value=True,
|
||||
) as forward_entry_setup:
|
||||
config_entry = await setup_unifi_integration(
|
||||
@ -257,12 +257,18 @@ async def test_hub_setup(
|
||||
hub = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
|
||||
|
||||
entry = hub.config.entry
|
||||
assert len(forward_entry_setup.mock_calls) == len(PLATFORMS)
|
||||
assert forward_entry_setup.mock_calls[0][1] == (entry, BUTTON_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[1][1] == (entry, TRACKER_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[2][1] == (entry, IMAGE_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[3][1] == (entry, SENSOR_DOMAIN)
|
||||
assert forward_entry_setup.mock_calls[4][1] == (entry, SWITCH_DOMAIN)
|
||||
assert len(forward_entry_setup.mock_calls) == 1
|
||||
assert forward_entry_setup.mock_calls[0][1] == (
|
||||
entry,
|
||||
[
|
||||
BUTTON_DOMAIN,
|
||||
TRACKER_DOMAIN,
|
||||
IMAGE_DOMAIN,
|
||||
SENSOR_DOMAIN,
|
||||
SWITCH_DOMAIN,
|
||||
UPDATE_DOMAIN,
|
||||
],
|
||||
)
|
||||
|
||||
assert hub.config.host == ENTRY_CONFIG[CONF_HOST]
|
||||
assert hub.is_admin == (SITE[0]["role"] == "admin")
|
||||
|
@ -30,15 +30,12 @@ async def test_async_setup_entry__not_login(
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as setups_mock, patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
) as setup_mock, patch(
|
||||
) as setups_mock, patch(
|
||||
"homeassistant.components.vesync.async_process_devices"
|
||||
) as process_mock:
|
||||
assert not await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
assert setups_mock.call_count == 0
|
||||
assert setup_mock.call_count == 0
|
||||
assert process_mock.call_count == 0
|
||||
|
||||
assert manager.login.call_count == 1
|
||||
@ -50,18 +47,13 @@ async def test_async_setup_entry__no_devices(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, manager: VeSync
|
||||
) -> None:
|
||||
"""Test setup connects to vesync and creates empty config when no devices."""
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as setups_mock, patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
) as setup_mock:
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setups") as setups_mock:
|
||||
assert await async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert setups_mock.call_count == 1
|
||||
assert setups_mock.call_args.args[0] == config_entry
|
||||
assert setups_mock.call_args.args[1] == []
|
||||
assert setup_mock.call_count == 0
|
||||
|
||||
assert manager.login.call_count == 1
|
||||
assert hass.data[DOMAIN][VS_MANAGER] == manager
|
||||
@ -81,18 +73,13 @@ async def test_async_setup_entry__loads_fans(
|
||||
"fans": fans,
|
||||
}
|
||||
|
||||
with patch.object(
|
||||
hass.config_entries, "async_forward_entry_setups"
|
||||
) as setups_mock, patch.object(
|
||||
hass.config_entries, "async_forward_entry_setup"
|
||||
) as setup_mock:
|
||||
with patch.object(hass.config_entries, "async_forward_entry_setups") as setups_mock:
|
||||
assert await async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert setups_mock.call_count == 1
|
||||
assert setups_mock.call_args.args[0] == config_entry
|
||||
assert setups_mock.call_args.args[1] == [Platform.FAN, Platform.SENSOR]
|
||||
assert setup_mock.call_count == 0
|
||||
assert manager.login.call_count == 1
|
||||
assert hass.data[DOMAIN][VS_MANAGER] == manager
|
||||
assert not hass.data[DOMAIN][VS_SWITCHES]
|
||||
|
@ -859,7 +859,7 @@ async def test_forward_entry_sets_up_component(hass: HomeAssistant) -> None:
|
||||
entry = MockConfigEntry(domain="original")
|
||||
|
||||
mock_original_setup_entry = AsyncMock(return_value=True)
|
||||
mock_integration(
|
||||
integration = mock_integration(
|
||||
hass, MockModule("original", async_setup_entry=mock_original_setup_entry)
|
||||
)
|
||||
|
||||
@ -868,7 +868,10 @@ async def test_forward_entry_sets_up_component(hass: HomeAssistant) -> None:
|
||||
hass, MockModule("forwarded", async_setup_entry=mock_forwarded_setup_entry)
|
||||
)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setup(entry, "forwarded")
|
||||
with patch.object(integration, "async_get_platform") as mock_async_get_platform:
|
||||
await hass.config_entries.async_forward_entry_setup(entry, "forwarded")
|
||||
|
||||
mock_async_get_platform.assert_called_once_with("forwarded")
|
||||
assert len(mock_original_setup_entry.mock_calls) == 0
|
||||
assert len(mock_forwarded_setup_entry.mock_calls) == 1
|
||||
|
||||
|
@ -4,6 +4,7 @@ import asyncio
|
||||
import threading
|
||||
from unittest.mock import ANY, AsyncMock, Mock, patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
@ -16,6 +17,10 @@ from homeassistant.helpers.config_validation import (
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_connect,
|
||||
async_dispatcher_send,
|
||||
)
|
||||
|
||||
from .common import (
|
||||
MockConfigEntry,
|
||||
@ -739,7 +744,9 @@ async def test_async_start_setup_running(hass: HomeAssistant) -> None:
|
||||
assert not setup_started
|
||||
|
||||
|
||||
async def test_async_start_setup_config_entry(hass: HomeAssistant) -> None:
|
||||
async def test_async_start_setup_config_entry(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test setup started keeps track of setup times with a config entry."""
|
||||
hass.set_state(CoreState.not_running)
|
||||
setup_started: dict[tuple[str, str | None], float]
|
||||
@ -778,6 +785,7 @@ async def test_async_start_setup_config_entry(hass: HomeAssistant) -> None:
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP,
|
||||
):
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
# Platforms outside of CONFIG_ENTRY_SETUP should be tracked
|
||||
# This simulates a late platform forward
|
||||
assert setup_time["august"] == {
|
||||
@ -788,6 +796,38 @@ async def test_async_start_setup_config_entry(hass: HomeAssistant) -> None:
|
||||
},
|
||||
}
|
||||
|
||||
shorter_time = setup_time["august"]["entry_id"][
|
||||
setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP
|
||||
]
|
||||
# Setup another platform, but make it take longer
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP,
|
||||
):
|
||||
freezer.tick(10)
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
longer_time = setup_time["august"]["entry_id"][
|
||||
setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP
|
||||
]
|
||||
assert longer_time > shorter_time
|
||||
# Setup another platform, but make it take shorter
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP,
|
||||
):
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
# Ensure we keep the longest time
|
||||
assert (
|
||||
setup_time["august"]["entry_id"][setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP]
|
||||
== longer_time
|
||||
)
|
||||
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
@ -815,6 +855,106 @@ async def test_async_start_setup_config_entry(hass: HomeAssistant) -> None:
|
||||
}
|
||||
|
||||
|
||||
async def test_async_start_setup_config_entry_late_platform(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test setup started tracks config entry time with a late platform load."""
|
||||
hass.set_state(CoreState.not_running)
|
||||
setup_started: dict[tuple[str, str | None], float]
|
||||
setup_started = hass.data.setdefault(setup.DATA_SETUP_STARTED, {})
|
||||
setup_time = setup._setup_times(hass)
|
||||
|
||||
with setup.async_start_setup(
|
||||
hass, integration="august", phase=setup.SetupPhases.SETUP
|
||||
):
|
||||
freezer.tick(10)
|
||||
assert isinstance(setup_started[("august", None)], float)
|
||||
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_SETUP,
|
||||
):
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
@callback
|
||||
def async_late_platform_load():
|
||||
with setup.async_pause_setup(hass, setup.SetupPhases.WAIT_IMPORT_PLATFORMS):
|
||||
freezer.tick(100)
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP,
|
||||
):
|
||||
freezer.tick(20)
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
disconnect = async_dispatcher_connect(
|
||||
hass, "late_platform_load_test", async_late_platform_load
|
||||
)
|
||||
|
||||
# Dispatch a late platform load
|
||||
async_dispatcher_send(hass, "late_platform_load_test")
|
||||
disconnect()
|
||||
|
||||
# CONFIG_ENTRY_PLATFORM_SETUP is late dispatched, so it should be tracked
|
||||
# but any waiting time should not be because it's blocking the setup
|
||||
assert setup_time["august"] == {
|
||||
None: {setup.SetupPhases.SETUP: 10.0},
|
||||
"entry_id": {
|
||||
setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP: 20.0,
|
||||
setup.SetupPhases.CONFIG_ENTRY_SETUP: 0.0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def test_async_start_setup_config_entry_platform_wait(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test setup started tracks wait time when a platform loads inside of config entry setup."""
|
||||
hass.set_state(CoreState.not_running)
|
||||
setup_started: dict[tuple[str, str | None], float]
|
||||
setup_started = hass.data.setdefault(setup.DATA_SETUP_STARTED, {})
|
||||
setup_time = setup._setup_times(hass)
|
||||
|
||||
with setup.async_start_setup(
|
||||
hass, integration="august", phase=setup.SetupPhases.SETUP
|
||||
):
|
||||
freezer.tick(10)
|
||||
assert isinstance(setup_started[("august", None)], float)
|
||||
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_SETUP,
|
||||
):
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
with setup.async_pause_setup(hass, setup.SetupPhases.WAIT_IMPORT_PLATFORMS):
|
||||
freezer.tick(100)
|
||||
with setup.async_start_setup(
|
||||
hass,
|
||||
integration="august",
|
||||
group="entry_id",
|
||||
phase=setup.SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP,
|
||||
):
|
||||
freezer.tick(20)
|
||||
assert isinstance(setup_started[("august", "entry_id")], float)
|
||||
|
||||
# CONFIG_ENTRY_PLATFORM_SETUP is run inside of CONFIG_ENTRY_SETUP, so it should not
|
||||
# be tracked, but any wait time should still be tracked because its blocking the setup
|
||||
assert setup_time["august"] == {
|
||||
None: {setup.SetupPhases.SETUP: 10.0},
|
||||
"entry_id": {
|
||||
setup.SetupPhases.WAIT_IMPORT_PLATFORMS: -100.0,
|
||||
setup.SetupPhases.CONFIG_ENTRY_SETUP: 120.0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def test_async_start_setup_top_level_yaml(hass: HomeAssistant) -> None:
|
||||
"""Test setup started context manager keeps track of setup times with modern yaml."""
|
||||
hass.set_state(CoreState.not_running)
|
||||
|
Loading…
x
Reference in New Issue
Block a user