Improve demo integration's update entity (#129401)

* Improve demo integration's update entity

* Improve tests
This commit is contained in:
Erik Montnemery 2024-10-30 08:06:22 +01:00 committed by GitHub
parent 5f4103a4a7
commit 599acaf514
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 46 deletions

View file

@ -75,6 +75,21 @@ async def async_setup_entry(
support_release_notes=True, support_release_notes=True,
release_url="https://www.example.com/release/1.93.3", release_url="https://www.example.com/release/1.93.3",
device_class=UpdateDeviceClass.FIRMWARE, device_class=UpdateDeviceClass.FIRMWARE,
update_steps=10,
),
DemoUpdate(
unique_id="update_support_decimal_progress",
device_name="Demo Update with Decimal Progress",
title="Philips Lamps Firmware",
installed_version="1.93.3",
latest_version="1.94.2",
support_progress=True,
release_summary="Added support for effects",
support_release_notes=True,
release_url="https://www.example.com/release/1.93.3",
device_class=UpdateDeviceClass.FIRMWARE,
display_precision=2,
update_steps=1000,
), ),
] ]
) )
@ -106,10 +121,13 @@ class DemoUpdate(UpdateEntity):
support_install: bool = True, support_install: bool = True,
support_release_notes: bool = False, support_release_notes: bool = False,
device_class: UpdateDeviceClass | None = None, device_class: UpdateDeviceClass | None = None,
display_precision: int = 0,
update_steps: int = 100,
) -> None: ) -> None:
"""Initialize the Demo select entity.""" """Initialize the Demo select entity."""
self._attr_installed_version = installed_version self._attr_installed_version = installed_version
self._attr_device_class = device_class self._attr_device_class = device_class
self._attr_display_precision = display_precision
self._attr_latest_version = latest_version self._attr_latest_version = latest_version
self._attr_release_summary = release_summary self._attr_release_summary = release_summary
self._attr_release_url = release_url self._attr_release_url = release_url
@ -119,6 +137,7 @@ class DemoUpdate(UpdateEntity):
identifiers={(DOMAIN, unique_id)}, identifiers={(DOMAIN, unique_id)},
name=device_name, name=device_name,
) )
self._update_steps = update_steps
if support_install: if support_install:
self._attr_supported_features |= ( self._attr_supported_features |= (
UpdateEntityFeature.INSTALL UpdateEntityFeature.INSTALL
@ -136,12 +155,14 @@ class DemoUpdate(UpdateEntity):
) -> None: ) -> None:
"""Install an update.""" """Install an update."""
if self.supported_features & UpdateEntityFeature.PROGRESS: if self.supported_features & UpdateEntityFeature.PROGRESS:
for progress in range(0, 100, 10): self._attr_in_progress = True
self._attr_in_progress = progress for progress in range(0, self._update_steps, 1):
self._attr_update_percentage = progress / (self._update_steps / 100)
self.async_write_ha_state() self.async_write_ha_state()
await _fake_install() await _fake_install()
self._attr_in_progress = False self._attr_in_progress = False
self._attr_update_percentage = None
self._attr_installed_version = ( self._attr_installed_version = (
version if version is not None else self.latest_version version if version is not None else self.latest_version
) )

View file

@ -126,9 +126,18 @@ def test_setup_params(hass: HomeAssistant) -> None:
) )
async def test_update_with_progress(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
("entity_id", "steps"),
[
("update.demo_update_with_progress", 10),
("update.demo_update_with_decimal_progress", 1000),
],
)
async def test_update_with_progress(
hass: HomeAssistant, entity_id: str, steps: int
) -> None:
"""Test update with progress.""" """Test update with progress."""
state = hass.states.get("update.demo_update_with_progress") state = hass.states.get(entity_id)
assert state assert state
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes[ATTR_IN_PROGRESS] is False assert state.attributes[ATTR_IN_PROGRESS] is False
@ -137,7 +146,7 @@ async def test_update_with_progress(hass: HomeAssistant) -> None:
events = [] events = []
async_track_state_change_event( async_track_state_change_event(
hass, hass,
"update.demo_update_with_progress", entity_id,
# pylint: disable-next=unnecessary-lambda # pylint: disable-next=unnecessary-lambda
callback(lambda event: events.append(event)), callback(lambda event: events.append(event)),
) )
@ -146,40 +155,35 @@ async def test_update_with_progress(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
UPDATE_DOMAIN, UPDATE_DOMAIN,
SERVICE_INSTALL, SERVICE_INSTALL,
{ATTR_ENTITY_ID: "update.demo_update_with_progress"}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
assert len(events) == 11 assert len(events) == steps + 1
assert events[0].data["new_state"].state == STATE_ON for i, event in enumerate(events[:steps]):
assert events[0].data["new_state"].attributes[ATTR_IN_PROGRESS] is True new_state = event.data["new_state"]
assert events[0].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 0 assert new_state.state == STATE_ON
assert events[1].data["new_state"].attributes[ATTR_IN_PROGRESS] is True assert new_state.attributes[ATTR_UPDATE_PERCENTAGE] == pytest.approx(
assert events[1].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 10 100 / steps * i
assert events[2].data["new_state"].attributes[ATTR_IN_PROGRESS] is True )
assert events[2].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 20 new_state = events[steps].data["new_state"]
assert events[3].data["new_state"].attributes[ATTR_IN_PROGRESS] is True assert new_state.attributes[ATTR_IN_PROGRESS] is False
assert events[3].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 30 assert new_state.attributes[ATTR_UPDATE_PERCENTAGE] is None
assert events[4].data["new_state"].attributes[ATTR_IN_PROGRESS] is True assert new_state.state == STATE_OFF
assert events[4].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 40
assert events[5].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[5].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 50
assert events[6].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[6].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 60
assert events[7].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[7].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 70
assert events[8].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[8].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 80
assert events[9].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[9].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 90
assert events[10].data["new_state"].attributes[ATTR_IN_PROGRESS] is False
assert events[10].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] is None
assert events[10].data["new_state"].state == STATE_OFF
async def test_update_with_progress_raising(hass: HomeAssistant) -> None: @pytest.mark.parametrize(
("entity_id", "steps"),
[
("update.demo_update_with_progress", 10),
("update.demo_update_with_decimal_progress", 1000),
],
)
async def test_update_with_progress_raising(
hass: HomeAssistant, entity_id: str, steps: int
) -> None:
"""Test update with progress failing to install.""" """Test update with progress failing to install."""
state = hass.states.get("update.demo_update_with_progress") state = hass.states.get(entity_id)
assert state assert state
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes[ATTR_IN_PROGRESS] is False assert state.attributes[ATTR_IN_PROGRESS] is False
@ -188,7 +192,7 @@ async def test_update_with_progress_raising(hass: HomeAssistant) -> None:
events = [] events = []
async_track_state_change_event( async_track_state_change_event(
hass, hass,
"update.demo_update_with_progress", entity_id,
# pylint: disable-next=unnecessary-lambda # pylint: disable-next=unnecessary-lambda
callback(lambda event: events.append(event)), callback(lambda event: events.append(event)),
) )
@ -203,24 +207,19 @@ async def test_update_with_progress_raising(hass: HomeAssistant) -> None:
await hass.services.async_call( await hass.services.async_call(
UPDATE_DOMAIN, UPDATE_DOMAIN,
SERVICE_INSTALL, SERVICE_INSTALL,
{ATTR_ENTITY_ID: "update.demo_update_with_progress"}, {ATTR_ENTITY_ID: entity_id},
blocking=True, blocking=True,
) )
await hass.async_block_till_done() await hass.async_block_till_done()
assert fake_sleep.call_count == 5 assert fake_sleep.call_count == 5
assert len(events) == 6 assert len(events) == 6
assert events[0].data["new_state"].state == STATE_ON for i, event in enumerate(events[:5]):
assert events[0].data["new_state"].attributes[ATTR_IN_PROGRESS] is True new_state = event.data["new_state"]
assert events[0].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 0 assert new_state.state == STATE_ON
assert events[1].data["new_state"].attributes[ATTR_IN_PROGRESS] is True assert new_state.attributes[ATTR_UPDATE_PERCENTAGE] == pytest.approx(
assert events[1].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 10 100 / steps * i
assert events[2].data["new_state"].attributes[ATTR_IN_PROGRESS] is True )
assert events[2].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 20
assert events[3].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[3].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 30
assert events[4].data["new_state"].attributes[ATTR_IN_PROGRESS] is True
assert events[4].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] == 40
assert events[5].data["new_state"].attributes[ATTR_IN_PROGRESS] is False assert events[5].data["new_state"].attributes[ATTR_IN_PROGRESS] is False
assert events[5].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] is None assert events[5].data["new_state"].attributes[ATTR_UPDATE_PERCENTAGE] is None
assert events[5].data["new_state"].state == STATE_ON assert events[5].data["new_state"].state == STATE_ON