758 lines
25 KiB
Python
758 lines
25 KiB
Python
"""The tests for the Update component."""
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant.components.update import (
|
|
ATTR_BACKUP,
|
|
ATTR_VERSION,
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
SERVICE_SKIP,
|
|
UpdateDeviceClass,
|
|
UpdateEntity,
|
|
UpdateEntityDescription,
|
|
)
|
|
from homeassistant.components.update.const import (
|
|
ATTR_AUTO_UPDATE,
|
|
ATTR_IN_PROGRESS,
|
|
ATTR_INSTALLED_VERSION,
|
|
ATTR_LATEST_VERSION,
|
|
ATTR_RELEASE_SUMMARY,
|
|
ATTR_RELEASE_URL,
|
|
ATTR_SKIPPED_VERSION,
|
|
ATTR_TITLE,
|
|
UpdateEntityFeature,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_ENTITY_ID,
|
|
CONF_PLATFORM,
|
|
STATE_OFF,
|
|
STATE_ON,
|
|
STATE_UNKNOWN,
|
|
EntityCategory,
|
|
)
|
|
from homeassistant.core import HomeAssistant, State, callback
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.event import async_track_state_change_event
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from tests.common import MockEntityPlatform, mock_restore_cache
|
|
from tests.typing import WebSocketGenerator
|
|
|
|
|
|
class MockUpdateEntity(UpdateEntity):
|
|
"""Mock UpdateEntity to use in tests."""
|
|
|
|
|
|
async def test_update(hass: HomeAssistant) -> None:
|
|
"""Test getting data from the mocked update entity."""
|
|
update = MockUpdateEntity()
|
|
update.hass = hass
|
|
|
|
update._attr_installed_version = "1.0.0"
|
|
update._attr_latest_version = "1.0.1"
|
|
update._attr_release_summary = "Summary"
|
|
update._attr_release_url = "https://example.com"
|
|
update._attr_title = "Title"
|
|
|
|
assert update.entity_category is EntityCategory.DIAGNOSTIC
|
|
assert update.entity_picture is None
|
|
assert update.installed_version == "1.0.0"
|
|
assert update.latest_version == "1.0.1"
|
|
assert update.release_summary == "Summary"
|
|
assert update.release_url == "https://example.com"
|
|
assert update.title == "Title"
|
|
assert update.in_progress is False
|
|
assert update.state == STATE_ON
|
|
assert update.state_attributes == {
|
|
ATTR_AUTO_UPDATE: False,
|
|
ATTR_INSTALLED_VERSION: "1.0.0",
|
|
ATTR_IN_PROGRESS: False,
|
|
ATTR_LATEST_VERSION: "1.0.1",
|
|
ATTR_RELEASE_SUMMARY: "Summary",
|
|
ATTR_RELEASE_URL: "https://example.com",
|
|
ATTR_SKIPPED_VERSION: None,
|
|
ATTR_TITLE: "Title",
|
|
}
|
|
|
|
# Test with platform
|
|
update.platform = MockEntityPlatform(hass)
|
|
assert (
|
|
update.entity_picture
|
|
== "https://brands.home-assistant.io/_/test_platform/icon.png"
|
|
)
|
|
|
|
# Test no update available
|
|
update._attr_installed_version = "1.0.0"
|
|
update._attr_latest_version = "1.0.0"
|
|
assert update.state is STATE_OFF
|
|
|
|
# Test state becomes unknown if installed version is unknown
|
|
update._attr_installed_version = None
|
|
update._attr_latest_version = "1.0.0"
|
|
assert update.state is None
|
|
|
|
# Test state becomes unknown if latest version is unknown
|
|
update._attr_installed_version = "1.0.0"
|
|
update._attr_latest_version = None
|
|
assert update.state is None
|
|
|
|
# Test no update if new version is not an update
|
|
update._attr_installed_version = "1.0.0"
|
|
update._attr_latest_version = "0.9.0"
|
|
assert update.state is STATE_OFF
|
|
|
|
# Test update if new version is not considered a valid version
|
|
update._attr_installed_version = "1.0.0"
|
|
update._attr_latest_version = "awesome_update"
|
|
assert update.state is STATE_ON
|
|
|
|
# Test entity category becomes config when its possible to install
|
|
update._attr_supported_features = UpdateEntityFeature.INSTALL
|
|
assert update.entity_category is EntityCategory.CONFIG
|
|
|
|
# UpdateEntityDescription was set
|
|
update._attr_supported_features = 0
|
|
update.entity_description = UpdateEntityDescription(key="F5 - Its very refreshing")
|
|
assert update.device_class is None
|
|
assert update.entity_category is EntityCategory.CONFIG
|
|
update.entity_description = UpdateEntityDescription(
|
|
key="F5 - Its very refreshing",
|
|
device_class=UpdateDeviceClass.FIRMWARE,
|
|
entity_category=None,
|
|
)
|
|
assert update.device_class is UpdateDeviceClass.FIRMWARE
|
|
assert update.entity_category is None
|
|
|
|
# Device class via attribute (override entity description)
|
|
update._attr_device_class = None
|
|
assert update.device_class is None
|
|
update._attr_device_class = UpdateDeviceClass.FIRMWARE
|
|
assert update.device_class is UpdateDeviceClass.FIRMWARE
|
|
|
|
# Entity Attribute via attribute (override entity description)
|
|
update._attr_entity_category = None
|
|
assert update.entity_category is None
|
|
update._attr_entity_category = EntityCategory.DIAGNOSTIC
|
|
assert update.entity_category is EntityCategory.DIAGNOSTIC
|
|
|
|
with pytest.raises(NotImplementedError):
|
|
await update.async_install(version=None, backup=True)
|
|
|
|
with pytest.raises(NotImplementedError):
|
|
update.install(version=None, backup=False)
|
|
|
|
update.install = MagicMock()
|
|
await update.async_install(version="1.0.1", backup=True)
|
|
|
|
assert update.install.called
|
|
assert update.install.call_args[0][0] == "1.0.1"
|
|
assert update.install.call_args[0][1] is True
|
|
|
|
|
|
async def test_entity_with_no_install(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
) -> None:
|
|
"""Test entity with no updates."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
# Update is available
|
|
state = hass.states.get("update.update_no_install")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
|
|
# Should not be able to install as the entity doesn't support that
|
|
with pytest.raises(HomeAssistantError):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_no_install"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Nothing changed
|
|
state = hass.states.get("update.update_no_install")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
|
|
# We can mark the update as skipped
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_SKIP,
|
|
{ATTR_ENTITY_ID: "update.update_no_install"},
|
|
blocking=True,
|
|
)
|
|
|
|
state = hass.states.get("update.update_no_install")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] == "1.0.1"
|
|
|
|
# We can clear the skipped marker again
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
"clear_skipped",
|
|
{ATTR_ENTITY_ID: "update.update_no_install"},
|
|
blocking=True,
|
|
)
|
|
|
|
state = hass.states.get("update.update_no_install")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
|
|
|
|
async def test_entity_with_no_updates(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
) -> None:
|
|
"""Test entity with no updates."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
# No update available
|
|
state = hass.states.get("update.no_update")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.0"
|
|
|
|
# Should not be able to skip when there is no update available
|
|
with pytest.raises(HomeAssistantError, match="No update available to skip for"):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_SKIP,
|
|
{ATTR_ENTITY_ID: "update.no_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Should not be able to install an update when there is no update available
|
|
with pytest.raises(HomeAssistantError, match="No update available for"):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.no_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Updating to a specific version is not supported by this entity
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Installing a specific version is not supported for",
|
|
):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_VERSION: "0.9.0", ATTR_ENTITY_ID: "update.no_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
async def test_entity_with_auto_update(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity that has auto update feature."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.update_with_auto_update")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
|
|
# Should be able to manually install an update even if it can auto update
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_with_auto_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Should not be able to skip the update
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Skipping update is not supported for update.update_with_auto_update",
|
|
):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_SKIP,
|
|
{ATTR_ENTITY_ID: "update.update_with_auto_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Should not be able to clear a skipped the update
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Clearing skipped update is not supported for update.update_with_auto_update",
|
|
):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
"clear_skipped",
|
|
{ATTR_ENTITY_ID: "update.update_with_auto_update"},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
async def test_entity_with_updates_available(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test basic update entity with updates available."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
# Entity has an update available
|
|
state = hass.states.get("update.update_available")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
|
|
# Skip skip the update
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_SKIP,
|
|
{ATTR_ENTITY_ID: "update.update_available"},
|
|
blocking=True,
|
|
)
|
|
|
|
# The state should have changed to off, skipped version should be set
|
|
state = hass.states.get("update.update_available")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] == "1.0.1"
|
|
|
|
# Even though skipped, we can still update if we want to
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_available"},
|
|
blocking=True,
|
|
)
|
|
|
|
# The state should have changed to off, skipped version should be set
|
|
state = hass.states.get("update.update_available")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
assert "Installed latest update" in caplog.text
|
|
|
|
|
|
async def test_entity_with_unknown_version(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity that has an unknown version."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.update_unknown")
|
|
assert state
|
|
assert state.state == STATE_UNKNOWN
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] is None
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] is None
|
|
|
|
# Should not be able to install an update when there is no update available
|
|
with pytest.raises(HomeAssistantError, match="No update available for"):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_unknown"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Should not be to skip the update
|
|
with pytest.raises(HomeAssistantError, match="Cannot skip an unknown version for"):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_SKIP,
|
|
{ATTR_ENTITY_ID: "update.update_unknown"},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
async def test_entity_with_specific_version(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity that support specific version."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.update_specific_version")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.0"
|
|
|
|
# Update to a specific version
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_VERSION: "0.9.9", ATTR_ENTITY_ID: "update.update_specific_version"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Version has changed, state should be on as there is an update available
|
|
state = hass.states.get("update.update_specific_version")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "0.9.9"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.0"
|
|
assert "Installed update with version: 0.9.9" in caplog.text
|
|
|
|
# Update back to the latest version
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_specific_version"},
|
|
blocking=True,
|
|
)
|
|
|
|
state = hass.states.get("update.update_specific_version")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.0"
|
|
assert "Installed latest update" in caplog.text
|
|
|
|
# This entity does not support doing a backup before upgrade
|
|
with pytest.raises(HomeAssistantError, match="Backup is not supported for"):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{
|
|
ATTR_VERSION: "0.9.9",
|
|
ATTR_BACKUP: True,
|
|
ATTR_ENTITY_ID: "update.update_specific_version",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
async def test_entity_with_backup_support(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity with backup support."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
# This entity support backing up before install the update
|
|
state = hass.states.get("update.update_backup")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
|
|
# Without a backup
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{
|
|
ATTR_BACKUP: False,
|
|
ATTR_ENTITY_ID: "update.update_backup",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
state = hass.states.get("update.update_backup")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert "Creating backup before installing update" not in caplog.text
|
|
assert "Installed latest update" in caplog.text
|
|
|
|
# Specific version, do create a backup this time
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{
|
|
ATTR_BACKUP: True,
|
|
ATTR_VERSION: "0.9.8",
|
|
ATTR_ENTITY_ID: "update.update_backup",
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
# This entity support backing up before install the update
|
|
state = hass.states.get("update.update_backup")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "0.9.8"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert "Creating backup before installing update" in caplog.text
|
|
assert "Installed update with version: 0.9.8" in caplog.text
|
|
|
|
|
|
async def test_entity_already_in_progress(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update install already in progress."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.update_already_in_progress")
|
|
assert state
|
|
assert state.state == STATE_ON
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_IN_PROGRESS] == 50
|
|
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Update installation already in progress for",
|
|
):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_already_in_progress"},
|
|
blocking=True,
|
|
)
|
|
|
|
|
|
async def test_entity_without_progress_support(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity without progress support.
|
|
|
|
In that case, progress is still handled by Home Assistant.
|
|
"""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
events = []
|
|
async_track_state_change_event(
|
|
hass, "update.update_available", callback(lambda event: events.append(event))
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_available"},
|
|
blocking=True,
|
|
)
|
|
|
|
assert len(events) == 2
|
|
assert events[0].data.get("old_state").attributes[ATTR_IN_PROGRESS] is False
|
|
assert events[0].data.get("old_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert events[0].data.get("new_state").attributes[ATTR_IN_PROGRESS] is True
|
|
assert events[0].data.get("new_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
|
|
assert events[1].data.get("old_state").attributes[ATTR_IN_PROGRESS] is True
|
|
assert events[1].data.get("old_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert events[1].data.get("new_state").attributes[ATTR_IN_PROGRESS] is False
|
|
assert events[1].data.get("new_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.1"
|
|
|
|
|
|
async def test_entity_without_progress_support_raising(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test update entity without progress support that raises during install.
|
|
|
|
In that case, progress is still handled by Home Assistant.
|
|
"""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
events = []
|
|
async_track_state_change_event(
|
|
hass, "update.update_available", callback(lambda event: events.append(event))
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.update.UpdateEntity.async_install",
|
|
side_effect=RuntimeError,
|
|
), pytest.raises(RuntimeError):
|
|
await hass.services.async_call(
|
|
DOMAIN,
|
|
SERVICE_INSTALL,
|
|
{ATTR_ENTITY_ID: "update.update_available"},
|
|
blocking=True,
|
|
)
|
|
|
|
assert len(events) == 2
|
|
assert events[0].data.get("old_state").attributes[ATTR_IN_PROGRESS] is False
|
|
assert events[0].data.get("old_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert events[0].data.get("new_state").attributes[ATTR_IN_PROGRESS] is True
|
|
assert events[0].data.get("new_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
|
|
assert events[1].data.get("old_state").attributes[ATTR_IN_PROGRESS] is True
|
|
assert events[1].data.get("old_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert events[1].data.get("new_state").attributes[ATTR_IN_PROGRESS] is False
|
|
assert events[1].data.get("new_state").attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
|
|
|
|
async def test_restore_state(
|
|
hass: HomeAssistant, enable_custom_integrations: None
|
|
) -> None:
|
|
"""Test we restore skipped version state."""
|
|
mock_restore_cache(
|
|
hass,
|
|
(
|
|
State(
|
|
"update.update_available",
|
|
STATE_ON, # Incorrect, but helps checking if it is ignored
|
|
{
|
|
ATTR_SKIPPED_VERSION: "1.0.1",
|
|
},
|
|
),
|
|
),
|
|
)
|
|
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("update.update_available")
|
|
assert state
|
|
assert state.state == STATE_OFF
|
|
assert state.attributes[ATTR_INSTALLED_VERSION] == "1.0.0"
|
|
assert state.attributes[ATTR_LATEST_VERSION] == "1.0.1"
|
|
assert state.attributes[ATTR_SKIPPED_VERSION] == "1.0.1"
|
|
|
|
|
|
async def test_release_notes(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
hass_ws_client: WebSocketGenerator,
|
|
) -> None:
|
|
"""Test getting the release notes over the websocket connection."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
client = await hass_ws_client(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
await client.send_json(
|
|
{
|
|
"id": 1,
|
|
"type": "update/release_notes",
|
|
"entity_id": "update.update_with_release_notes",
|
|
}
|
|
)
|
|
result = await client.receive_json()
|
|
assert result["result"] == "Release notes"
|
|
|
|
|
|
async def test_release_notes_entity_not_found(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
hass_ws_client: WebSocketGenerator,
|
|
) -> None:
|
|
"""Test getting the release notes for not found entity."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
client = await hass_ws_client(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
await client.send_json(
|
|
{
|
|
"id": 1,
|
|
"type": "update/release_notes",
|
|
"entity_id": "update.entity_not_found",
|
|
}
|
|
)
|
|
result = await client.receive_json()
|
|
assert result["error"]["code"] == "not_found"
|
|
assert result["error"]["message"] == "Entity not found"
|
|
|
|
|
|
async def test_release_notes_entity_does_not_support_release_notes(
|
|
hass: HomeAssistant,
|
|
enable_custom_integrations: None,
|
|
hass_ws_client: WebSocketGenerator,
|
|
) -> None:
|
|
"""Test getting the release notes for entity that does not support release notes."""
|
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
|
platform.init()
|
|
|
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
|
|
await hass.async_block_till_done()
|
|
|
|
client = await hass_ws_client(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
await client.send_json(
|
|
{
|
|
"id": 1,
|
|
"type": "update/release_notes",
|
|
"entity_id": "update.update_available",
|
|
}
|
|
)
|
|
result = await client.receive_json()
|
|
assert result["error"]["code"] == "not_supported"
|
|
assert result["error"]["message"] == "Entity does not support release notes"
|