mirror of https://github.com/home-assistant/core
218 lines
6.1 KiB
Python
218 lines
6.1 KiB
Python
"""The tests for RFXCOM RFXtrx device actions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, NamedTuple
|
|
|
|
import pytest
|
|
from pytest_unordered import unordered
|
|
import RFXtrx
|
|
|
|
from homeassistant.components import automation
|
|
from homeassistant.components.device_automation import DeviceAutomationType
|
|
from homeassistant.components.rfxtrx import DOMAIN
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import device_registry as dr
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from .conftest import create_rfx_test_cfg
|
|
|
|
from tests.common import MockConfigEntry, async_get_device_automations
|
|
|
|
|
|
class DeviceTestData(NamedTuple):
|
|
"""Test data linked to a device."""
|
|
|
|
code: str
|
|
device_identifiers: set[tuple[str, str, str, str]]
|
|
|
|
|
|
DEVICE_LIGHTING_1 = DeviceTestData("0710002a45050170", {("rfxtrx", "10", "0", "E5")})
|
|
|
|
DEVICE_BLINDS_1 = DeviceTestData(
|
|
"09190000009ba8010100", {("rfxtrx", "19", "0", "009ba8:1")}
|
|
)
|
|
|
|
DEVICE_TEMPHUM_1 = DeviceTestData(
|
|
"0a52080705020095220269", {("rfxtrx", "52", "8", "05:02")}
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("device", [DEVICE_LIGHTING_1, DEVICE_TEMPHUM_1])
|
|
async def test_device_test_data(rfxtrx, device: DeviceTestData) -> None:
|
|
"""Verify that our testing data remains correct."""
|
|
pkt: RFXtrx.lowlevel.Packet = RFXtrx.lowlevel.parse(bytearray.fromhex(device.code))
|
|
assert device.device_identifiers == {
|
|
("rfxtrx", f"{pkt.packettype:x}", f"{pkt.subtype:x}", pkt.id_string)
|
|
}
|
|
|
|
|
|
async def setup_entry(hass: HomeAssistant, devices: dict[str, Any]) -> None:
|
|
"""Construct a config setup."""
|
|
entry_data = create_rfx_test_cfg(devices=devices)
|
|
mock_entry = MockConfigEntry(domain="rfxtrx", unique_id=DOMAIN, data=entry_data)
|
|
|
|
mock_entry.add_to_hass(hass)
|
|
|
|
await hass.config_entries.async_setup(mock_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
await hass.async_start()
|
|
|
|
|
|
def _get_expected_actions(data):
|
|
for value in data.values():
|
|
yield {"type": "send_command", "subtype": value}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("device", "expected"),
|
|
[
|
|
(
|
|
DEVICE_LIGHTING_1,
|
|
list(_get_expected_actions(RFXtrx.lowlevel.Lighting1.COMMANDS)),
|
|
),
|
|
(
|
|
DEVICE_BLINDS_1,
|
|
list(_get_expected_actions(RFXtrx.lowlevel.RollerTrol.COMMANDS)),
|
|
),
|
|
(DEVICE_TEMPHUM_1, []),
|
|
],
|
|
)
|
|
async def test_get_actions(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
device: DeviceTestData,
|
|
expected,
|
|
) -> None:
|
|
"""Test we get the expected actions from a rfxtrx."""
|
|
await setup_entry(hass, {device.code: {}})
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers=device.device_identifiers
|
|
)
|
|
assert device_entry
|
|
|
|
# Add alternate identifiers, to make sure we can handle future formats
|
|
identifiers: list[str] = list(*device_entry.identifiers)
|
|
device_registry.async_update_device(
|
|
device_entry.id, merge_identifiers={(identifiers[0], "_".join(identifiers[1:]))}
|
|
)
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers=device.device_identifiers
|
|
)
|
|
assert device_entry
|
|
|
|
actions = await async_get_device_automations(
|
|
hass, DeviceAutomationType.ACTION, device_entry.id
|
|
)
|
|
actions = [action for action in actions if action["domain"] == DOMAIN]
|
|
|
|
expected_actions = [
|
|
{"domain": DOMAIN, "device_id": device_entry.id, "metadata": {}, **action_type}
|
|
for action_type in expected
|
|
]
|
|
|
|
assert actions == unordered(expected_actions)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("device", "config", "expected"),
|
|
[
|
|
(
|
|
DEVICE_LIGHTING_1,
|
|
{"type": "send_command", "subtype": "On"},
|
|
"0710000045050100",
|
|
),
|
|
(
|
|
DEVICE_LIGHTING_1,
|
|
{"type": "send_command", "subtype": "Off"},
|
|
"0710000045050000",
|
|
),
|
|
(
|
|
DEVICE_BLINDS_1,
|
|
{"type": "send_command", "subtype": "Stop"},
|
|
"09190000009ba8010200",
|
|
),
|
|
],
|
|
)
|
|
async def test_action(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
rfxtrx: RFXtrx.Connect,
|
|
device: DeviceTestData,
|
|
config,
|
|
expected,
|
|
) -> None:
|
|
"""Test for actions."""
|
|
|
|
await setup_entry(hass, {device.code: {}})
|
|
|
|
device_entry = device_registry.async_get_device(
|
|
identifiers=device.device_identifiers
|
|
)
|
|
assert device_entry
|
|
|
|
assert await async_setup_component(
|
|
hass,
|
|
automation.DOMAIN,
|
|
{
|
|
automation.DOMAIN: [
|
|
{
|
|
"trigger": {
|
|
"platform": "event",
|
|
"event_type": "test_event",
|
|
},
|
|
"action": {
|
|
"domain": DOMAIN,
|
|
"device_id": device_entry.id,
|
|
**config,
|
|
},
|
|
},
|
|
]
|
|
},
|
|
)
|
|
|
|
hass.bus.async_fire("test_event")
|
|
await hass.async_block_till_done()
|
|
|
|
rfxtrx.transport.send.assert_called_once_with(bytearray.fromhex(expected))
|
|
|
|
|
|
async def test_invalid_action(
|
|
hass: HomeAssistant,
|
|
device_registry: dr.DeviceRegistry,
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""Test for invalid actions."""
|
|
device = DEVICE_LIGHTING_1
|
|
|
|
await setup_entry(hass, {device.code: {}})
|
|
|
|
device_identifiers: Any = device.device_identifiers
|
|
device_entry = device_registry.async_get_device(identifiers=device_identifiers)
|
|
assert device_entry
|
|
|
|
assert await async_setup_component(
|
|
hass,
|
|
automation.DOMAIN,
|
|
{
|
|
automation.DOMAIN: [
|
|
{
|
|
"trigger": {
|
|
"platform": "event",
|
|
"event_type": "test_event",
|
|
},
|
|
"action": {
|
|
"domain": DOMAIN,
|
|
"device_id": device_entry.id,
|
|
"type": "send_command",
|
|
"subtype": "invalid",
|
|
},
|
|
},
|
|
]
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert "Subtype invalid not found in device commands" in caplog.text
|