diff --git a/homeassistant/components/reolink/update.py b/homeassistant/components/reolink/update.py index 9b710c6576d..3c1e70612a7 100644 --- a/homeassistant/components/reolink/update.py +++ b/homeassistant/components/reolink/update.py @@ -137,8 +137,7 @@ class ReolinkUpdateEntity( async def async_release_notes(self) -> str | None: """Return the release notes.""" new_firmware = self._host.api.firmware_update_available(self._channel) - if not isinstance(new_firmware, NewSoftwareVersion): - return None + assert isinstance(new_firmware, NewSoftwareVersion) return ( "If the install button fails, download this" @@ -229,8 +228,7 @@ class ReolinkHostUpdateEntity( async def async_release_notes(self) -> str | None: """Return the release notes.""" new_firmware = self._host.api.firmware_update_available() - if not isinstance(new_firmware, NewSoftwareVersion): - return None + assert isinstance(new_firmware, NewSoftwareVersion) return ( "If the install button fails, download this" diff --git a/tests/components/reolink/conftest.py b/tests/components/reolink/conftest.py index be87aac9291..b0f599c28fb 100644 --- a/tests/components/reolink/conftest.py +++ b/tests/components/reolink/conftest.py @@ -35,6 +35,7 @@ TEST_PORT = 1234 TEST_NVR_NAME = "test_reolink_name" TEST_CAM_NAME = "test_reolink_cam" TEST_NVR_NAME2 = "test2_reolink_name" +TEST_CAM_NAME = "test_reolink_cam" TEST_USE_HTTPS = True TEST_HOST_MODEL = "RLN8-410" TEST_ITEM_NUMBER = "P000" diff --git a/tests/components/reolink/test_update.py b/tests/components/reolink/test_update.py new file mode 100644 index 00000000000..3ad10a11499 --- /dev/null +++ b/tests/components/reolink/test_update.py @@ -0,0 +1,131 @@ +"""Test the Reolink update platform.""" + +from unittest.mock import MagicMock, patch + +from freezegun.api import FrozenDateTimeFactory +import pytest +from reolink_aio.exceptions import ReolinkError +from reolink_aio.software_version import NewSoftwareVersion + +from homeassistant.components.reolink.update import POLL_AFTER_INSTALL +from homeassistant.components.update import DOMAIN as UPDATE_DOMAIN, SERVICE_INSTALL +from homeassistant.config_entries import ConfigEntryState +from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError + +from .conftest import TEST_CAM_NAME, TEST_NVR_NAME + +from tests.common import MockConfigEntry, async_fire_time_changed +from tests.typing import WebSocketGenerator + +TEST_DOWNLOAD_URL = "https://reolink.com/test" +TEST_RELEASE_NOTES = "bugfix 1, bugfix 2" + + +@pytest.mark.parametrize("entity_name", [TEST_NVR_NAME, TEST_CAM_NAME]) +async def test_no_update( + hass: HomeAssistant, + config_entry: MockConfigEntry, + reolink_connect: MagicMock, + entity_name: str, +) -> None: + """Test update state when no update available.""" + reolink_connect.camera_name.return_value = TEST_CAM_NAME + + with patch("homeassistant.components.reolink.PLATFORMS", [Platform.UPDATE]): + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.LOADED + + entity_id = f"{Platform.UPDATE}.{entity_name}_firmware" + assert hass.states.get(entity_id).state == STATE_OFF + + +@pytest.mark.parametrize("entity_name", [TEST_NVR_NAME, TEST_CAM_NAME]) +async def test_update_str( + hass: HomeAssistant, + config_entry: MockConfigEntry, + reolink_connect: MagicMock, + entity_name: str, +) -> None: + """Test update state when update available with string from API.""" + reolink_connect.camera_name.return_value = TEST_CAM_NAME + reolink_connect.firmware_update_available.return_value = "New firmware available" + + with patch("homeassistant.components.reolink.PLATFORMS", [Platform.UPDATE]): + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.LOADED + + entity_id = f"{Platform.UPDATE}.{entity_name}_firmware" + assert hass.states.get(entity_id).state == STATE_ON + + +@pytest.mark.parametrize("entity_name", [TEST_NVR_NAME, TEST_CAM_NAME]) +async def test_update_firm( + hass: HomeAssistant, + config_entry: MockConfigEntry, + reolink_connect: MagicMock, + hass_ws_client: WebSocketGenerator, + freezer: FrozenDateTimeFactory, + entity_name: str, +) -> None: + """Test update state when update available with firmware info from reolink.com.""" + reolink_connect.camera_name.return_value = TEST_CAM_NAME + new_firmware = NewSoftwareVersion( + version_string="v3.3.0.226_23031644", + download_url=TEST_DOWNLOAD_URL, + release_notes=TEST_RELEASE_NOTES, + ) + reolink_connect.firmware_update_available.return_value = new_firmware + + with patch("homeassistant.components.reolink.PLATFORMS", [Platform.UPDATE]): + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.LOADED + + entity_id = f"{Platform.UPDATE}.{entity_name}_firmware" + assert hass.states.get(entity_id).state == STATE_ON + + # release notes + client = await hass_ws_client(hass) + await hass.async_block_till_done() + + await client.send_json( + { + "id": 1, + "type": "update/release_notes", + "entity_id": entity_id, + } + ) + result = await client.receive_json() + assert TEST_DOWNLOAD_URL in result["result"] + assert TEST_RELEASE_NOTES in result["result"] + + # test install + await hass.services.async_call( + UPDATE_DOMAIN, + SERVICE_INSTALL, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + reolink_connect.update_firmware.assert_called() + + reolink_connect.update_firmware.side_effect = ReolinkError("Test error") + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + UPDATE_DOMAIN, + SERVICE_INSTALL, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + + # test _async_update_future + reolink_connect.camera_sw_version.return_value = "v3.3.0.226_23031644" + reolink_connect.firmware_update_available.return_value = False + freezer.tick(POLL_AFTER_INSTALL) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert hass.states.get(entity_id).state == STATE_OFF