core/tests/components/shelly/test_device_trigger.py

356 lines
11 KiB
Python

"""The tests for Shelly device triggers."""
import pytest
from homeassistant.components import automation
from homeassistant.components.device_automation import DeviceAutomationType
from homeassistant.components.device_automation.exceptions import (
InvalidDeviceAutomationConfig,
)
from homeassistant.components.shelly.const import (
ATTR_CHANNEL,
ATTR_CLICK_TYPE,
CONF_SUBTYPE,
DOMAIN,
EVENT_SHELLY_CLICK,
)
from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_PLATFORM, CONF_TYPE
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
async_entries_for_config_entry,
async_get as async_get_dev_reg,
)
from homeassistant.setup import async_setup_component
from . import init_integration
from tests.common import (
MockConfigEntry,
assert_lists_same,
async_get_device_automations,
)
@pytest.mark.parametrize(
"button_type, is_valid",
[
("momentary", True),
("momentary_on_release", True),
("detached", True),
("toggle", False),
],
)
async def test_get_triggers_block_device(
hass, mock_block_device, monkeypatch, button_type, is_valid
):
"""Test we get the expected triggers from a shelly block device."""
monkeypatch.setitem(
mock_block_device.settings,
"relays",
[
{"btn_type": button_type},
{"btn_type": "toggle"},
],
)
entry = await init_integration(hass, 1)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
expected_triggers = []
if is_valid:
expected_triggers = [
{
CONF_PLATFORM: "device",
CONF_DEVICE_ID: device.id,
CONF_DOMAIN: DOMAIN,
CONF_TYPE: type_,
CONF_SUBTYPE: "button1",
"metadata": {},
}
for type_ in ["single", "long"]
]
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device.id
)
triggers = [value for value in triggers if value["domain"] == DOMAIN]
assert_lists_same(triggers, expected_triggers)
async def test_get_triggers_rpc_device(hass, mock_rpc_device):
"""Test we get the expected triggers from a shelly RPC device."""
entry = await init_integration(hass, 2)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
expected_triggers = [
{
CONF_PLATFORM: "device",
CONF_DEVICE_ID: device.id,
CONF_DOMAIN: DOMAIN,
CONF_TYPE: type,
CONF_SUBTYPE: "button1",
"metadata": {},
}
for type in ["btn_down", "btn_up", "single_push", "double_push", "long_push"]
]
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device.id
)
triggers = [value for value in triggers if value["domain"] == DOMAIN]
assert_lists_same(triggers, expected_triggers)
async def test_get_triggers_button(hass, mock_block_device):
"""Test we get the expected triggers from a shelly button."""
entry = await init_integration(hass, 1, model="SHBTN-1")
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
expected_triggers = [
{
CONF_PLATFORM: "device",
CONF_DEVICE_ID: device.id,
CONF_DOMAIN: DOMAIN,
CONF_TYPE: type,
CONF_SUBTYPE: "button",
"metadata": {},
}
for type in ["single", "double", "triple", "long"]
]
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device.id
)
triggers = [value for value in triggers if value["domain"] == DOMAIN]
assert_lists_same(triggers, expected_triggers)
async def test_get_triggers_non_initialized_devices(
hass, mock_block_device, monkeypatch
):
"""Test we get the empty triggers for non-initialized devices."""
monkeypatch.setattr(mock_block_device, "initialized", False)
entry = await init_integration(hass, 1)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
expected_triggers = []
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device.id
)
triggers = [value for value in triggers if value["domain"] == DOMAIN]
assert_lists_same(triggers, expected_triggers)
async def test_get_triggers_for_invalid_device_id(hass, device_reg, mock_block_device):
"""Test error raised for invalid shelly device_id."""
await init_integration(hass, 1)
config_entry = MockConfigEntry(domain=DOMAIN, data={})
config_entry.add_to_hass(hass)
invalid_device = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
with pytest.raises(InvalidDeviceAutomationConfig):
await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, invalid_device.id
)
async def test_if_fires_on_click_event_block_device(hass, calls, mock_block_device):
"""Test for click_event trigger firing for block device."""
entry = await init_integration(hass, 1)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
CONF_PLATFORM: "device",
CONF_DOMAIN: DOMAIN,
CONF_DEVICE_ID: device.id,
CONF_TYPE: "single",
CONF_SUBTYPE: "button1",
},
"action": {
"service": "test.automation",
"data_template": {"some": "test_trigger_single_click"},
},
},
]
},
)
message = {
CONF_DEVICE_ID: device.id,
ATTR_CLICK_TYPE: "single",
ATTR_CHANNEL: 1,
}
hass.bus.async_fire(EVENT_SHELLY_CLICK, message)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "test_trigger_single_click"
async def test_if_fires_on_click_event_rpc_device(hass, calls, mock_rpc_device):
"""Test for click_event trigger firing for rpc device."""
entry = await init_integration(hass, 2)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
CONF_PLATFORM: "device",
CONF_DOMAIN: DOMAIN,
CONF_DEVICE_ID: device.id,
CONF_TYPE: "single_push",
CONF_SUBTYPE: "button1",
},
"action": {
"service": "test.automation",
"data_template": {"some": "test_trigger_single_push"},
},
},
]
},
)
message = {
CONF_DEVICE_ID: device.id,
ATTR_CLICK_TYPE: "single_push",
ATTR_CHANNEL: 1,
}
hass.bus.async_fire(EVENT_SHELLY_CLICK, message)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "test_trigger_single_push"
async def test_validate_trigger_block_device_not_ready(
hass, calls, mock_block_device, monkeypatch
):
"""Test validate trigger config when block device is not ready."""
monkeypatch.setattr(mock_block_device, "initialized", False)
entry = await init_integration(hass, 1)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
CONF_PLATFORM: "device",
CONF_DOMAIN: DOMAIN,
CONF_DEVICE_ID: device.id,
CONF_TYPE: "single",
CONF_SUBTYPE: "button1",
},
"action": {
"service": "test.automation",
"data_template": {"some": "test_trigger_single_click"},
},
},
]
},
)
message = {
CONF_DEVICE_ID: device.id,
ATTR_CLICK_TYPE: "single",
ATTR_CHANNEL: 1,
}
hass.bus.async_fire(EVENT_SHELLY_CLICK, message)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "test_trigger_single_click"
async def test_validate_trigger_rpc_device_not_ready(
hass, calls, mock_rpc_device, monkeypatch
):
"""Test validate trigger config when RPC device is not ready."""
monkeypatch.setattr(mock_rpc_device, "initialized", False)
entry = await init_integration(hass, 2)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
CONF_PLATFORM: "device",
CONF_DOMAIN: DOMAIN,
CONF_DEVICE_ID: device.id,
CONF_TYPE: "single_push",
CONF_SUBTYPE: "button1",
},
"action": {
"service": "test.automation",
"data_template": {"some": "test_trigger_single_push"},
},
},
]
},
)
message = {
CONF_DEVICE_ID: device.id,
ATTR_CLICK_TYPE: "single_push",
ATTR_CHANNEL: 1,
}
hass.bus.async_fire(EVENT_SHELLY_CLICK, message)
await hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].data["some"] == "test_trigger_single_push"
async def test_validate_trigger_invalid_triggers(hass, mock_block_device, caplog):
"""Test for click_event with invalid triggers."""
entry = await init_integration(hass, 1)
dev_reg = async_get_dev_reg(hass)
device = async_entries_for_config_entry(dev_reg, entry.entry_id)[0]
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
CONF_PLATFORM: "device",
CONF_DOMAIN: DOMAIN,
CONF_DEVICE_ID: device.id,
CONF_TYPE: "single",
CONF_SUBTYPE: "button3",
},
"action": {
"service": "test.automation",
"data_template": {"some": "test_trigger_single_click"},
},
},
]
},
)
assert "Invalid (type,subtype): ('single', 'button3')" in caplog.text