2023-01-11 21:26:13 +00:00
|
|
|
"""Test ESPHome update entities."""
|
2024-03-08 13:50:25 +00:00
|
|
|
|
2023-07-13 02:46:29 +00:00
|
|
|
from collections.abc import Awaitable, Callable
|
2023-01-11 21:26:13 +00:00
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
|
2023-08-10 12:27:03 +00:00
|
|
|
from aioesphomeapi import APIClient, EntityInfo, EntityState, UserService
|
2023-01-11 21:26:13 +00:00
|
|
|
import pytest
|
|
|
|
|
2023-08-10 12:27:03 +00:00
|
|
|
from homeassistant.components.esphome.dashboard import async_get_dashboard
|
2023-02-01 04:15:23 +00:00
|
|
|
from homeassistant.components.update import UpdateEntityFeature
|
2024-01-04 00:58:04 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
ATTR_SUPPORTED_FEATURES,
|
|
|
|
STATE_OFF,
|
|
|
|
STATE_ON,
|
|
|
|
STATE_UNAVAILABLE,
|
|
|
|
STATE_UNKNOWN,
|
|
|
|
)
|
2023-02-13 08:45:11 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
2023-07-13 02:46:29 +00:00
|
|
|
from homeassistant.exceptions import HomeAssistantError
|
2023-01-11 21:26:13 +00:00
|
|
|
|
2023-07-13 02:46:29 +00:00
|
|
|
from .conftest import MockESPHomeDevice
|
2023-01-11 21:26:13 +00:00
|
|
|
|
2023-07-13 02:46:29 +00:00
|
|
|
|
|
|
|
@pytest.fixture
|
2023-01-11 21:26:13 +00:00
|
|
|
def stub_reconnect():
|
|
|
|
"""Stub reconnect."""
|
2023-07-08 07:19:44 +00:00
|
|
|
with patch("homeassistant.components.esphome.manager.ReconnectLogic.start"):
|
2023-01-11 21:26:13 +00:00
|
|
|
yield
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-02-15 13:09:50 +00:00
|
|
|
("devices_payload", "expected_state", "expected_attributes"),
|
2023-01-11 21:26:13 +00:00
|
|
|
[
|
|
|
|
(
|
2023-01-19 21:28:46 +00:00
|
|
|
[
|
|
|
|
{
|
|
|
|
"name": "test",
|
2023-02-01 04:15:23 +00:00
|
|
|
"current_version": "2023.2.0-dev",
|
2023-01-19 21:28:46 +00:00
|
|
|
"configuration": "test.yaml",
|
|
|
|
}
|
|
|
|
],
|
2023-07-13 02:46:29 +00:00
|
|
|
STATE_ON,
|
2023-02-01 04:15:23 +00:00
|
|
|
{
|
|
|
|
"latest_version": "2023.2.0-dev",
|
|
|
|
"installed_version": "1.0.0",
|
|
|
|
"supported_features": UpdateEntityFeature.INSTALL,
|
|
|
|
},
|
2023-01-11 21:26:13 +00:00
|
|
|
),
|
|
|
|
(
|
2023-01-19 21:28:46 +00:00
|
|
|
[
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "1.0.0",
|
|
|
|
},
|
|
|
|
],
|
2023-07-13 02:46:29 +00:00
|
|
|
STATE_OFF,
|
2023-02-01 04:15:23 +00:00
|
|
|
{
|
|
|
|
"latest_version": "1.0.0",
|
|
|
|
"installed_version": "1.0.0",
|
|
|
|
"supported_features": 0,
|
|
|
|
},
|
2023-01-11 21:26:13 +00:00
|
|
|
),
|
|
|
|
(
|
|
|
|
[],
|
2023-07-13 02:46:29 +00:00
|
|
|
STATE_UNKNOWN, # dashboard is available but device is unknown
|
2023-02-01 04:15:23 +00:00
|
|
|
{"supported_features": 0},
|
2023-01-11 21:26:13 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
async def test_update_entity(
|
2023-02-13 08:45:11 +00:00
|
|
|
hass: HomeAssistant,
|
2023-07-13 02:46:29 +00:00
|
|
|
stub_reconnect,
|
2023-01-11 21:26:13 +00:00
|
|
|
mock_config_entry,
|
|
|
|
mock_device_info,
|
2023-01-18 16:59:55 +00:00
|
|
|
mock_dashboard,
|
2023-01-11 21:26:13 +00:00
|
|
|
devices_payload,
|
|
|
|
expected_state,
|
|
|
|
expected_attributes,
|
2023-02-13 08:45:11 +00:00
|
|
|
) -> None:
|
2023-01-11 21:26:13 +00:00
|
|
|
"""Test ESPHome update entity."""
|
2023-01-18 16:59:55 +00:00
|
|
|
mock_dashboard["configured"] = devices_payload
|
2023-01-18 20:15:37 +00:00
|
|
|
await async_get_dashboard(hass).async_refresh()
|
2023-01-11 21:26:13 +00:00
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.esphome.update.DomainData.get_entry_data",
|
|
|
|
return_value=Mock(available=True, device_info=mock_device_info),
|
|
|
|
):
|
Ensure config entries are not unloaded while their platforms are setting up (#118767)
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* run with error on to find them
* cert_exp, hold lock
* cert_exp, hold lock
* shelly async_late_forward_entry_setups
* compact
* compact
* found another
* patch up mobileapp
* patch up hue tests
* patch up smartthings
* fix mqtt
* fix esphome
* zwave_js
* mqtt
* rework
* fixes
* fix mocking
* fix mocking
* do not call async_forward_entry_setup directly
* docstrings
* docstrings
* docstrings
* add comments
* doc strings
* fixed all in core, turn off strict
* coverage
* coverage
* missing
* coverage
2024-06-05 01:34:39 +00:00
|
|
|
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
2023-01-11 21:26:13 +00:00
|
|
|
|
|
|
|
state = hass.states.get("update.none_firmware")
|
|
|
|
assert state is not None
|
|
|
|
assert state.state == expected_state
|
|
|
|
for key, expected_value in expected_attributes.items():
|
|
|
|
assert state.attributes.get(key) == expected_value
|
2023-01-19 21:28:46 +00:00
|
|
|
|
|
|
|
if expected_state != "on":
|
|
|
|
return
|
|
|
|
|
2023-07-13 02:46:29 +00:00
|
|
|
# Compile failed, don't try to upload
|
2024-03-25 23:02:16 +00:00
|
|
|
with (
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=False
|
|
|
|
) as mock_compile,
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.upload", return_value=True
|
|
|
|
) as mock_upload,
|
|
|
|
pytest.raises(
|
|
|
|
HomeAssistantError,
|
|
|
|
match="compiling",
|
|
|
|
),
|
2023-07-13 02:46:29 +00:00
|
|
|
):
|
|
|
|
await hass.services.async_call(
|
|
|
|
"update",
|
|
|
|
"install",
|
|
|
|
{"entity_id": "update.none_firmware"},
|
|
|
|
blocking=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert len(mock_compile.mock_calls) == 1
|
|
|
|
assert mock_compile.mock_calls[0][1][0] == "test.yaml"
|
|
|
|
|
|
|
|
assert len(mock_upload.mock_calls) == 0
|
|
|
|
|
|
|
|
# Compile success, upload fails
|
2024-03-25 23:02:16 +00:00
|
|
|
with (
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=True
|
|
|
|
) as mock_compile,
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.upload", return_value=False
|
|
|
|
) as mock_upload,
|
|
|
|
pytest.raises(
|
|
|
|
HomeAssistantError,
|
|
|
|
match="OTA",
|
|
|
|
),
|
2023-07-13 02:46:29 +00:00
|
|
|
):
|
|
|
|
await hass.services.async_call(
|
|
|
|
"update",
|
|
|
|
"install",
|
|
|
|
{"entity_id": "update.none_firmware"},
|
|
|
|
blocking=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert len(mock_compile.mock_calls) == 1
|
|
|
|
assert mock_compile.mock_calls[0][1][0] == "test.yaml"
|
|
|
|
|
|
|
|
assert len(mock_upload.mock_calls) == 1
|
|
|
|
assert mock_upload.mock_calls[0][1][0] == "test.yaml"
|
|
|
|
|
|
|
|
# Everything works
|
2024-03-25 23:02:16 +00:00
|
|
|
with (
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=True
|
|
|
|
) as mock_compile,
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.upload", return_value=True
|
|
|
|
) as mock_upload,
|
|
|
|
):
|
2023-01-19 21:28:46 +00:00
|
|
|
await hass.services.async_call(
|
|
|
|
"update",
|
|
|
|
"install",
|
|
|
|
{"entity_id": "update.none_firmware"},
|
|
|
|
blocking=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
assert len(mock_compile.mock_calls) == 1
|
|
|
|
assert mock_compile.mock_calls[0][1][0] == "test.yaml"
|
|
|
|
|
|
|
|
assert len(mock_upload.mock_calls) == 1
|
|
|
|
assert mock_upload.mock_calls[0][1][0] == "test.yaml"
|
2023-02-01 03:13:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_update_static_info(
|
2023-02-13 08:45:11 +00:00
|
|
|
hass: HomeAssistant,
|
2024-04-24 14:14:44 +00:00
|
|
|
mock_client: APIClient,
|
|
|
|
mock_esphome_device: Callable[
|
|
|
|
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
|
|
|
Awaitable[MockESPHomeDevice],
|
|
|
|
],
|
2023-02-01 03:13:41 +00:00
|
|
|
mock_dashboard,
|
2023-02-13 08:45:11 +00:00
|
|
|
) -> None:
|
2023-02-01 03:13:41 +00:00
|
|
|
"""Test ESPHome update entity."""
|
|
|
|
mock_dashboard["configured"] = [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "1.2.3",
|
|
|
|
},
|
|
|
|
]
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
|
2024-04-24 14:14:44 +00:00
|
|
|
mock_device: MockESPHomeDevice = await mock_esphome_device(
|
|
|
|
mock_client=mock_client,
|
|
|
|
entity_info=[],
|
|
|
|
user_service=[],
|
|
|
|
states=[],
|
2023-02-01 03:13:41 +00:00
|
|
|
)
|
|
|
|
|
2024-04-24 14:14:44 +00:00
|
|
|
state = hass.states.get("update.test_firmware")
|
2023-02-01 03:13:41 +00:00
|
|
|
assert state is not None
|
2024-04-24 14:14:44 +00:00
|
|
|
assert state.state == STATE_ON
|
2023-02-01 03:13:41 +00:00
|
|
|
|
2024-04-24 14:14:44 +00:00
|
|
|
object.__setattr__(mock_device.device_info, "esphome_version", "1.2.3")
|
|
|
|
await mock_device.mock_disconnect(True)
|
|
|
|
await mock_device.mock_connect()
|
2023-02-01 03:13:41 +00:00
|
|
|
|
2024-04-24 14:14:44 +00:00
|
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state.state == STATE_OFF
|
2023-02-07 21:15:54 +00:00
|
|
|
|
|
|
|
|
2023-06-26 20:20:56 +00:00
|
|
|
@pytest.mark.parametrize(
|
2024-03-10 06:30:17 +00:00
|
|
|
("expected_disconnect", "expected_state", "has_deep_sleep"),
|
|
|
|
[
|
|
|
|
(True, STATE_ON, False),
|
|
|
|
(False, STATE_UNAVAILABLE, False),
|
|
|
|
(True, STATE_ON, True),
|
|
|
|
(False, STATE_ON, True),
|
|
|
|
],
|
2023-06-26 20:20:56 +00:00
|
|
|
)
|
2023-02-07 21:15:54 +00:00
|
|
|
async def test_update_device_state_for_availability(
|
2023-02-13 08:45:11 +00:00
|
|
|
hass: HomeAssistant,
|
2024-03-10 06:30:17 +00:00
|
|
|
expected_disconnect: bool,
|
|
|
|
expected_state: str,
|
|
|
|
has_deep_sleep: bool,
|
2023-02-07 21:15:54 +00:00
|
|
|
mock_dashboard,
|
2024-03-10 06:30:17 +00:00
|
|
|
mock_client: APIClient,
|
|
|
|
mock_esphome_device: Callable[
|
|
|
|
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
|
|
|
Awaitable[MockESPHomeDevice],
|
|
|
|
],
|
2023-02-13 08:45:11 +00:00
|
|
|
) -> None:
|
2023-02-07 21:15:54 +00:00
|
|
|
"""Test ESPHome update entity changes availability with the device."""
|
|
|
|
mock_dashboard["configured"] = [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "1.2.3",
|
|
|
|
},
|
|
|
|
]
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
2024-03-10 06:30:17 +00:00
|
|
|
mock_device = await mock_esphome_device(
|
|
|
|
mock_client=mock_client,
|
|
|
|
entity_info=[],
|
|
|
|
user_service=[],
|
|
|
|
states=[],
|
|
|
|
device_info={"has_deep_sleep": has_deep_sleep},
|
2023-02-07 21:15:54 +00:00
|
|
|
)
|
|
|
|
|
2024-03-10 06:30:17 +00:00
|
|
|
state = hass.states.get("update.test_firmware")
|
2023-02-07 21:15:54 +00:00
|
|
|
assert state is not None
|
2024-03-10 06:30:17 +00:00
|
|
|
assert state.state == STATE_ON
|
|
|
|
await mock_device.mock_disconnect(expected_disconnect)
|
|
|
|
state = hass.states.get("update.test_firmware")
|
2023-06-26 20:20:56 +00:00
|
|
|
assert state.state == expected_state
|
2023-02-07 21:15:54 +00:00
|
|
|
|
2023-04-26 16:41:00 +00:00
|
|
|
|
|
|
|
async def test_update_entity_dashboard_not_available_startup(
|
2023-07-13 02:46:29 +00:00
|
|
|
hass: HomeAssistant,
|
|
|
|
stub_reconnect,
|
|
|
|
mock_config_entry,
|
|
|
|
mock_device_info,
|
|
|
|
mock_dashboard,
|
2023-04-26 16:41:00 +00:00
|
|
|
) -> None:
|
|
|
|
"""Test ESPHome update entity when dashboard is not available at startup."""
|
2024-03-25 23:02:16 +00:00
|
|
|
with (
|
|
|
|
patch(
|
|
|
|
"homeassistant.components.esphome.update.DomainData.get_entry_data",
|
|
|
|
return_value=Mock(available=True, device_info=mock_device_info),
|
|
|
|
),
|
|
|
|
patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.get_devices",
|
|
|
|
side_effect=TimeoutError,
|
|
|
|
),
|
2023-04-26 16:41:00 +00:00
|
|
|
):
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
Ensure config entries are not unloaded while their platforms are setting up (#118767)
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* run with error on to find them
* cert_exp, hold lock
* cert_exp, hold lock
* shelly async_late_forward_entry_setups
* compact
* compact
* found another
* patch up mobileapp
* patch up hue tests
* patch up smartthings
* fix mqtt
* fix esphome
* zwave_js
* mqtt
* rework
* fixes
* fix mocking
* fix mocking
* do not call async_forward_entry_setup directly
* docstrings
* docstrings
* docstrings
* add comments
* doc strings
* fixed all in core, turn off strict
* coverage
* coverage
* missing
* coverage
2024-06-05 01:34:39 +00:00
|
|
|
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
2023-04-26 16:41:00 +00:00
|
|
|
|
2023-07-13 02:46:29 +00:00
|
|
|
# We have a dashboard but it is not available
|
2023-04-26 16:41:00 +00:00
|
|
|
state = hass.states.get("update.none_firmware")
|
|
|
|
assert state is None
|
|
|
|
|
|
|
|
mock_dashboard["configured"] = [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "2023.2.0-dev",
|
|
|
|
"configuration": "test.yaml",
|
|
|
|
}
|
|
|
|
]
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
state = hass.states.get("update.none_firmware")
|
2023-07-13 02:46:29 +00:00
|
|
|
assert state.state == STATE_ON
|
2023-04-26 16:41:00 +00:00
|
|
|
expected_attributes = {
|
|
|
|
"latest_version": "2023.2.0-dev",
|
|
|
|
"installed_version": "1.0.0",
|
|
|
|
"supported_features": UpdateEntityFeature.INSTALL,
|
|
|
|
}
|
|
|
|
for key, expected_value in expected_attributes.items():
|
|
|
|
assert state.attributes.get(key) == expected_value
|
2023-07-13 02:46:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_update_entity_dashboard_discovered_after_startup_but_update_failed(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
mock_client: APIClient,
|
|
|
|
mock_esphome_device: Callable[
|
|
|
|
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
|
|
|
Awaitable[MockESPHomeDevice],
|
|
|
|
],
|
|
|
|
mock_dashboard,
|
|
|
|
) -> None:
|
|
|
|
"""Test ESPHome update entity when dashboard is discovered after startup and the first update fails."""
|
|
|
|
with patch(
|
|
|
|
"esphome_dashboard_api.ESPHomeDashboardAPI.get_devices",
|
2024-02-05 11:00:37 +00:00
|
|
|
side_effect=TimeoutError,
|
2023-07-13 02:46:29 +00:00
|
|
|
):
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
mock_device = await mock_esphome_device(
|
|
|
|
mock_client=mock_client,
|
|
|
|
entity_info=[],
|
|
|
|
user_service=[],
|
|
|
|
states=[],
|
|
|
|
)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state is None
|
|
|
|
|
|
|
|
await mock_device.mock_disconnect(False)
|
|
|
|
|
|
|
|
mock_dashboard["configured"] = [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "2023.2.0-dev",
|
|
|
|
"configuration": "test.yaml",
|
|
|
|
}
|
|
|
|
]
|
|
|
|
# Device goes unavailable, and dashboard becomes available
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state is None
|
|
|
|
|
|
|
|
# Finally both are available
|
|
|
|
await mock_device.mock_connect()
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state is not None
|
|
|
|
|
|
|
|
|
|
|
|
async def test_update_entity_not_present_without_dashboard(
|
|
|
|
hass: HomeAssistant, stub_reconnect, mock_config_entry, mock_device_info
|
|
|
|
) -> None:
|
|
|
|
"""Test ESPHome update entity does not get created if there is no dashboard."""
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.esphome.update.DomainData.get_entry_data",
|
|
|
|
return_value=Mock(available=True, device_info=mock_device_info),
|
|
|
|
):
|
Ensure config entries are not unloaded while their platforms are setting up (#118767)
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* Report non-awaited/non-locked config entry platform forwards
Its currently possible for config entries to be reloaded while their platforms
are being forwarded if platform forwards are not awaited or done after the
config entry is setup since the lock will not be held in this case.
In https://developers.home-assistant.io/blog/2022/07/08/config_entry_forwards
we advised to await platform forwards to ensure this does not happen, however
for sleeping devices and late discovered devices, platform forwards may happen
later.
If config platform forwards are happening during setup, they should be awaited
If config entry platform forwards are not happening during setup, instead
async_late_forward_entry_setups should be used which will hold the lock to
prevent the config entry from being unloaded while its platforms are being
setup
* run with error on to find them
* cert_exp, hold lock
* cert_exp, hold lock
* shelly async_late_forward_entry_setups
* compact
* compact
* found another
* patch up mobileapp
* patch up hue tests
* patch up smartthings
* fix mqtt
* fix esphome
* zwave_js
* mqtt
* rework
* fixes
* fix mocking
* fix mocking
* do not call async_forward_entry_setup directly
* docstrings
* docstrings
* docstrings
* add comments
* doc strings
* fixed all in core, turn off strict
* coverage
* coverage
* missing
* coverage
2024-06-05 01:34:39 +00:00
|
|
|
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
2023-07-13 02:46:29 +00:00
|
|
|
|
|
|
|
state = hass.states.get("update.none_firmware")
|
|
|
|
assert state is None
|
2024-01-04 00:58:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_update_becomes_available_at_runtime(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
mock_client: APIClient,
|
|
|
|
mock_esphome_device: Callable[
|
|
|
|
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
|
|
|
Awaitable[MockESPHomeDevice],
|
|
|
|
],
|
|
|
|
mock_dashboard,
|
|
|
|
) -> None:
|
|
|
|
"""Test ESPHome update entity when the dashboard has no device at startup but gets them later."""
|
|
|
|
await mock_esphome_device(
|
|
|
|
mock_client=mock_client,
|
|
|
|
entity_info=[],
|
|
|
|
user_service=[],
|
|
|
|
states=[],
|
|
|
|
)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state is not None
|
|
|
|
features = state.attributes[ATTR_SUPPORTED_FEATURES]
|
|
|
|
# There are no devices on the dashboard so no
|
|
|
|
# way to tell the version so install is disabled
|
|
|
|
assert features is UpdateEntityFeature(0)
|
|
|
|
|
|
|
|
# A device gets added to the dashboard
|
|
|
|
mock_dashboard["configured"] = [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"current_version": "2023.2.0-dev",
|
|
|
|
"configuration": "test.yaml",
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
await async_get_dashboard(hass).async_refresh()
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
state = hass.states.get("update.test_firmware")
|
|
|
|
assert state is not None
|
|
|
|
# We now know the version so install is enabled
|
|
|
|
features = state.attributes[ATTR_SUPPORTED_FEATURES]
|
|
|
|
assert features is UpdateEntityFeature.INSTALL
|