mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Allow update entities to report progress as a float (#128930)
* Allow update entities to report progress as a float * Add test * Update snapshots * Update recorder test * Use _attr_* in MockUpdateEntity
This commit is contained in:
parent
87a2465a25
commit
bd55fe868d
@ -27,6 +27,7 @@ from homeassistant.util.hass_dict import HassKey
|
|||||||
from .const import (
|
from .const import (
|
||||||
ATTR_AUTO_UPDATE,
|
ATTR_AUTO_UPDATE,
|
||||||
ATTR_BACKUP,
|
ATTR_BACKUP,
|
||||||
|
ATTR_DISPLAY_PRECISION,
|
||||||
ATTR_IN_PROGRESS,
|
ATTR_IN_PROGRESS,
|
||||||
ATTR_INSTALLED_VERSION,
|
ATTR_INSTALLED_VERSION,
|
||||||
ATTR_LATEST_VERSION,
|
ATTR_LATEST_VERSION,
|
||||||
@ -178,6 +179,7 @@ class UpdateEntityDescription(EntityDescription, frozen_or_thawed=True):
|
|||||||
"""A class that describes update entities."""
|
"""A class that describes update entities."""
|
||||||
|
|
||||||
device_class: UpdateDeviceClass | None = None
|
device_class: UpdateDeviceClass | None = None
|
||||||
|
display_precision: int = 0
|
||||||
entity_category: EntityCategory | None = EntityCategory.CONFIG
|
entity_category: EntityCategory | None = EntityCategory.CONFIG
|
||||||
|
|
||||||
|
|
||||||
@ -191,6 +193,7 @@ CACHED_PROPERTIES_WITH_ATTR_ = {
|
|||||||
"auto_update",
|
"auto_update",
|
||||||
"installed_version",
|
"installed_version",
|
||||||
"device_class",
|
"device_class",
|
||||||
|
"display_precision",
|
||||||
"in_progress",
|
"in_progress",
|
||||||
"latest_version",
|
"latest_version",
|
||||||
"release_summary",
|
"release_summary",
|
||||||
@ -210,6 +213,7 @@ class UpdateEntity(
|
|||||||
|
|
||||||
_entity_component_unrecorded_attributes = frozenset(
|
_entity_component_unrecorded_attributes = frozenset(
|
||||||
{
|
{
|
||||||
|
ATTR_DISPLAY_PRECISION,
|
||||||
ATTR_ENTITY_PICTURE,
|
ATTR_ENTITY_PICTURE,
|
||||||
ATTR_IN_PROGRESS,
|
ATTR_IN_PROGRESS,
|
||||||
ATTR_RELEASE_SUMMARY,
|
ATTR_RELEASE_SUMMARY,
|
||||||
@ -221,6 +225,7 @@ class UpdateEntity(
|
|||||||
_attr_auto_update: bool = False
|
_attr_auto_update: bool = False
|
||||||
_attr_installed_version: str | None = None
|
_attr_installed_version: str | None = None
|
||||||
_attr_device_class: UpdateDeviceClass | None
|
_attr_device_class: UpdateDeviceClass | None
|
||||||
|
_attr_display_precision: int
|
||||||
_attr_in_progress: bool | int = False
|
_attr_in_progress: bool | int = False
|
||||||
_attr_latest_version: str | None = None
|
_attr_latest_version: str | None = None
|
||||||
_attr_release_summary: str | None = None
|
_attr_release_summary: str | None = None
|
||||||
@ -228,7 +233,7 @@ class UpdateEntity(
|
|||||||
_attr_state: None = None
|
_attr_state: None = None
|
||||||
_attr_supported_features: UpdateEntityFeature = UpdateEntityFeature(0)
|
_attr_supported_features: UpdateEntityFeature = UpdateEntityFeature(0)
|
||||||
_attr_title: str | None = None
|
_attr_title: str | None = None
|
||||||
_attr_update_percentage: int | None = None
|
_attr_update_percentage: int | float | None = None
|
||||||
__skipped_version: str | None = None
|
__skipped_version: str | None = None
|
||||||
__in_progress: bool = False
|
__in_progress: bool = False
|
||||||
|
|
||||||
@ -258,6 +263,15 @@ class UpdateEntity(
|
|||||||
return self.entity_description.device_class
|
return self.entity_description.device_class
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def display_precision(self) -> int:
|
||||||
|
"""Return number of decimal digits for display of update progress."""
|
||||||
|
if hasattr(self, "_attr_display_precision"):
|
||||||
|
return self._attr_display_precision
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.display_precision
|
||||||
|
return 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entity_category(self) -> EntityCategory | None:
|
def entity_category(self) -> EntityCategory | None:
|
||||||
"""Return the category of the entity, if any."""
|
"""Return the category of the entity, if any."""
|
||||||
@ -337,12 +351,12 @@ class UpdateEntity(
|
|||||||
return features
|
return features
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def update_percentage(self) -> int | None:
|
def update_percentage(self) -> int | float | None:
|
||||||
"""Update installation progress.
|
"""Update installation progress.
|
||||||
|
|
||||||
Needs UpdateEntityFeature.PROGRESS flag to be set for it to be used.
|
Needs UpdateEntityFeature.PROGRESS flag to be set for it to be used.
|
||||||
|
|
||||||
Can either return an integer to indicate the progress from 0 to 100% or None.
|
Can either return a number to indicate the progress from 0 to 100% or None.
|
||||||
"""
|
"""
|
||||||
return self._attr_update_percentage
|
return self._attr_update_percentage
|
||||||
|
|
||||||
@ -460,6 +474,7 @@ class UpdateEntity(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
ATTR_AUTO_UPDATE: self.auto_update,
|
ATTR_AUTO_UPDATE: self.auto_update,
|
||||||
|
ATTR_DISPLAY_PRECISION: self.display_precision,
|
||||||
ATTR_INSTALLED_VERSION: installed_version,
|
ATTR_INSTALLED_VERSION: installed_version,
|
||||||
ATTR_IN_PROGRESS: in_progress,
|
ATTR_IN_PROGRESS: in_progress,
|
||||||
ATTR_LATEST_VERSION: latest_version,
|
ATTR_LATEST_VERSION: latest_version,
|
||||||
|
@ -23,6 +23,7 @@ SERVICE_SKIP: Final = "skip"
|
|||||||
|
|
||||||
ATTR_AUTO_UPDATE: Final = "auto_update"
|
ATTR_AUTO_UPDATE: Final = "auto_update"
|
||||||
ATTR_BACKUP: Final = "backup"
|
ATTR_BACKUP: Final = "backup"
|
||||||
|
ATTR_DISPLAY_PRECISION: Final = "display_precision"
|
||||||
ATTR_INSTALLED_VERSION: Final = "installed_version"
|
ATTR_INSTALLED_VERSION: Final = "installed_version"
|
||||||
ATTR_IN_PROGRESS: Final = "in_progress"
|
ATTR_IN_PROGRESS: Final = "in_progress"
|
||||||
ATTR_LATEST_VERSION: Final = "latest_version"
|
ATTR_LATEST_VERSION: Final = "latest_version"
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/airgradient/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/airgradient/icon.png',
|
||||||
'friendly_name': 'Airgradient Firmware',
|
'friendly_name': 'Airgradient Firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/devolo_home_network/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/devolo_home_network/icon.png',
|
||||||
'friendly_name': 'Mock Title Firmware',
|
'friendly_name': 'Mock Title Firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
||||||
'friendly_name': 'Mock Title FRITZ!OS',
|
'friendly_name': 'Mock Title FRITZ!OS',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -93,6 +94,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
||||||
'friendly_name': 'Mock Title FRITZ!OS',
|
'friendly_name': 'Mock Title FRITZ!OS',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -150,6 +152,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/fritz/icon.png',
|
||||||
'friendly_name': 'Mock Title FRITZ!OS',
|
'friendly_name': 'Mock Title FRITZ!OS',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/iron_os/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/iron_os/icon.png',
|
||||||
'friendly_name': 'Pinecil Firmware',
|
'friendly_name': 'Pinecil Firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/lamarzocco/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/lamarzocco/icon.png',
|
||||||
'friendly_name': 'GS01234 Gateway firmware',
|
'friendly_name': 'GS01234 Gateway firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -62,6 +63,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/lamarzocco/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/lamarzocco/icon.png',
|
||||||
'friendly_name': 'GS01234 Machine firmware',
|
'friendly_name': 'GS01234 Machine firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/nextcloud/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/nextcloud/icon.png',
|
||||||
'friendly_name': 'my.nc_url.local None',
|
'friendly_name': 'my.nc_url.local None',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/smlight/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/smlight/icon.png',
|
||||||
'friendly_name': 'Mock Title Core firmware',
|
'friendly_name': 'Mock Title Core firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -95,6 +96,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/smlight/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/smlight/icon.png',
|
||||||
'friendly_name': 'Mock Title Zigbee firmware',
|
'friendly_name': 'Mock Title Zigbee firmware',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/teslemetry/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/teslemetry/icon.png',
|
||||||
'friendly_name': 'Test Update',
|
'friendly_name': 'Test Update',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -93,6 +94,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/teslemetry/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/teslemetry/icon.png',
|
||||||
'friendly_name': 'Test Update',
|
'friendly_name': 'Test Update',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/tessie/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/tessie/icon.png',
|
||||||
'friendly_name': 'Test Update',
|
'friendly_name': 'Test Update',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
||||||
'friendly_name': 'Device 1',
|
'friendly_name': 'Device 1',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -95,6 +96,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
||||||
'friendly_name': 'Device 2',
|
'friendly_name': 'Device 2',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -153,6 +155,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
||||||
'friendly_name': 'Device 1',
|
'friendly_name': 'Device 1',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
@ -211,6 +214,7 @@
|
|||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'auto_update': False,
|
'auto_update': False,
|
||||||
'device_class': 'firmware',
|
'device_class': 'firmware',
|
||||||
|
'display_precision': 0,
|
||||||
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
'entity_picture': 'https://brands.home-assistant.io/_/unifi/icon.png',
|
||||||
'friendly_name': 'Device 2',
|
'friendly_name': 'Device 2',
|
||||||
'in_progress': False,
|
'in_progress': False,
|
||||||
|
@ -5,53 +5,16 @@ from typing import Any
|
|||||||
|
|
||||||
from homeassistant.components.update import UpdateEntity
|
from homeassistant.components.update import UpdateEntity
|
||||||
|
|
||||||
from tests.common import MockEntity
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MockUpdateEntity(MockEntity, UpdateEntity):
|
class MockUpdateEntity(UpdateEntity):
|
||||||
"""Mock UpdateEntity class."""
|
"""Mock UpdateEntity class."""
|
||||||
|
|
||||||
@property
|
def __init__(self, **values: Any) -> None:
|
||||||
def auto_update(self) -> bool:
|
"""Initialize an entity."""
|
||||||
"""Indicate if the device or service has auto update enabled."""
|
for key, val in values.items():
|
||||||
return self._handle("auto_update")
|
setattr(self, f"_attr_{key}", val)
|
||||||
|
|
||||||
@property
|
|
||||||
def installed_version(self) -> str | None:
|
|
||||||
"""Version currently installed and in use."""
|
|
||||||
return self._handle("installed_version")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def in_progress(self) -> bool | int | None:
|
|
||||||
"""Update installation progress."""
|
|
||||||
return self._handle("in_progress")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def latest_version(self) -> str | None:
|
|
||||||
"""Latest version available for install."""
|
|
||||||
return self._handle("latest_version")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def release_summary(self) -> str | None:
|
|
||||||
"""Summary of the release notes or changelog."""
|
|
||||||
return self._handle("release_summary")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def release_url(self) -> str | None:
|
|
||||||
"""URL to the full release notes of the latest version available."""
|
|
||||||
return self._handle("release_url")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def title(self) -> str | None:
|
|
||||||
"""Title of the software."""
|
|
||||||
return self._handle("title")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def update_percentage(self) -> int | None:
|
|
||||||
"""Update installation progress."""
|
|
||||||
return self._handle("update_percentage")
|
|
||||||
|
|
||||||
def install(self, version: str | None, backup: bool, **kwargs: Any) -> None:
|
def install(self, version: str | None, backup: bool, **kwargs: Any) -> None:
|
||||||
"""Install an update."""
|
"""Install an update."""
|
||||||
@ -59,10 +22,10 @@ class MockUpdateEntity(MockEntity, UpdateEntity):
|
|||||||
_LOGGER.info("Creating backup before installing update")
|
_LOGGER.info("Creating backup before installing update")
|
||||||
|
|
||||||
if version is not None:
|
if version is not None:
|
||||||
self._values["installed_version"] = version
|
self._attr_installed_version = version
|
||||||
_LOGGER.info("Installed update with version: %s", version)
|
_LOGGER.info("Installed update with version: %s", version)
|
||||||
else:
|
else:
|
||||||
self._values["installed_version"] = self.latest_version
|
self._attr_installed_version = self.latest_version
|
||||||
_LOGGER.info("Installed latest update")
|
_LOGGER.info("Installed latest update")
|
||||||
|
|
||||||
def release_notes(self) -> str | None:
|
def release_notes(self) -> str | None:
|
||||||
|
@ -51,7 +51,7 @@ def mock_update_entities() -> list[MockUpdateEntity]:
|
|||||||
),
|
),
|
||||||
MockUpdateEntity(
|
MockUpdateEntity(
|
||||||
name="Update Already in Progress",
|
name="Update Already in Progress",
|
||||||
unique_id="update_already_in_progres",
|
unique_id="update_already_in_progress",
|
||||||
installed_version="1.0.0",
|
installed_version="1.0.0",
|
||||||
latest_version="1.0.1",
|
latest_version="1.0.1",
|
||||||
in_progress=True,
|
in_progress=True,
|
||||||
@ -59,6 +59,17 @@ def mock_update_entities() -> list[MockUpdateEntity]:
|
|||||||
| UpdateEntityFeature.PROGRESS,
|
| UpdateEntityFeature.PROGRESS,
|
||||||
update_percentage=50,
|
update_percentage=50,
|
||||||
),
|
),
|
||||||
|
MockUpdateEntity(
|
||||||
|
name="Update Already in Progress Float",
|
||||||
|
unique_id="update_already_in_progress_float",
|
||||||
|
installed_version="1.0.0",
|
||||||
|
latest_version="1.0.1",
|
||||||
|
in_progress=True,
|
||||||
|
supported_features=UpdateEntityFeature.INSTALL
|
||||||
|
| UpdateEntityFeature.PROGRESS,
|
||||||
|
update_percentage=0.25,
|
||||||
|
display_precision=2,
|
||||||
|
),
|
||||||
MockUpdateEntity(
|
MockUpdateEntity(
|
||||||
name="Update No Install",
|
name="Update No Install",
|
||||||
unique_id="no_install",
|
unique_id="no_install",
|
||||||
|
@ -18,6 +18,7 @@ from homeassistant.components.update import (
|
|||||||
)
|
)
|
||||||
from homeassistant.components.update.const import (
|
from homeassistant.components.update.const import (
|
||||||
ATTR_AUTO_UPDATE,
|
ATTR_AUTO_UPDATE,
|
||||||
|
ATTR_DISPLAY_PRECISION,
|
||||||
ATTR_IN_PROGRESS,
|
ATTR_IN_PROGRESS,
|
||||||
ATTR_INSTALLED_VERSION,
|
ATTR_INSTALLED_VERSION,
|
||||||
ATTR_LATEST_VERSION,
|
ATTR_LATEST_VERSION,
|
||||||
@ -92,6 +93,7 @@ async def test_update(hass: HomeAssistant) -> None:
|
|||||||
assert update.state == STATE_ON
|
assert update.state == STATE_ON
|
||||||
assert update.state_attributes == {
|
assert update.state_attributes == {
|
||||||
ATTR_AUTO_UPDATE: False,
|
ATTR_AUTO_UPDATE: False,
|
||||||
|
ATTR_DISPLAY_PRECISION: 0,
|
||||||
ATTR_INSTALLED_VERSION: "1.0.0",
|
ATTR_INSTALLED_VERSION: "1.0.0",
|
||||||
ATTR_IN_PROGRESS: False,
|
ATTR_IN_PROGRESS: False,
|
||||||
ATTR_LATEST_VERSION: "1.0.1",
|
ATTR_LATEST_VERSION: "1.0.1",
|
||||||
@ -546,10 +548,20 @@ async def test_entity_with_backup_support(
|
|||||||
assert "Installed update with version: 0.9.8" in caplog.text
|
assert "Installed update with version: 0.9.8" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("entity_id", "expected_display_precision", "expected_update_percentage"),
|
||||||
|
[
|
||||||
|
("update.update_already_in_progress", 0, 50),
|
||||||
|
("update.update_already_in_progress_float", 2, 0.25),
|
||||||
|
],
|
||||||
|
)
|
||||||
async def test_entity_already_in_progress(
|
async def test_entity_already_in_progress(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_update_entities: list[MockUpdateEntity],
|
mock_update_entities: list[MockUpdateEntity],
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
entity_id: str,
|
||||||
|
expected_display_precision: int,
|
||||||
|
expected_update_percentage: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test update install already in progress."""
|
"""Test update install already in progress."""
|
||||||
setup_test_component_platform(hass, DOMAIN, mock_update_entities)
|
setup_test_component_platform(hass, DOMAIN, mock_update_entities)
|
||||||
@ -557,13 +569,14 @@ async def test_entity_already_in_progress(
|
|||||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get("update.update_already_in_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_DISPLAY_PRECISION] == expected_display_precision
|
||||||
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
||||||
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
||||||
assert state.attributes[ATTR_IN_PROGRESS] is True
|
assert state.attributes[ATTR_IN_PROGRESS] is True
|
||||||
assert state.attributes[ATTR_UPDATE_PERCENTAGE] == 50
|
assert state.attributes[ATTR_UPDATE_PERCENTAGE] == expected_update_percentage
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
@ -572,7 +585,7 @@ async def test_entity_already_in_progress(
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_INSTALL,
|
SERVICE_INSTALL,
|
||||||
{ATTR_ENTITY_ID: "update.update_already_in_progress"},
|
{ATTR_ENTITY_ID: entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1056,6 +1069,7 @@ async def test_update_percentage_backwards_compatibility(
|
|||||||
|
|
||||||
expected_attributes = {
|
expected_attributes = {
|
||||||
ATTR_AUTO_UPDATE: False,
|
ATTR_AUTO_UPDATE: False,
|
||||||
|
ATTR_DISPLAY_PRECISION: 0,
|
||||||
ATTR_ENTITY_PICTURE: "https://brands.home-assistant.io/_/test/icon.png",
|
ATTR_ENTITY_PICTURE: "https://brands.home-assistant.io/_/test/icon.png",
|
||||||
ATTR_FRIENDLY_NAME: "legacy",
|
ATTR_FRIENDLY_NAME: "legacy",
|
||||||
ATTR_INSTALLED_VERSION: "1.0.0",
|
ATTR_INSTALLED_VERSION: "1.0.0",
|
||||||
|
@ -7,6 +7,7 @@ from datetime import timedelta
|
|||||||
from homeassistant.components.recorder import Recorder
|
from homeassistant.components.recorder import Recorder
|
||||||
from homeassistant.components.recorder.history import get_significant_states
|
from homeassistant.components.recorder.history import get_significant_states
|
||||||
from homeassistant.components.update.const import (
|
from homeassistant.components.update.const import (
|
||||||
|
ATTR_DISPLAY_PRECISION,
|
||||||
ATTR_IN_PROGRESS,
|
ATTR_IN_PROGRESS,
|
||||||
ATTR_INSTALLED_VERSION,
|
ATTR_INSTALLED_VERSION,
|
||||||
ATTR_RELEASE_SUMMARY,
|
ATTR_RELEASE_SUMMARY,
|
||||||
@ -35,6 +36,7 @@ async def test_exclude_attributes(
|
|||||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get("update.update_already_in_progress")
|
state = hass.states.get("update.update_already_in_progress")
|
||||||
|
assert state.attributes[ATTR_DISPLAY_PRECISION] == 0
|
||||||
assert state.attributes[ATTR_IN_PROGRESS] is True
|
assert state.attributes[ATTR_IN_PROGRESS] is True
|
||||||
assert state.attributes[ATTR_UPDATE_PERCENTAGE] == 50
|
assert state.attributes[ATTR_UPDATE_PERCENTAGE] == 50
|
||||||
assert (
|
assert (
|
||||||
@ -54,6 +56,7 @@ async def test_exclude_attributes(
|
|||||||
assert len(states) >= 1
|
assert len(states) >= 1
|
||||||
for entity_states in states.values():
|
for entity_states in states.values():
|
||||||
for state in entity_states:
|
for state in entity_states:
|
||||||
|
assert ATTR_DISPLAY_PRECISION not in state.attributes
|
||||||
assert ATTR_ENTITY_PICTURE not in state.attributes
|
assert ATTR_ENTITY_PICTURE not in state.attributes
|
||||||
assert ATTR_IN_PROGRESS not in state.attributes
|
assert ATTR_IN_PROGRESS not in state.attributes
|
||||||
assert ATTR_RELEASE_SUMMARY not in state.attributes
|
assert ATTR_RELEASE_SUMMARY not in state.attributes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user