From b83ada8c19e816b6db30725b1ee432258b3e207f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 25 Oct 2023 16:09:39 +0200 Subject: [PATCH] Use real devices in automation and script tests (#102785) --- tests/components/automation/test_init.py | 50 +++++++++++++++++------ tests/components/script/test_blueprint.py | 22 +++++++--- tests/components/script/test_init.py | 39 ++++++++++++++---- tests/helpers/test_script.py | 19 +++++++-- 4 files changed, 101 insertions(+), 29 deletions(-) diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index 0d983864e44..6d83b00517d 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -6,6 +6,7 @@ from unittest.mock import Mock, patch import pytest +from homeassistant import config_entries import homeassistant.components.automation as automation from homeassistant.components.automation import ( ATTR_SOURCE, @@ -36,6 +37,7 @@ from homeassistant.core import ( callback, ) from homeassistant.exceptions import HomeAssistantError, Unauthorized +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.script import ( SCRIPT_MODE_CHOICES, SCRIPT_MODE_PARALLEL, @@ -49,6 +51,7 @@ from homeassistant.util import yaml import homeassistant.util.dt as dt_util from tests.common import ( + MockConfigEntry, MockUser, assert_setup_component, async_capture_events, @@ -1589,8 +1592,31 @@ async def test_extraction_functions_unavailable_automation(hass: HomeAssistant) assert automation.entities_in_automation(hass, entity_id) == [] -async def test_extraction_functions(hass: HomeAssistant) -> None: +async def test_extraction_functions( + hass: HomeAssistant, device_registry: dr.DeviceRegistry +) -> None: """Test extraction functions.""" + config_entry = MockConfigEntry(domain="fake_integration", data={}) + config_entry.state = config_entries.ConfigEntryState.LOADED + config_entry.add_to_hass(hass) + + condition_device = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:01")}, + ) + device_in_both = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:02")}, + ) + device_in_last = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:03")}, + ) + trigger_device_2 = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:04")}, + ) + await async_setup_component(hass, "homeassistant", {}) await async_setup_component(hass, "calendar", {"calendar": {"platform": "demo"}}) assert await async_setup_component( @@ -1652,7 +1678,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: }, { "domain": "light", - "device_id": "device-in-both", + "device_id": device_in_both.id, "entity_id": "light.bla", "type": "turn_on", }, @@ -1670,7 +1696,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: "domain": "light", "type": "turned_on", "entity_id": "light.trigger_2", - "device_id": "trigger-device-2", + "device_id": trigger_device_2.id, }, { "platform": "tag", @@ -1702,7 +1728,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: ], "condition": { "condition": "device", - "device_id": "condition-device", + "device_id": condition_device.id, "domain": "light", "type": "is_on", "entity_id": "light.bla", @@ -1720,13 +1746,13 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: {"scene": "scene.hello"}, { "domain": "light", - "device_id": "device-in-both", + "device_id": device_in_both.id, "entity_id": "light.bla", "type": "turn_on", }, { "domain": "light", - "device_id": "device-in-last", + "device_id": device_in_last.id, "entity_id": "light.bla", "type": "turn_on", }, @@ -1755,7 +1781,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: ], "condition": { "condition": "device", - "device_id": "condition-device", + "device_id": condition_device.id, "domain": "light", "type": "is_on", "entity_id": "light.bla", @@ -1799,15 +1825,15 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: "light.in_both", "light.in_first", } - assert set(automation.automations_with_device(hass, "device-in-both")) == { + assert set(automation.automations_with_device(hass, device_in_both.id)) == { "automation.test1", "automation.test2", } assert set(automation.devices_in_automation(hass, "automation.test2")) == { - "trigger-device-2", - "condition-device", - "device-in-both", - "device-in-last", + trigger_device_2.id, + condition_device.id, + device_in_both.id, + device_in_last.id, "device-trigger-event", "device-trigger-tag1", "device-trigger-tag2", diff --git a/tests/components/script/test_blueprint.py b/tests/components/script/test_blueprint.py index 8368eb06140..b248a3d7650 100644 --- a/tests/components/script/test_blueprint.py +++ b/tests/components/script/test_blueprint.py @@ -7,14 +7,15 @@ from unittest.mock import patch import pytest +from homeassistant import config_entries from homeassistant.components import script from homeassistant.components.blueprint.models import Blueprint, DomainBlueprints from homeassistant.core import Context, HomeAssistant, callback -from homeassistant.helpers import template +from homeassistant.helpers import device_registry as dr, template from homeassistant.setup import async_setup_component from homeassistant.util import yaml -from tests.common import async_mock_service +from tests.common import MockConfigEntry, async_mock_service BUILTIN_BLUEPRINT_FOLDER = pathlib.Path(script.__file__).parent / "blueprints" @@ -41,8 +42,19 @@ def patch_blueprint(blueprint_path: str, data_path: str) -> Iterator[None]: yield -async def test_confirmable_notification(hass: HomeAssistant) -> None: +async def test_confirmable_notification( + hass: HomeAssistant, device_registry: dr.DeviceRegistry +) -> None: """Test confirmable notification blueprint.""" + config_entry = MockConfigEntry(domain="fake_integration", data={}) + config_entry.state = config_entries.ConfigEntryState.LOADED + config_entry.add_to_hass(hass) + + frodo = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:01")}, + ) + with patch_blueprint( "confirmable_notification.yaml", BUILTIN_BLUEPRINT_FOLDER / "confirmable_notification.yaml", @@ -56,7 +68,7 @@ async def test_confirmable_notification(hass: HomeAssistant) -> None: "use_blueprint": { "path": "confirmable_notification.yaml", "input": { - "notify_device": "frodo", + "notify_device": frodo.id, "title": "Lord of the things", "message": "Throw ring in mountain?", "confirm_action": [ @@ -105,7 +117,7 @@ async def test_confirmable_notification(hass: HomeAssistant) -> None: "alias": "Send notification", "domain": "mobile_app", "type": "notify", - "device_id": "frodo", + "device_id": frodo.id, "data": { "actions": [ {"action": "CONFIRM_" + _context.id, "title": "Confirm"}, diff --git a/tests/components/script/test_init.py b/tests/components/script/test_init.py index cddefc8d3dc..83abd37137e 100644 --- a/tests/components/script/test_init.py +++ b/tests/components/script/test_init.py @@ -6,6 +6,7 @@ from unittest.mock import Mock, patch import pytest +from homeassistant import config_entries from homeassistant.components import script from homeassistant.components.script import DOMAIN, EVENT_SCRIPT_STARTED, ScriptEntity from homeassistant.const import ( @@ -27,7 +28,7 @@ from homeassistant.core import ( split_entity_id, ) from homeassistant.exceptions import ServiceNotFound -from homeassistant.helpers import entity_registry as er, template +from homeassistant.helpers import device_registry as dr, entity_registry as er, template from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers.script import ( SCRIPT_MODE_CHOICES, @@ -42,7 +43,12 @@ from homeassistant.setup import async_setup_component from homeassistant.util import yaml import homeassistant.util.dt as dt_util -from tests.common import async_fire_time_changed, async_mock_service, mock_restore_cache +from tests.common import ( + MockConfigEntry, + async_fire_time_changed, + async_mock_service, + mock_restore_cache, +) from tests.components.logbook.common import MockRow, mock_humanify from tests.typing import WebSocketGenerator @@ -707,8 +713,23 @@ async def test_extraction_functions_unavailable_script(hass: HomeAssistant) -> N assert script.entities_in_script(hass, entity_id) == [] -async def test_extraction_functions(hass: HomeAssistant) -> None: +async def test_extraction_functions( + hass: HomeAssistant, device_registry: dr.DeviceRegistry +) -> None: """Test extraction functions.""" + config_entry = MockConfigEntry(domain="fake_integration", data={}) + config_entry.state = config_entries.ConfigEntryState.LOADED + config_entry.add_to_hass(hass) + + device_in_both = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:02")}, + ) + device_in_last = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:03")}, + ) + assert await async_setup_component( hass, DOMAIN, @@ -728,7 +749,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: "entity_id": "light.device_in_both", "domain": "light", "type": "turn_on", - "device_id": "device-in-both", + "device_id": device_in_both.id, }, { "service": "test.test", @@ -752,13 +773,13 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: "entity_id": "light.device_in_both", "domain": "light", "type": "turn_on", - "device_id": "device-in-both", + "device_id": device_in_both.id, }, { "entity_id": "light.device_in_last", "domain": "light", "type": "turn_on", - "device_id": "device-in-last", + "device_id": device_in_last.id, }, ], }, @@ -797,13 +818,13 @@ async def test_extraction_functions(hass: HomeAssistant) -> None: "light.in_both", "light.in_first", } - assert set(script.scripts_with_device(hass, "device-in-both")) == { + assert set(script.scripts_with_device(hass, device_in_both.id)) == { "script.test1", "script.test2", } assert set(script.devices_in_script(hass, "script.test2")) == { - "device-in-both", - "device-in-last", + device_in_both.id, + device_in_last.id, } assert set(script.scripts_with_area(hass, "area-in-both")) == { "script.test1", diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index 8e4409daa54..6c327345881 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -13,7 +13,7 @@ import pytest import voluptuous as vol # Otherwise can't test just this file (import order issue) -from homeassistant import exceptions +from homeassistant import config_entries, exceptions import homeassistant.components.scene as scene from homeassistant.const import ( ATTR_ENTITY_ID, @@ -33,6 +33,7 @@ from homeassistant.core import ( from homeassistant.exceptions import ConditionError, HomeAssistantError, ServiceNotFound from homeassistant.helpers import ( config_validation as cv, + device_registry as dr, entity_registry as er, script, template, @@ -43,6 +44,7 @@ from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util from tests.common import ( + MockConfigEntry, async_capture_events, async_fire_time_changed, async_mock_service, @@ -4532,12 +4534,23 @@ async def test_set_redefines_variable( assert_action_trace(expected_trace) -async def test_validate_action_config(hass: HomeAssistant) -> None: +async def test_validate_action_config( + hass: HomeAssistant, device_registry: dr.DeviceRegistry +) -> None: """Validate action config.""" + config_entry = MockConfigEntry(domain="fake_integration", data={}) + config_entry.state = config_entries.ConfigEntryState.LOADED + config_entry.add_to_hass(hass) + + mock_device = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "00:00:00:00:00:02")}, + ) + def templated_device_action(message): return { - "device_id": "abcd", + "device_id": mock_device.id, "domain": "mobile_app", "message": f"{message} {{{{ 5 + 5}}}}", "type": "notify",