diff --git a/homeassistant/components/unifiprotect/binary_sensor.py b/homeassistant/components/unifiprotect/binary_sensor.py index 66c1a0a4e33..f779fc7a1ad 100644 --- a/homeassistant/components/unifiprotect/binary_sensor.py +++ b/homeassistant/components/unifiprotect/binary_sensor.py @@ -458,6 +458,7 @@ EVENT_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = ( name="Package Detected", icon="mdi:package-variant-closed", ufp_value="is_package_currently_detected", + entity_registry_enabled_default=False, ufp_required_field="can_detect_package", ufp_enabled="is_package_detection_on", ufp_event_obj="last_package_detect_event", diff --git a/homeassistant/components/unifiprotect/migrate.py b/homeassistant/components/unifiprotect/migrate.py index 601220bc4f0..1fbf8bab8e2 100644 --- a/homeassistant/components/unifiprotect/migrate.py +++ b/homeassistant/components/unifiprotect/migrate.py @@ -2,19 +2,103 @@ from __future__ import annotations +from itertools import chain import logging from pyunifiprotect import ProtectApiClient -from pyunifiprotect.data import NVR, Bootstrap, ProtectAdoptableDeviceModel +from pyunifiprotect.data import Bootstrap +from typing_extensions import TypedDict +from homeassistant.components.automation import automations_with_entity +from homeassistant.components.script import scripts_with_entity from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform -from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity_registry as er +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import entity_registry as er, issue_registry as ir +from homeassistant.helpers.issue_registry import IssueSeverity + +from .const import DOMAIN _LOGGER = logging.getLogger(__name__) +class EntityRef(TypedDict): + """Entity ref parameter variable.""" + + id: str + platform: Platform + + +class EntityUsage(TypedDict): + """Entity usages response variable.""" + + automations: dict[str, list[str]] + scripts: dict[str, list[str]] + + +@callback +def check_if_used( + hass: HomeAssistant, entry: ConfigEntry, entities: dict[str, EntityRef] +) -> dict[str, EntityUsage]: + """Check for usages of entities and return them.""" + + entity_registry = er.async_get(hass) + refs: dict[str, EntityUsage] = { + ref: {"automations": {}, "scripts": {}} for ref in entities + } + + for entity in er.async_entries_for_config_entry(entity_registry, entry.entry_id): + for ref_id, ref in entities.items(): + if ( + entity.domain == ref["platform"] + and entity.disabled_by is None + and ref["id"] in entity.unique_id + ): + entity_automations = automations_with_entity(hass, entity.entity_id) + entity_scripts = scripts_with_entity(hass, entity.entity_id) + if entity_automations: + refs[ref_id]["automations"][entity.entity_id] = entity_automations + if entity_scripts: + refs[ref_id]["scripts"][entity.entity_id] = entity_scripts + + return refs + + +@callback +def create_repair_if_used( + hass: HomeAssistant, + entry: ConfigEntry, + breaks_in: str, + entities: dict[str, EntityRef], +) -> None: + """Create repairs for used entities that are deprecated.""" + + usages = check_if_used(hass, entry, entities) + for ref_id, refs in usages.items(): + issue_id = f"deprecate_{ref_id}" + automations = refs["automations"] + scripts = refs["scripts"] + if automations or scripts: + items = sorted( + set(chain.from_iterable(chain(automations.values(), scripts.values()))) + ) + ir.async_create_issue( + hass, + DOMAIN, + issue_id, + is_fixable=False, + breaks_in_ha_version=breaks_in, + severity=IssueSeverity.WARNING, + translation_key=issue_id, + translation_placeholders={ + "items": "* `" + "`\n* `".join(items) + "`\n" + }, + ) + else: + _LOGGER.debug("No found usages of %s", ref_id) + ir.async_delete_issue(hass, DOMAIN, issue_id) + + async def async_migrate_data( hass: HomeAssistant, entry: ConfigEntry, @@ -23,132 +107,32 @@ async def async_migrate_data( ) -> None: """Run all valid UniFi Protect data migrations.""" - _LOGGER.debug("Start Migrate: async_migrate_buttons") - await async_migrate_buttons(hass, entry, protect, bootstrap) - _LOGGER.debug("Completed Migrate: async_migrate_buttons") - - _LOGGER.debug("Start Migrate: async_migrate_device_ids") - await async_migrate_device_ids(hass, entry, protect, bootstrap) - _LOGGER.debug("Completed Migrate: async_migrate_device_ids") + _LOGGER.debug("Start Migrate: async_deprecate_hdr_package") + async_deprecate_hdr_package(hass, entry) + _LOGGER.debug("Completed Migrate: async_deprecate_hdr_package") -async def async_migrate_buttons( - hass: HomeAssistant, - entry: ConfigEntry, - protect: ProtectApiClient, - bootstrap: Bootstrap, -) -> None: - """Migrate existing Reboot button unique IDs from {device_id} to {deivce_id}_reboot. +@callback +def async_deprecate_hdr_package(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Check for usages of hdr_mode switch and package sensor and raise repair if it is used. - This allows for additional types of buttons that are outside of just a reboot button. + UniFi Protect v3.0.22 changed how HDR works so it is no longer a simple on/off toggle. There is + Always On, Always Off and Auto. So it has been migrated to a select. The old switch is now deprecated. - Added in 2022.6.0. + Additionally, the Package sensor is no longer functional due to how events work so a repair to notify users. + + Added in 2024.4.0 """ - registry = er.async_get(hass) - to_migrate = [] - for entity in er.async_entries_for_config_entry(registry, entry.entry_id): - if entity.domain == Platform.BUTTON and "_" not in entity.unique_id: - _LOGGER.debug("Button %s needs migration", entity.entity_id) - to_migrate.append(entity) - - if len(to_migrate) == 0: - _LOGGER.debug("No button entities need migration") - return - - count = 0 - for button in to_migrate: - device = bootstrap.get_device_from_id(button.unique_id) - if device is None: - continue - - new_unique_id = f"{device.id}_reboot" - _LOGGER.debug( - "Migrating entity %s (old unique_id: %s, new unique_id: %s)", - button.entity_id, - button.unique_id, - new_unique_id, - ) - try: - registry.async_update_entity(button.entity_id, new_unique_id=new_unique_id) - except ValueError: - _LOGGER.warning( - "Could not migrate entity %s (old unique_id: %s, new unique_id: %s)", - button.entity_id, - button.unique_id, - new_unique_id, - ) - else: - count += 1 - - if count < len(to_migrate): - _LOGGER.warning("Failed to migate %s reboot buttons", len(to_migrate) - count) - - -async def async_migrate_device_ids( - hass: HomeAssistant, - entry: ConfigEntry, - protect: ProtectApiClient, - bootstrap: Bootstrap, -) -> None: - """Migrate unique IDs from {device_id}_{name} format to {mac}_{name} format. - - This makes devices persist better with in HA. Anything a device is unadopted/readopted or - the Protect instance has to rebuild the disk array, the device IDs of Protect devices - can change. This causes a ton of orphaned entities and loss of historical data. MAC - addresses are the one persistent identifier a device has that does not change. - - Added in 2022.7.0. - """ - - registry = er.async_get(hass) - to_migrate = [] - for entity in er.async_entries_for_config_entry(registry, entry.entry_id): - parts = entity.unique_id.split("_") - # device ID = 24 characters, MAC = 12 - if len(parts[0]) == 24: - _LOGGER.debug("Entity %s needs migration", entity.entity_id) - to_migrate.append(entity) - - if len(to_migrate) == 0: - _LOGGER.debug("No entities need migration to MAC address ID") - return - - count = 0 - for entity in to_migrate: - parts = entity.unique_id.split("_") - if parts[0] == bootstrap.nvr.id: - device: NVR | ProtectAdoptableDeviceModel | None = bootstrap.nvr - else: - device = bootstrap.get_device_from_id(parts[0]) - - if device is None: - continue - - new_unique_id = device.mac - if len(parts) > 1: - new_unique_id = f"{device.mac}_{'_'.join(parts[1:])}" - _LOGGER.debug( - "Migrating entity %s (old unique_id: %s, new unique_id: %s)", - entity.entity_id, - entity.unique_id, - new_unique_id, - ) - try: - registry.async_update_entity(entity.entity_id, new_unique_id=new_unique_id) - except ValueError as err: - _LOGGER.warning( - ( - "Could not migrate entity %s (old unique_id: %s, new unique_id:" - " %s): %s" - ), - entity.entity_id, - entity.unique_id, - new_unique_id, - err, - ) - else: - count += 1 - - if count < len(to_migrate): - _LOGGER.warning("Failed to migrate %s entities", len(to_migrate) - count) + create_repair_if_used( + hass, + entry, + "2024.10.0", + { + "hdr_switch": {"id": "hdr_mode", "platform": Platform.SWITCH}, + "package_sensor": { + "id": "smart_obj_package", + "platform": Platform.BINARY_SENSOR, + }, + }, + ) diff --git a/homeassistant/components/unifiprotect/strings.json b/homeassistant/components/unifiprotect/strings.json index b783bdf1a2c..0b01c8f220c 100644 --- a/homeassistant/components/unifiprotect/strings.json +++ b/homeassistant/components/unifiprotect/strings.json @@ -90,6 +90,14 @@ } } } + }, + "deprecate_hdr_switch": { + "title": "HDR Mode Switch Deprecated", + "description": "UniFi Protect v3 added a new state for HDR (auto). As a result, the HDR Mode Switch has been replaced with an HDR Mode Select, and it is deprecated.\n\nBelow are the detected automations or scripts that use one or more of the deprecated entities:\n{items}\nThe above list may be incomplete and it does not include any template usages inside of dashboards. Please update any templates, automations or scripts accordingly." + }, + "deprecate_package_sensor": { + "title": "Package Event Sensor Deprecated", + "description": "The package event sensor never tripped because of the way events are reported in UniFi Protect. As a result, the sensor is deprecated and will be removed.\n\nBelow are the detected automations or scripts that use one or more of the deprecated entities:\n{items}\nThe above list may be incomplete and it does not include any template usages inside of dashboards. Please update any templates, automations or scripts accordingly." } }, "entity": { diff --git a/tests/components/unifiprotect/fixtures/sample_nvr.json b/tests/components/unifiprotect/fixtures/sample_nvr.json index 8777e3ce945..13e93a8c2e7 100644 --- a/tests/components/unifiprotect/fixtures/sample_nvr.json +++ b/tests/components/unifiprotect/fixtures/sample_nvr.json @@ -5,7 +5,7 @@ "canAutoUpdate": true, "isStatsGatheringEnabled": true, "timezone": "America/New_York", - "version": "1.21.0-beta.2", + "version": "2.2.6", "ucoreVersion": "2.3.26", "firmwareVersion": "2.3.10", "uiVersion": null, @@ -40,7 +40,7 @@ "enableStatsReporting": false, "isSshEnabled": false, "errorCode": null, - "releaseChannel": "beta", + "releaseChannel": "release", "ssoChannel": null, "hosts": ["192.168.216.198"], "enableBridgeAutoAdoption": true, diff --git a/tests/components/unifiprotect/test_migrate.py b/tests/components/unifiprotect/test_migrate.py index 88d66c819bc..7e736c39e6a 100644 --- a/tests/components/unifiprotect/test_migrate.py +++ b/tests/components/unifiprotect/test_migrate.py @@ -2,238 +2,225 @@ from __future__ import annotations -from unittest.mock import AsyncMock +from unittest.mock import patch -from pyunifiprotect.data import Light -from pyunifiprotect.exceptions import NvrError +from pyunifiprotect.data import Camera +from homeassistant.components.automation import DOMAIN as AUTOMATION_DOMAIN +from homeassistant.components.repairs.issue_handler import ( + async_process_repairs_platforms, +) +from homeassistant.components.script import DOMAIN as SCRIPT_DOMAIN from homeassistant.components.unifiprotect.const import DOMAIN -from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import Platform +from homeassistant.const import SERVICE_RELOAD, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er +from homeassistant.setup import async_setup_component -from .utils import ( - MockUFPFixture, - generate_random_ids, - init_entry, - regenerate_device_ids, -) +from .utils import MockUFPFixture, init_entry + +from tests.typing import WebSocketGenerator -async def test_migrate_reboot_button( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light -) -> None: - """Test migrating unique ID of reboot button.""" +async def test_deprecated_entity( + hass: HomeAssistant, ufp: MockUFPFixture, hass_ws_client, doorbell: Camera +): + """Test Deprecate entity repair does not exist by default (new installs).""" - light1 = light.copy() - light1.name = "Test Light 1" - regenerate_device_ids(light1) + await init_entry(hass, ufp, [doorbell]) - light2 = light.copy() - light2.name = "Test Light 2" - regenerate_device_ids(light2) + await async_process_repairs_platforms(hass) + ws_client = await hass_ws_client(hass) + + await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() + + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is None + + +async def test_deprecated_entity_no_automations( + hass: HomeAssistant, ufp: MockUFPFixture, hass_ws_client, doorbell: Camera +): + """Test Deprecate entity repair exists for existing installs.""" registry = er.async_get(hass) registry.async_get_or_create( - Platform.BUTTON, DOMAIN, light1.id, config_entry=ufp.entry - ) - registry.async_get_or_create( - Platform.BUTTON, + Platform.SWITCH, DOMAIN, - f"{light2.mac}_reboot", + f"{doorbell.mac}_hdr_mode", config_entry=ufp.entry, ) - ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) - await init_entry(hass, ufp, [light1, light2], regenerate_ids=False) + await init_entry(hass, ufp, [doorbell]) - assert ufp.entry.state == ConfigEntryState.LOADED - assert ufp.api.update.called - assert ufp.entry.unique_id == ufp.api.bootstrap.nvr.mac + await async_process_repairs_platforms(hass) + ws_client = await hass_ws_client(hass) - buttons = [ - entity - for entity in er.async_entries_for_config_entry(registry, ufp.entry.entry_id) - if entity.domain == Platform.BUTTON.value - ] - assert len(buttons) == 4 + await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() - assert registry.async_get(f"{Platform.BUTTON}.test_light_1_reboot_device") is None - assert registry.async_get(f"{Platform.BUTTON}.test_light_1_reboot_device_2") is None - light = registry.async_get(f"{Platform.BUTTON}.unifiprotect_{light1.id.lower()}") - assert light is not None - assert light.unique_id == f"{light1.mac}_reboot" + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is None - assert registry.async_get(f"{Platform.BUTTON}.test_light_2_reboot_device") is None - assert registry.async_get(f"{Platform.BUTTON}.test_light_2_reboot_device_2") is None - light = registry.async_get( - f"{Platform.BUTTON}.unifiprotect_{light2.mac.lower()}_reboot" + +async def _load_automation(hass: HomeAssistant, entity_id: str): + assert await async_setup_component( + hass, + AUTOMATION_DOMAIN, + { + AUTOMATION_DOMAIN: [ + { + "alias": "test1", + "trigger": [ + {"platform": "state", "entity_id": entity_id}, + { + "platform": "event", + "event_type": "state_changed", + "event_data": {"entity_id": entity_id}, + }, + ], + "condition": { + "condition": "state", + "entity_id": entity_id, + "state": "on", + }, + "action": [ + { + "service": "test.script", + "data": {"entity_id": entity_id}, + }, + ], + }, + ] + }, ) - assert light is not None - assert light.unique_id == f"{light2.mac}_reboot" -async def test_migrate_nvr_mac( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light +async def test_deprecate_entity_automation( + hass: HomeAssistant, + ufp: MockUFPFixture, + hass_ws_client: WebSocketGenerator, + doorbell: Camera, ) -> None: - """Test migrating unique ID of NVR to use MAC address.""" - - light1 = light.copy() - light1.name = "Test Light 1" - regenerate_device_ids(light1) - - light2 = light.copy() - light2.name = "Test Light 2" - regenerate_device_ids(light2) - - nvr = ufp.api.bootstrap.nvr - regenerate_device_ids(nvr) - registry = er.async_get(hass) - registry.async_get_or_create( - Platform.SENSOR, - DOMAIN, - f"{nvr.id}_storage_utilization", - config_entry=ufp.entry, - ) - - ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) - await init_entry(hass, ufp, [light1, light2], regenerate_ids=False) - - assert ufp.entry.state == ConfigEntryState.LOADED - assert ufp.api.update.called - assert ufp.entry.unique_id == ufp.api.bootstrap.nvr.mac - - assert registry.async_get(f"{Platform.SENSOR}.{DOMAIN}_storage_utilization") is None - assert ( - registry.async_get(f"{Platform.SENSOR}.{DOMAIN}_storage_utilization_2") is None - ) - sensor = registry.async_get( - f"{Platform.SENSOR}.{DOMAIN}_{nvr.id}_storage_utilization" - ) - assert sensor is not None - assert sensor.unique_id == f"{nvr.mac}_storage_utilization" - - -async def test_migrate_reboot_button_no_device( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light -) -> None: - """Test migrating unique ID of reboot button if UniFi Protect device ID changed.""" - - light2_id, _ = generate_random_ids() + """Test Deprecate entity repair exists for existing installs.""" registry = er.async_get(hass) - registry.async_get_or_create( - Platform.BUTTON, DOMAIN, light2_id, config_entry=ufp.entry + entry = registry.async_get_or_create( + Platform.SWITCH, + DOMAIN, + f"{doorbell.mac}_hdr_mode", + config_entry=ufp.entry, + ) + await _load_automation(hass, entry.entity_id) + await init_entry(hass, ufp, [doorbell]) + + await async_process_repairs_platforms(hass) + ws_client = await hass_ws_client(hass) + + await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() + + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is not None + + with patch( + "homeassistant.config.load_yaml_config_file", + autospec=True, + return_value={AUTOMATION_DOMAIN: []}, + ): + await hass.services.async_call(AUTOMATION_DOMAIN, SERVICE_RELOAD, blocking=True) + + await hass.config_entries.async_reload(ufp.entry.entry_id) + await hass.async_block_till_done() + + await ws_client.send_json({"id": 2, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() + + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is None + + +async def _load_script(hass: HomeAssistant, entity_id: str): + assert await async_setup_component( + hass, + SCRIPT_DOMAIN, + { + SCRIPT_DOMAIN: { + "test": { + "sequence": { + "service": "test.script", + "data": {"entity_id": entity_id}, + } + } + }, + }, ) - ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) - await init_entry(hass, ufp, [light], regenerate_ids=False) - assert ufp.entry.state == ConfigEntryState.LOADED - assert ufp.api.update.called - assert ufp.entry.unique_id == ufp.api.bootstrap.nvr.mac - - buttons = [ - entity - for entity in er.async_entries_for_config_entry(registry, ufp.entry.entry_id) - if entity.domain == Platform.BUTTON.value - ] - assert len(buttons) == 3 - - entity = registry.async_get(f"{Platform.BUTTON}.unifiprotect_{light2_id.lower()}") - assert entity is not None - assert entity.unique_id == light2_id - - -async def test_migrate_reboot_button_fail( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light +async def test_deprecate_entity_script( + hass: HomeAssistant, + ufp: MockUFPFixture, + hass_ws_client: WebSocketGenerator, + doorbell: Camera, ) -> None: - """Test migrating unique ID of reboot button.""" + """Test Deprecate entity repair exists for existing installs.""" registry = er.async_get(hass) - registry.async_get_or_create( - Platform.BUTTON, + entry = registry.async_get_or_create( + Platform.SWITCH, DOMAIN, - light.id, + f"{doorbell.mac}_hdr_mode", config_entry=ufp.entry, - suggested_object_id=light.display_name, - ) - registry.async_get_or_create( - Platform.BUTTON, - DOMAIN, - f"{light.id}_reboot", - config_entry=ufp.entry, - suggested_object_id=light.display_name, ) + await _load_script(hass, entry.entity_id) + await init_entry(hass, ufp, [doorbell]) - ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) - await init_entry(hass, ufp, [light], regenerate_ids=False) + await async_process_repairs_platforms(hass) + ws_client = await hass_ws_client(hass) - assert ufp.entry.state == ConfigEntryState.LOADED - assert ufp.api.update.called - assert ufp.entry.unique_id == ufp.api.bootstrap.nvr.mac + await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() - entity = registry.async_get(f"{Platform.BUTTON}.test_light") - assert entity is not None - assert entity.unique_id == f"{light.mac}" + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is not None + with patch( + "homeassistant.config.load_yaml_config_file", + autospec=True, + return_value={SCRIPT_DOMAIN: {}}, + ): + await hass.services.async_call(SCRIPT_DOMAIN, SERVICE_RELOAD, blocking=True) -async def test_migrate_device_mac_button_fail( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light -) -> None: - """Test migrating unique ID to MAC format.""" + await hass.config_entries.async_reload(ufp.entry.entry_id) + await hass.async_block_till_done() - registry = er.async_get(hass) - registry.async_get_or_create( - Platform.BUTTON, - DOMAIN, - f"{light.id}_reboot", - config_entry=ufp.entry, - suggested_object_id=light.display_name, - ) - registry.async_get_or_create( - Platform.BUTTON, - DOMAIN, - f"{light.mac}_reboot", - config_entry=ufp.entry, - suggested_object_id=light.display_name, - ) + await ws_client.send_json({"id": 2, "type": "repairs/list_issues"}) + msg = await ws_client.receive_json() - ufp.api.get_bootstrap = AsyncMock(return_value=ufp.api.bootstrap) - await init_entry(hass, ufp, [light], regenerate_ids=False) - - assert ufp.entry.state == ConfigEntryState.LOADED - assert ufp.api.update.called - assert ufp.entry.unique_id == ufp.api.bootstrap.nvr.mac - - entity = registry.async_get(f"{Platform.BUTTON}.test_light") - assert entity is not None - assert entity.unique_id == f"{light.id}_reboot" - - -async def test_migrate_device_mac_bootstrap_fail( - hass: HomeAssistant, ufp: MockUFPFixture, light: Light -) -> None: - """Test migrating with a network error.""" - - registry = er.async_get(hass) - registry.async_get_or_create( - Platform.BUTTON, - DOMAIN, - f"{light.id}_reboot", - config_entry=ufp.entry, - suggested_object_id=light.name, - ) - registry.async_get_or_create( - Platform.BUTTON, - DOMAIN, - f"{light.mac}_reboot", - config_entry=ufp.entry, - suggested_object_id=light.name, - ) - - ufp.api.get_bootstrap = AsyncMock(side_effect=NvrError) - await init_entry(hass, ufp, [light], regenerate_ids=False) - - assert ufp.entry.state == ConfigEntryState.SETUP_RETRY + assert msg["success"] + issue = None + for i in msg["result"]["issues"]: + if i["issue_id"] == "deprecate_hdr_switch": + issue = i + assert issue is None diff --git a/tests/components/unifiprotect/test_repairs.py b/tests/components/unifiprotect/test_repairs.py index b75b025be11..6ec0b3fe6ca 100644 --- a/tests/components/unifiprotect/test_repairs.py +++ b/tests/components/unifiprotect/test_repairs.py @@ -32,6 +32,8 @@ async def test_ea_warning_ignore( ) -> None: """Test EA warning is created if using prerelease version of Protect.""" + ufp.api.bootstrap.nvr.release_channel = "beta" + ufp.api.bootstrap.nvr.version = Version("1.21.0-beta.2") version = ufp.api.bootstrap.nvr.version assert version.is_prerelease await init_entry(hass, ufp, []) @@ -92,6 +94,8 @@ async def test_ea_warning_fix( ) -> None: """Test EA warning is created if using prerelease version of Protect.""" + ufp.api.bootstrap.nvr.release_channel = "beta" + ufp.api.bootstrap.nvr.version = Version("1.21.0-beta.2") version = ufp.api.bootstrap.nvr.version assert version.is_prerelease await init_entry(hass, ufp, []) @@ -125,8 +129,8 @@ async def test_ea_warning_fix( assert data["step_id"] == "start" new_nvr = copy(ufp.api.bootstrap.nvr) - new_nvr.version = Version("2.2.6") new_nvr.release_channel = "release" + new_nvr.version = Version("2.2.6") mock_msg = Mock() mock_msg.changed_data = {"version": "2.2.6", "releaseChannel": "release"} mock_msg.new_obj = new_nvr