Files
core/tests/components/knx/test_entity.py
T

240 lines
6.9 KiB
Python

"""KNX base entity tests."""
from typing import Any
import pytest
from homeassistant.components.knx.const import DOMAIN, KNX_ADDRESS
from homeassistant.const import STATE_UNKNOWN, EntityCategory, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from .conftest import KNXTestKit
@pytest.mark.parametrize(
("config", "expected_entity_id", "expected_friendly_name"),
[
(
{
"name": "test",
KNX_ADDRESS: "1/2/3",
},
"switch.test",
"test",
),
(
{
KNX_ADDRESS: "1/2/3",
},
"switch.knx_1_2_3", # generated from unique_id
None,
),
(
{
"name": "",
KNX_ADDRESS: "1/2/3",
},
"switch.knx_1_2_3", # generated from unique_id
None,
),
(
{
"default_entity_id": "switch.test_default_entity_id",
KNX_ADDRESS: "1/2/3",
},
"switch.test_default_entity_id",
None,
),
(
{
"name": "my_test_name",
"default_entity_id": "switch.test_default_entity_id",
KNX_ADDRESS: "1/2/3",
},
"switch.test_default_entity_id",
"my_test_name",
),
],
)
async def test_yaml_entity_naming(
hass: HomeAssistant,
knx: KNXTestKit,
config: dict[str, Any],
expected_entity_id: str,
expected_friendly_name: str | None,
) -> None:
"""Test KNX entity id and name setting from YAML configuration."""
await knx.setup_integration({Platform.SWITCH: config})
knx.assert_state(
expected_entity_id,
STATE_UNKNOWN,
friendly_name=expected_friendly_name,
)
@pytest.mark.parametrize(
("config", "expected_entity_category"),
[
(
{},
None,
),
(
{
"entity_category": "diagnostic",
},
EntityCategory.DIAGNOSTIC,
),
(
{
"entity_category": "config",
},
EntityCategory.CONFIG,
),
],
)
async def test_yaml_entity_category(
hass: HomeAssistant,
knx: KNXTestKit,
entity_registry: er.EntityRegistry,
config: dict[str, Any],
expected_entity_category: EntityCategory | None,
) -> None:
"""Test KNX entity category setting from YAML configuration."""
await knx.setup_integration(
{
Platform.SWITCH: [
{
"default_entity_id": "switch.test",
KNX_ADDRESS: "1/1/1",
**config,
},
]
}
)
entity = entity_registry.async_get("switch.test")
assert entity.entity_category is expected_entity_category
async def test_yaml_entity_device_grouping(
hass: HomeAssistant,
knx: KNXTestKit,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
) -> None:
"""Entities sharing a `device` name are grouped into a single device."""
await knx.setup_integration(
{
Platform.SWITCH: [
{
"default_entity_id": "switch.a",
KNX_ADDRESS: "1/1/1",
"device": {"id": "living_room", "name": "Living room"},
},
{
"default_entity_id": "switch.b",
KNX_ADDRESS: "1/1/2",
"device": {"id": "living_room", "name": "Living room"},
},
{
"default_entity_id": "switch.c",
KNX_ADDRESS: "1/1/3",
"device": {"id": "bedroom"}, # name is optional
},
{"default_entity_id": "switch.d", KNX_ADDRESS: "1/1/4"},
]
}
)
entity_a = entity_registry.async_get("switch.a")
entity_b = entity_registry.async_get("switch.b")
entity_c = entity_registry.async_get("switch.c")
entity_d = entity_registry.async_get("switch.d")
assert entity_a.device_id is not None
assert entity_a.device_id == entity_b.device_id
assert entity_c.device_id not in (None, entity_a.device_id)
assert entity_d.device_id is None
device = device_registry.async_get(entity_a.device_id)
assert device.name == "Living room"
assert device.manufacturer == "KNX"
assert (DOMAIN, "living_room") in device.identifiers
# `name` is optional; the device is still created keyed by its `id`.
bedroom = device_registry.async_get(entity_c.device_id)
assert (DOMAIN, "bedroom") in bedroom.identifiers
@pytest.mark.parametrize(
("config", "expected_friendly_name"),
[
(
{
"name": "Ceiling light",
KNX_ADDRESS: "1/1/1",
"device": {"id": "kitchen", "name": "Kitchen"},
},
"Kitchen Ceiling light",
),
(
{
KNX_ADDRESS: "1/1/1",
"device": {"id": "kitchen", "name": "Kitchen"},
},
"Kitchen", # no entity name: entity is the device's main feature
),
(
{"name": "Ceiling light", KNX_ADDRESS: "1/1/1"},
"Ceiling light", # no device: name is shown verbatim, as before
),
],
)
async def test_yaml_entity_device_naming(
hass: HomeAssistant,
knx: KNXTestKit,
config: dict[str, Any],
expected_friendly_name: str,
) -> None:
"""An entity on a device uses has_entity_name naming, like a UI entity."""
await knx.setup_integration({Platform.SWITCH: config})
states = hass.states.async_all("switch")
assert len(states) == 1
assert states[0].attributes["friendly_name"] == expected_friendly_name
@pytest.mark.parametrize(
("device_id", "expected_identifier"),
[
("Living Room", "living_room"),
("living room", "living_room"),
(" living_room ", "living_room"),
# A UI device identifier is preserved verbatim, not lower-cased.
("knx_vdev_ABC123", "knx_vdev_ABC123"),
# Surrounding whitespace is stripped before the UI-prefix check.
(" knx_vdev_ABC123 ", "knx_vdev_ABC123"),
],
)
async def test_yaml_device_id_normalization(
hass: HomeAssistant,
knx: KNXTestKit,
device_registry: dr.DeviceRegistry,
device_id: str,
expected_identifier: str,
) -> None:
"""A YAML device `id` is slugified unless it is a UI device identifier."""
await knx.setup_integration(
{
Platform.SWITCH: {
"name": "test",
KNX_ADDRESS: "1/1/1",
"device": {"id": device_id},
}
}
)
assert device_registry.async_get_device_by_identifier(
(DOMAIN, expected_identifier), knx.mock_config_entry.entry_id
)