Use real devices in automation and script tests (#102785)

This commit is contained in:
Erik Montnemery 2023-10-25 16:09:39 +02:00 committed by GitHub
parent e734a4bc53
commit b83ada8c19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 29 deletions

View File

@ -6,6 +6,7 @@ from unittest.mock import Mock, patch
import pytest import pytest
from homeassistant import config_entries
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.automation import ( from homeassistant.components.automation import (
ATTR_SOURCE, ATTR_SOURCE,
@ -36,6 +37,7 @@ from homeassistant.core import (
callback, callback,
) )
from homeassistant.exceptions import HomeAssistantError, Unauthorized from homeassistant.exceptions import HomeAssistantError, Unauthorized
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.script import ( from homeassistant.helpers.script import (
SCRIPT_MODE_CHOICES, SCRIPT_MODE_CHOICES,
SCRIPT_MODE_PARALLEL, SCRIPT_MODE_PARALLEL,
@ -49,6 +51,7 @@ from homeassistant.util import yaml
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import ( from tests.common import (
MockConfigEntry,
MockUser, MockUser,
assert_setup_component, assert_setup_component,
async_capture_events, async_capture_events,
@ -1589,8 +1592,31 @@ async def test_extraction_functions_unavailable_automation(hass: HomeAssistant)
assert automation.entities_in_automation(hass, entity_id) == [] 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.""" """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, "homeassistant", {})
await async_setup_component(hass, "calendar", {"calendar": {"platform": "demo"}}) await async_setup_component(hass, "calendar", {"calendar": {"platform": "demo"}})
assert await async_setup_component( assert await async_setup_component(
@ -1652,7 +1678,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
}, },
{ {
"domain": "light", "domain": "light",
"device_id": "device-in-both", "device_id": device_in_both.id,
"entity_id": "light.bla", "entity_id": "light.bla",
"type": "turn_on", "type": "turn_on",
}, },
@ -1670,7 +1696,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
"domain": "light", "domain": "light",
"type": "turned_on", "type": "turned_on",
"entity_id": "light.trigger_2", "entity_id": "light.trigger_2",
"device_id": "trigger-device-2", "device_id": trigger_device_2.id,
}, },
{ {
"platform": "tag", "platform": "tag",
@ -1702,7 +1728,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
], ],
"condition": { "condition": {
"condition": "device", "condition": "device",
"device_id": "condition-device", "device_id": condition_device.id,
"domain": "light", "domain": "light",
"type": "is_on", "type": "is_on",
"entity_id": "light.bla", "entity_id": "light.bla",
@ -1720,13 +1746,13 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
{"scene": "scene.hello"}, {"scene": "scene.hello"},
{ {
"domain": "light", "domain": "light",
"device_id": "device-in-both", "device_id": device_in_both.id,
"entity_id": "light.bla", "entity_id": "light.bla",
"type": "turn_on", "type": "turn_on",
}, },
{ {
"domain": "light", "domain": "light",
"device_id": "device-in-last", "device_id": device_in_last.id,
"entity_id": "light.bla", "entity_id": "light.bla",
"type": "turn_on", "type": "turn_on",
}, },
@ -1755,7 +1781,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
], ],
"condition": { "condition": {
"condition": "device", "condition": "device",
"device_id": "condition-device", "device_id": condition_device.id,
"domain": "light", "domain": "light",
"type": "is_on", "type": "is_on",
"entity_id": "light.bla", "entity_id": "light.bla",
@ -1799,15 +1825,15 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
"light.in_both", "light.in_both",
"light.in_first", "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.test1",
"automation.test2", "automation.test2",
} }
assert set(automation.devices_in_automation(hass, "automation.test2")) == { assert set(automation.devices_in_automation(hass, "automation.test2")) == {
"trigger-device-2", trigger_device_2.id,
"condition-device", condition_device.id,
"device-in-both", device_in_both.id,
"device-in-last", device_in_last.id,
"device-trigger-event", "device-trigger-event",
"device-trigger-tag1", "device-trigger-tag1",
"device-trigger-tag2", "device-trigger-tag2",

View File

@ -7,14 +7,15 @@ from unittest.mock import patch
import pytest import pytest
from homeassistant import config_entries
from homeassistant.components import script from homeassistant.components import script
from homeassistant.components.blueprint.models import Blueprint, DomainBlueprints from homeassistant.components.blueprint.models import Blueprint, DomainBlueprints
from homeassistant.core import Context, HomeAssistant, callback 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.setup import async_setup_component
from homeassistant.util import yaml 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" 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 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.""" """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( with patch_blueprint(
"confirmable_notification.yaml", "confirmable_notification.yaml",
BUILTIN_BLUEPRINT_FOLDER / "confirmable_notification.yaml", BUILTIN_BLUEPRINT_FOLDER / "confirmable_notification.yaml",
@ -56,7 +68,7 @@ async def test_confirmable_notification(hass: HomeAssistant) -> None:
"use_blueprint": { "use_blueprint": {
"path": "confirmable_notification.yaml", "path": "confirmable_notification.yaml",
"input": { "input": {
"notify_device": "frodo", "notify_device": frodo.id,
"title": "Lord of the things", "title": "Lord of the things",
"message": "Throw ring in mountain?", "message": "Throw ring in mountain?",
"confirm_action": [ "confirm_action": [
@ -105,7 +117,7 @@ async def test_confirmable_notification(hass: HomeAssistant) -> None:
"alias": "Send notification", "alias": "Send notification",
"domain": "mobile_app", "domain": "mobile_app",
"type": "notify", "type": "notify",
"device_id": "frodo", "device_id": frodo.id,
"data": { "data": {
"actions": [ "actions": [
{"action": "CONFIRM_" + _context.id, "title": "Confirm"}, {"action": "CONFIRM_" + _context.id, "title": "Confirm"},

View File

@ -6,6 +6,7 @@ from unittest.mock import Mock, patch
import pytest import pytest
from homeassistant import config_entries
from homeassistant.components import script from homeassistant.components import script
from homeassistant.components.script import DOMAIN, EVENT_SCRIPT_STARTED, ScriptEntity from homeassistant.components.script import DOMAIN, EVENT_SCRIPT_STARTED, ScriptEntity
from homeassistant.const import ( from homeassistant.const import (
@ -27,7 +28,7 @@ from homeassistant.core import (
split_entity_id, split_entity_id,
) )
from homeassistant.exceptions import ServiceNotFound 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.event import async_track_state_change
from homeassistant.helpers.script import ( from homeassistant.helpers.script import (
SCRIPT_MODE_CHOICES, SCRIPT_MODE_CHOICES,
@ -42,7 +43,12 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import yaml from homeassistant.util import yaml
import homeassistant.util.dt as dt_util 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.components.logbook.common import MockRow, mock_humanify
from tests.typing import WebSocketGenerator 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) == [] 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.""" """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( assert await async_setup_component(
hass, hass,
DOMAIN, DOMAIN,
@ -728,7 +749,7 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
"entity_id": "light.device_in_both", "entity_id": "light.device_in_both",
"domain": "light", "domain": "light",
"type": "turn_on", "type": "turn_on",
"device_id": "device-in-both", "device_id": device_in_both.id,
}, },
{ {
"service": "test.test", "service": "test.test",
@ -752,13 +773,13 @@ async def test_extraction_functions(hass: HomeAssistant) -> None:
"entity_id": "light.device_in_both", "entity_id": "light.device_in_both",
"domain": "light", "domain": "light",
"type": "turn_on", "type": "turn_on",
"device_id": "device-in-both", "device_id": device_in_both.id,
}, },
{ {
"entity_id": "light.device_in_last", "entity_id": "light.device_in_last",
"domain": "light", "domain": "light",
"type": "turn_on", "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_both",
"light.in_first", "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.test1",
"script.test2", "script.test2",
} }
assert set(script.devices_in_script(hass, "script.test2")) == { assert set(script.devices_in_script(hass, "script.test2")) == {
"device-in-both", device_in_both.id,
"device-in-last", device_in_last.id,
} }
assert set(script.scripts_with_area(hass, "area-in-both")) == { assert set(script.scripts_with_area(hass, "area-in-both")) == {
"script.test1", "script.test1",

View File

@ -13,7 +13,7 @@ import pytest
import voluptuous as vol import voluptuous as vol
# Otherwise can't test just this file (import order issue) # 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 import homeassistant.components.scene as scene
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
@ -33,6 +33,7 @@ from homeassistant.core import (
from homeassistant.exceptions import ConditionError, HomeAssistantError, ServiceNotFound from homeassistant.exceptions import ConditionError, HomeAssistantError, ServiceNotFound
from homeassistant.helpers import ( from homeassistant.helpers import (
config_validation as cv, config_validation as cv,
device_registry as dr,
entity_registry as er, entity_registry as er,
script, script,
template, template,
@ -43,6 +44,7 @@ from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import ( from tests.common import (
MockConfigEntry,
async_capture_events, async_capture_events,
async_fire_time_changed, async_fire_time_changed,
async_mock_service, async_mock_service,
@ -4532,12 +4534,23 @@ async def test_set_redefines_variable(
assert_action_trace(expected_trace) 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.""" """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): def templated_device_action(message):
return { return {
"device_id": "abcd", "device_id": mock_device.id,
"domain": "mobile_app", "domain": "mobile_app",
"message": f"{message} {{{{ 5 + 5}}}}", "message": f"{message} {{{{ 5 + 5}}}}",
"type": "notify", "type": "notify",