diff --git a/homeassistant/components/qnap_qsw/update.py b/homeassistant/components/qnap_qsw/update.py index 70bd4afa880..38a963818d4 100644 --- a/homeassistant/components/qnap_qsw/update.py +++ b/homeassistant/components/qnap_qsw/update.py @@ -1,7 +1,7 @@ """Support for the QNAP QSW update.""" from __future__ import annotations -from typing import Final +from typing import Any, Final from aioqsw.const import ( QSD_DESCRIPTION, @@ -16,6 +16,7 @@ from homeassistant.components.update import ( UpdateDeviceClass, UpdateEntity, UpdateEntityDescription, + UpdateEntityFeature, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory @@ -51,6 +52,7 @@ async def async_setup_entry( class QswUpdate(QswFirmwareEntity, UpdateEntity): """Define a QNAP QSW update.""" + _attr_supported_features = UpdateEntityFeature.INSTALL entity_description: UpdateEntityDescription def __init__( @@ -87,3 +89,13 @@ class QswUpdate(QswFirmwareEntity, UpdateEntity): self._attr_release_summary = self.get_device_value( QSD_FIRMWARE_CHECK, QSD_DESCRIPTION ) + + async def async_install( + self, version: str | None, backup: bool, **kwargs: Any + ) -> None: + """Install an update.""" + await self.coordinator.async_refresh() + await self.coordinator.qsw.live_update() + + self._attr_installed_version = self.latest_version + self.async_write_ha_state() diff --git a/tests/components/qnap_qsw/test_update.py b/tests/components/qnap_qsw/test_update.py index 69f4a3d08b4..26b7157f64d 100644 --- a/tests/components/qnap_qsw/test_update.py +++ b/tests/components/qnap_qsw/test_update.py @@ -1,11 +1,32 @@ """The sensor tests for the QNAP QSW platform.""" -from aioqsw.const import API_RESULT, API_VERSION +from unittest.mock import patch -from homeassistant.const import STATE_OFF +from aioqsw.const import API_ERROR_CODE, API_ERROR_MESSAGE, API_RESULT, API_VERSION + +from homeassistant.components.update import ( + ATTR_BACKUP, + ATTR_IN_PROGRESS, + ATTR_INSTALLED_VERSION, + ATTR_LATEST_VERSION, + DOMAIN as UPDATE_DOMAIN, + SERVICE_INSTALL, +) +from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON from homeassistant.core import HomeAssistant -from .util import FIRMWARE_INFO_MOCK, FIRMWARE_UPDATE_CHECK_MOCK, async_init_integration +from .util import ( + FIRMWARE_INFO_MOCK, + FIRMWARE_UPDATE_CHECK_MOCK, + USERS_VERIFICATION_MOCK, + async_init_integration, +) + +FIRMWARE_UPDATE_LIVE_MOCK = { + API_ERROR_CODE: 200, + API_ERROR_MESSAGE: "OK", + API_RESULT: "None", +} async def test_qnap_qsw_update(hass: HomeAssistant) -> None: @@ -15,12 +36,50 @@ async def test_qnap_qsw_update(hass: HomeAssistant) -> None: update = hass.states.get("update.qsw_m408_4c_firmware_update") assert update is not None - assert update.state == STATE_OFF + assert update.state == STATE_ON assert ( - update.attributes.get("installed_version") + update.attributes[ATTR_INSTALLED_VERSION] == FIRMWARE_INFO_MOCK[API_RESULT][API_VERSION] ) assert ( - update.attributes.get("latest_version") + update.attributes[ATTR_LATEST_VERSION] == FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION] ) + assert update.attributes[ATTR_IN_PROGRESS] is False + + with patch( + "homeassistant.components.qnap_qsw.QnapQswApi.get_firmware_update_check", + return_value=FIRMWARE_UPDATE_CHECK_MOCK, + ) as mock_firmware_update_check, patch( + "homeassistant.components.qnap_qsw.QnapQswApi.get_users_verification", + return_value=USERS_VERIFICATION_MOCK, + ) as mock_users_verification, patch( + "homeassistant.components.qnap_qsw.QnapQswApi.post_firmware_update_live", + return_value=FIRMWARE_UPDATE_LIVE_MOCK, + ) as mock_firmware_update_live: + await hass.services.async_call( + UPDATE_DOMAIN, + SERVICE_INSTALL, + { + ATTR_BACKUP: False, + ATTR_ENTITY_ID: "update.qsw_m408_4c_firmware_update", + }, + blocking=True, + ) + + mock_firmware_update_check.assert_called_once() + mock_firmware_update_live.assert_called_once() + mock_users_verification.assert_called() + + update = hass.states.get("update.qsw_m408_4c_firmware_update") + assert update is not None + assert update.state == STATE_OFF + assert ( + update.attributes[ATTR_INSTALLED_VERSION] + == FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION] + ) + assert ( + update.attributes[ATTR_LATEST_VERSION] + == FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION] + ) + assert update.attributes[ATTR_IN_PROGRESS] is False diff --git a/tests/components/qnap_qsw/util.py b/tests/components/qnap_qsw/util.py index 5ae801283bc..b0dd5d5bf60 100644 --- a/tests/components/qnap_qsw/util.py +++ b/tests/components/qnap_qsw/util.py @@ -109,17 +109,17 @@ FIRMWARE_UPDATE_CHECK_MOCK = { API_ERROR_CODE: 200, API_ERROR_MESSAGE: "OK", API_RESULT: { - API_VERSION: "1.2.0", - API_NUMBER: "29649", - API_BUILD_NUMBER: "20220128", - API_DATE: "Fri, 28 Jan 2022 01:17:39 +0800", + API_VERSION: "1.3.0", + API_NUMBER: "527638", + API_BUILD_NUMBER: "20221123", + API_DATE: "Wed, 07, Dec 2022 16:30:00 +0800", API_DESCRIPTION: "", API_DOWNLOAD_URL: [ - "https://download.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img", - "https://eu1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img", - "https://us1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img", + "https://download.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img", + "https://eu1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img", + "https://us1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img", ], - API_NEWER: False, + API_NEWER: True, }, }