Files

471 lines
14 KiB
Python

"""The tests for template helpers."""
import pytest
from homeassistant.components.template import DOMAIN
from homeassistant.components.template.alarm_control_panel import (
SCRIPT_FIELDS as ALARM_CONTROL_PANEL_SCRIPT_FIELDS,
)
from homeassistant.components.template.button import (
SCRIPT_FIELDS as BUTTON_SCRIPT_FIELDS,
StateButtonEntity,
)
from homeassistant.components.template.cover import SCRIPT_FIELDS as COVER_SCRIPT_FIELDS
from homeassistant.components.template.fan import SCRIPT_FIELDS as FAN_SCRIPT_FIELDS
from homeassistant.components.template.helpers import async_setup_template_platform
from homeassistant.components.template.light import SCRIPT_FIELDS as LIGHT_SCRIPT_FIELDS
from homeassistant.components.template.lock import SCRIPT_FIELDS as LOCK_SCRIPT_FIELDS
from homeassistant.components.template.number import (
SCRIPT_FIELDS as NUMBER_SCRIPT_FIELDS,
)
from homeassistant.components.template.select import (
SCRIPT_FIELDS as SELECT_SCRIPT_FIELDS,
)
from homeassistant.components.template.switch import (
SCRIPT_FIELDS as SWITCH_SCRIPT_FIELDS,
)
from homeassistant.components.template.update import (
SCRIPT_FIELDS as UPDATE_SCRIPT_FIELDS,
)
from homeassistant.components.template.vacuum import (
CONF_CLEAN_SEGMENTS as VACUUM_CLEAN_SEGMENTS,
SCRIPT_FIELDS as VACUUM_SCRIPT_FIELDS,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.typing import ConfigType
from .conftest import (
ConfigurationStyle,
assert_action,
async_trigger,
make_mock_device_actions,
setup_entity,
setup_mock_devices,
)
from tests.common import MockConfigEntry
async def _setup_and_test_yaml_device_action(
hass: HomeAssistant,
style: ConfigurationStyle,
domain: str,
script_fields,
extra_config: ConfigType,
test_actions: tuple[tuple[str, dict], ...],
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
calls: list,
) -> None:
platform_setup, device_entry, entity_entry = await setup_mock_devices(
hass, domain, device_registry, entity_registry
)
actions = make_mock_device_actions(
script_fields, platform_setup, device_entry, entity_entry
)
await setup_entity(hass, platform_setup, style, 1, {**actions, **extra_config})
await async_trigger(hass, "sensor.trigger", "anything")
for test_action, action_data in test_actions:
call_count = len(calls)
await hass.services.async_call(
domain,
test_action,
{"entity_id": platform_setup.entity_id, **action_data},
blocking=True,
)
assert_action(platform_setup, calls, call_count + 1, "fake_action")
@pytest.mark.parametrize(
"style",
[ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
("domain", "script_fields", "extra_config", "test_actions"),
[
(
"alarm_control_panel",
ALARM_CONTROL_PANEL_SCRIPT_FIELDS,
{},
(
("alarm_arm_home", {"code": "1234"}),
("alarm_arm_away", {"code": "1234"}),
("alarm_arm_night", {"code": "1234"}),
("alarm_arm_vacation", {"code": "1234"}),
("alarm_arm_custom_bypass", {"code": "1234"}),
("alarm_disarm", {"code": "1234"}),
("alarm_trigger", {"code": "1234"}),
),
),
(
"cover",
COVER_SCRIPT_FIELDS,
{},
(
("open_cover", {}),
("close_cover", {}),
("stop_cover", {}),
("set_cover_position", {"position": 25}),
("set_cover_tilt_position", {"tilt_position": 25}),
),
),
(
"fan",
FAN_SCRIPT_FIELDS,
{
"preset_modes": ["auto", "low", "medium", "high"],
},
(
("turn_on", {}),
("turn_off", {}),
("set_percentage", {"percentage": 25}),
("set_preset_mode", {"preset_mode": "auto"}),
("oscillate", {"oscillating": True}),
("set_direction", {"direction": "forward"}),
),
),
(
"light",
LIGHT_SCRIPT_FIELDS,
{"effect_list": "{{ ['foo', 'bar'] }}", "effect": "{{ 'foo' }}"},
(
("turn_on", {"brightness": 1}),
("turn_off", {}),
("turn_on", {"color_temp_kelvin": 8130}),
("turn_on", {"hs_color": (360, 100)}),
("turn_on", {"rgb_color": (160, 78, 192)}),
("turn_on", {"rgbw_color": (160, 78, 192, 25)}),
("turn_on", {"rgbww_color": (160, 78, 192, 25, 55)}),
("turn_on", {"effect": "foo"}),
),
),
(
"lock",
LOCK_SCRIPT_FIELDS,
{},
(
("lock", {}),
("unlock", {}),
("open", {}),
),
),
(
"number",
NUMBER_SCRIPT_FIELDS,
{"step": "1"},
(("set_value", {"value": 4}),),
),
(
"select",
SELECT_SCRIPT_FIELDS,
{
"options": "{{ ['test', 'yes', 'no'] }}",
},
(("select_option", {"option": "test"}),),
),
(
"switch",
SWITCH_SCRIPT_FIELDS,
{},
(
("turn_on", {}),
("turn_off", {}),
),
),
(
"update",
UPDATE_SCRIPT_FIELDS,
{"installed_version": "{{ '2.0.0' }}", "latest_version": "{{ '3.0.0' }}"},
(("install", {}),),
),
(
"vacuum",
[
service
for service in VACUUM_SCRIPT_FIELDS
if service != VACUUM_CLEAN_SEGMENTS
],
{
"fan_speeds": ["low", "medium", "high"],
},
(
("start", {}),
("pause", {}),
("stop", {}),
("return_to_base", {}),
("clean_spot", {}),
("locate", {}),
("set_fan_speed", {"fan_speed": "medium"}),
),
),
],
)
async def test_yaml_device_actions(
hass: HomeAssistant,
style: ConfigurationStyle,
domain: str,
script_fields,
extra_config: ConfigType,
test_actions: tuple[tuple[str, dict], ...],
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
calls: list,
) -> None:
"""Test device actions in platforms supporting trigger and modern configs."""
await _setup_and_test_yaml_device_action(
hass,
style,
domain,
script_fields,
extra_config,
test_actions,
device_registry,
entity_registry,
calls,
)
@pytest.mark.parametrize(
"style",
[ConfigurationStyle.MODERN],
)
@pytest.mark.parametrize(
("domain", "script_fields", "extra_config", "test_actions"),
[
(
"button",
BUTTON_SCRIPT_FIELDS,
{},
(("press", {}),),
),
],
)
async def test_yaml_device_actions_modern_config(
hass: HomeAssistant,
style: ConfigurationStyle,
domain: str,
script_fields,
extra_config: str,
test_actions: tuple[tuple[str, dict], ...],
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
calls: list,
) -> None:
"""Test device actions in platforms that supports modern configuration only."""
await _setup_and_test_yaml_device_action(
hass,
style,
domain,
script_fields,
extra_config,
test_actions,
device_registry,
entity_registry,
calls,
)
@pytest.mark.parametrize(
("domain", "script_fields", "extra_config", "test_actions"),
[
(
"alarm_control_panel",
ALARM_CONTROL_PANEL_SCRIPT_FIELDS,
{"state": "{{ 'armed' }}"},
(
("alarm_arm_home", {"code": "1234"}),
("alarm_arm_away", {"code": "1234"}),
("alarm_arm_night", {"code": "1234"}),
("alarm_arm_vacation", {"code": "1234"}),
("alarm_arm_custom_bypass", {"code": "1234"}),
("alarm_disarm", {"code": "1234"}),
("alarm_trigger", {"code": "1234"}),
),
),
(
"button",
BUTTON_SCRIPT_FIELDS,
{},
(("press", {}),),
),
(
"cover",
COVER_SCRIPT_FIELDS,
{"state": "{{ 'open' }}"},
(
("open_cover", {}),
("close_cover", {}),
("stop_cover", {}),
("set_cover_position", {"position": 25}),
("set_cover_tilt_position", {"tilt_position": 25}),
),
),
(
"fan",
FAN_SCRIPT_FIELDS,
{
"preset_modes": ["auto", "low", "medium", "high"],
"state": "{{ 'on' }}",
},
(
("turn_on", {}),
("turn_off", {}),
("set_percentage", {"percentage": 25}),
("set_preset_mode", {"preset_mode": "auto"}),
("oscillate", {"oscillating": True}),
("set_direction", {"direction": "forward"}),
),
),
(
"light",
LIGHT_SCRIPT_FIELDS,
{
"effect_list": "{{ ['foo', 'bar'] }}",
"effect": "{{ 'foo' }}",
"state": "{{ 'on' }}",
},
(
("turn_on", {"brightness": 1}),
("turn_off", {}),
("turn_on", {"color_temp_kelvin": 8130}),
("turn_on", {"hs_color": (360, 100)}),
("turn_on", {"rgb_color": (160, 78, 192)}),
("turn_on", {"rgbw_color": (160, 78, 192, 25)}),
("turn_on", {"rgbww_color": (160, 78, 192, 25, 55)}),
("turn_on", {"effect": "foo"}),
),
),
(
"lock",
LOCK_SCRIPT_FIELDS,
{
"state": "{{ 'on' }}",
},
(
("lock", {}),
("unlock", {}),
("open", {}),
),
),
(
"number",
NUMBER_SCRIPT_FIELDS,
{"step": 1},
(("set_value", {"value": 4}),),
),
(
"select",
SELECT_SCRIPT_FIELDS,
{
"state": "{{ 'yes' }}",
"options": "{{ ['test', 'yes', 'no'] }}",
},
(("select_option", {"option": "test"}),),
),
(
"switch",
SWITCH_SCRIPT_FIELDS,
{
"state": "{{ 'on' }}",
},
(
("turn_on", {}),
("turn_off", {}),
),
),
(
"update",
UPDATE_SCRIPT_FIELDS,
{"installed_version": "{{ '2.0.0' }}", "latest_version": "{{ '3.0.0' }}"},
(("install", {}),),
),
(
"vacuum",
[
service
for service in VACUUM_SCRIPT_FIELDS
if service != VACUUM_CLEAN_SEGMENTS
],
{
"fan_speeds": ["low", "medium", "high"],
"state": "{{ 'on' }}",
},
(
("start", {}),
("pause", {}),
("stop", {}),
("return_to_base", {}),
("clean_spot", {}),
("locate", {}),
("set_fan_speed", {"fan_speed": "medium"}),
),
),
],
)
async def test_config_entry_device_actions(
hass: HomeAssistant,
domain: str,
script_fields,
extra_config: str,
test_actions: tuple[tuple[str, dict], ...],
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
calls: list,
) -> None:
"""Test device actions in config flow."""
platform_setup, device_entry, entity_entry = await setup_mock_devices(
hass, domain, device_registry, entity_registry
)
actions = make_mock_device_actions(
script_fields, platform_setup, device_entry, entity_entry
)
template_config_entry = MockConfigEntry(
data={},
domain=DOMAIN,
options={
"name": platform_setup.object_id,
"template_type": domain,
**actions,
**extra_config,
},
title="My template",
)
template_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
await hass.async_block_till_done()
for test_action, action_data in test_actions:
call_count = len(calls)
await hass.services.async_call(
domain,
test_action,
{"entity_id": platform_setup.entity_id, **action_data},
blocking=True,
)
assert_action(platform_setup, calls, call_count + 1, "fake_action")
async def test_platform_not_ready(
hass: HomeAssistant,
) -> None:
"""Test async_setup_template_platform raises PlatformNotReady."""
with pytest.raises(PlatformNotReady):
await async_setup_template_platform(
hass,
"button",
{},
StateButtonEntity,
None,
None,
{"coordinator": None, "entities": []},
)