mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Fix execute device actions with WS execute_script (#95783)
This commit is contained in:
parent
3f9d5a0192
commit
78880f0c9d
@ -704,10 +704,12 @@ async def handle_execute_script(
|
|||||||
"""Handle execute script command."""
|
"""Handle execute script command."""
|
||||||
# Circular dep
|
# Circular dep
|
||||||
# pylint: disable-next=import-outside-toplevel
|
# pylint: disable-next=import-outside-toplevel
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script, async_validate_actions_config
|
||||||
|
|
||||||
|
script_config = await async_validate_actions_config(hass, msg["sequence"])
|
||||||
|
|
||||||
context = connection.context(msg)
|
context = connection.context(msg)
|
||||||
script_obj = Script(hass, msg["sequence"], f"{const.DOMAIN} script", const.DOMAIN)
|
script_obj = Script(hass, script_config, f"{const.DOMAIN} script", const.DOMAIN)
|
||||||
response = await script_obj.async_run(msg.get("variables"), context=context)
|
response = await script_obj.async_run(msg.get("variables"), context=context)
|
||||||
connection.send_result(
|
connection.send_result(
|
||||||
msg["id"],
|
msg["id"],
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
"""Tests for WebSocket API commands."""
|
"""Tests for WebSocket API commands."""
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import datetime
|
import datetime
|
||||||
from unittest.mock import ANY, patch
|
from unittest.mock import ANY, AsyncMock, Mock, patch
|
||||||
|
|
||||||
from async_timeout import timeout
|
from async_timeout import timeout
|
||||||
import pytest
|
import pytest
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries, loader
|
||||||
|
from homeassistant.components.device_automation import toggle_entity
|
||||||
from homeassistant.components.websocket_api import const
|
from homeassistant.components.websocket_api import const
|
||||||
from homeassistant.components.websocket_api.auth import (
|
from homeassistant.components.websocket_api.auth import (
|
||||||
TYPE_AUTH,
|
TYPE_AUTH,
|
||||||
@ -17,13 +19,20 @@ from homeassistant.components.websocket_api.const import FEATURE_COALESCE_MESSAG
|
|||||||
from homeassistant.const import SIGNAL_BOOTSTRAP_INTEGRATIONS
|
from homeassistant.const import SIGNAL_BOOTSTRAP_INTEGRATIONS
|
||||||
from homeassistant.core import Context, HomeAssistant, State, callback
|
from homeassistant.core import Context, HomeAssistant, State, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity
|
from homeassistant.helpers import device_registry as dr, entity
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.loader import async_get_integration
|
from homeassistant.loader import async_get_integration
|
||||||
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
|
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
|
||||||
from homeassistant.util.json import json_loads
|
from homeassistant.util.json import json_loads
|
||||||
|
|
||||||
from tests.common import MockEntity, MockEntityPlatform, MockUser, async_mock_service
|
from tests.common import (
|
||||||
|
MockConfigEntry,
|
||||||
|
MockEntity,
|
||||||
|
MockEntityPlatform,
|
||||||
|
MockUser,
|
||||||
|
async_mock_service,
|
||||||
|
mock_platform,
|
||||||
|
)
|
||||||
from tests.typing import (
|
from tests.typing import (
|
||||||
ClientSessionGenerator,
|
ClientSessionGenerator,
|
||||||
WebSocketGenerator,
|
WebSocketGenerator,
|
||||||
@ -40,6 +49,25 @@ STATE_KEY_SHORT_NAMES = {
|
|||||||
STATE_KEY_LONG_NAMES = {v: k for k, v in STATE_KEY_SHORT_NAMES.items()}
|
STATE_KEY_LONG_NAMES = {v: k for k, v in STATE_KEY_SHORT_NAMES.items()}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def fake_integration(hass: HomeAssistant):
|
||||||
|
"""Set up a mock integration with device automation support."""
|
||||||
|
DOMAIN = "fake_integration"
|
||||||
|
|
||||||
|
hass.config.components.add(DOMAIN)
|
||||||
|
|
||||||
|
mock_platform(
|
||||||
|
hass,
|
||||||
|
f"{DOMAIN}.device_action",
|
||||||
|
Mock(
|
||||||
|
ACTION_SCHEMA=toggle_entity.ACTION_SCHEMA.extend(
|
||||||
|
{vol.Required("domain"): DOMAIN}
|
||||||
|
),
|
||||||
|
spec=["ACTION_SCHEMA"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _apply_entities_changes(state_dict: dict, change_dict: dict) -> None:
|
def _apply_entities_changes(state_dict: dict, change_dict: dict) -> None:
|
||||||
"""Apply a diff set to a dict.
|
"""Apply a diff set to a dict.
|
||||||
|
|
||||||
@ -1775,6 +1803,52 @@ async def test_execute_script_complex_response(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_execute_script_with_dynamically_validated_action(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client: WebSocketGenerator,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
fake_integration,
|
||||||
|
) -> None:
|
||||||
|
"""Test executing a script with an action which is dynamically validated."""
|
||||||
|
|
||||||
|
ws_client = await hass_ws_client(hass)
|
||||||
|
|
||||||
|
module_cache = hass.data.setdefault(loader.DATA_COMPONENTS, {})
|
||||||
|
module = module_cache["fake_integration.device_action"]
|
||||||
|
module.async_call_action_from_config = AsyncMock()
|
||||||
|
module.async_validate_action_config = AsyncMock(
|
||||||
|
side_effect=lambda hass, config: config
|
||||||
|
)
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(domain="fake_integration", data={})
|
||||||
|
config_entry.state = config_entries.ConfigEntryState.LOADED
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
)
|
||||||
|
|
||||||
|
await ws_client.send_json_auto_id(
|
||||||
|
{
|
||||||
|
"type": "execute_script",
|
||||||
|
"sequence": [
|
||||||
|
{
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"domain": "fake_integration",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
msg_no_var = await ws_client.receive_json()
|
||||||
|
assert msg_no_var["type"] == const.TYPE_RESULT
|
||||||
|
assert msg_no_var["success"]
|
||||||
|
assert msg_no_var["result"]["response"] is None
|
||||||
|
|
||||||
|
module.async_validate_action_config.assert_awaited_once()
|
||||||
|
module.async_call_action_from_config.assert_awaited_once()
|
||||||
|
|
||||||
|
|
||||||
async def test_subscribe_unsubscribe_bootstrap_integrations(
|
async def test_subscribe_unsubscribe_bootstrap_integrations(
|
||||||
hass: HomeAssistant, websocket_client, hass_admin_user: MockUser
|
hass: HomeAssistant, websocket_client, hass_admin_user: MockUser
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user