"""Tests for sensor entities: native_value and extra_state_attributes.""" import pytest from unittest.mock import patch from custom_components.zlock_slots.coordinator import ZLockCoordinator, LockState, SlotInfo from custom_components.zlock_slots.sensor import ( ZLockLastActionSensor, ZLockLastUserSensor, ZLockSlotsSensor, ZLockGroupLastActionSensor, ZLockGroupLastUserSensor, ) from custom_components.zlock_slots.const import CONF_GROUPS, CONF_GROUP_NAME, CONF_LOCK_ENTITY_IDS from tests.conftest import LOCK_ENTITY_ID, ALARM_TYPE_ENTITY, ALARM_LEVEL_ENTITY _ZWAVE_HELPER = "homeassistant.components.zwave_js.helpers.async_get_node_from_entity_id" @pytest.fixture async def coord(hass, config_entry, mock_node): config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=mock_node): c = ZLockCoordinator(hass, config_entry) await c.async_setup() await hass.async_block_till_done() yield c c.async_teardown() # --------------------------------------------------------------------------- # ZLockLastActionSensor # --------------------------------------------------------------------------- async def test_last_action_none_initially(coord, config_entry): sensor = ZLockLastActionSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value is None async def test_last_action_after_event(hass, coord, config_entry): hass.states.async_set(ALARM_LEVEL_ENTITY, "1") hass.states.async_set(ALARM_TYPE_ENTITY, "18") await hass.async_block_till_done() sensor = ZLockLastActionSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == "locked" # --------------------------------------------------------------------------- # ZLockLastUserSensor # --------------------------------------------------------------------------- async def test_last_user_none_initially(coord, config_entry): sensor = ZLockLastUserSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value is None async def test_last_user_slot_number_when_unnamed(hass, coord, config_entry): hass.states.async_set(ALARM_LEVEL_ENTITY, "2") hass.states.async_set(ALARM_TYPE_ENTITY, "19") await hass.async_block_till_done() sensor = ZLockLastUserSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == "2" async def test_last_user_name_when_named(hass, coord, config_entry): await coord.async_set_name(LOCK_ENTITY_ID, 1, "Eve") hass.states.async_set(ALARM_LEVEL_ENTITY, "1") hass.states.async_set(ALARM_TYPE_ENTITY, "18") await hass.async_block_till_done() sensor = ZLockLastUserSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == "Eve" async def test_last_user_manual(hass, coord, config_entry): hass.states.async_set(ALARM_TYPE_ENTITY, "21") await hass.async_block_till_done() sensor = ZLockLastUserSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == "" async def test_last_user_radio(hass, coord, config_entry): hass.states.async_set(ALARM_TYPE_ENTITY, "25") await hass.async_block_till_done() sensor = ZLockLastUserSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == "" # --------------------------------------------------------------------------- # ZLockSlotsSensor # --------------------------------------------------------------------------- async def test_slots_sensor_count(coord, config_entry): sensor = ZLockSlotsSensor(coord, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == 2 async def test_slots_sensor_zero_when_empty(hass, config_entry): from tests.conftest import FakeNode config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=FakeNode(users=[])): c = ZLockCoordinator(hass, config_entry) await c.async_setup() sensor = ZLockSlotsSensor(c, config_entry, LOCK_ENTITY_ID) assert sensor.native_value == 0 assert sensor.extra_state_attributes == {"slots": []} c.async_teardown() async def test_slots_sensor_attributes_structure(coord, config_entry): sensor = ZLockSlotsSensor(coord, config_entry, LOCK_ENTITY_ID) attrs = sensor.extra_state_attributes assert "slots" in attrs slots = attrs["slots"] assert len(slots) == 2 assert slots[0] == {"slot_num": 1, "status": "enabled", "name": None} assert slots[1] == {"slot_num": 2, "status": "disabled", "name": None} async def test_slots_sensor_attributes_sorted(hass, config_entry): from tests.conftest import FakeNode, FakeUserData node = FakeNode(users=[FakeUserData(5), FakeUserData(1), FakeUserData(3)]) config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=node): c = ZLockCoordinator(hass, config_entry) await c.async_setup() sensor = ZLockSlotsSensor(c, config_entry, LOCK_ENTITY_ID) slot_nums = [s["slot_num"] for s in sensor.extra_state_attributes["slots"]] assert slot_nums == [1, 3, 5] c.async_teardown() async def test_slots_sensor_attributes_include_names(hass, config_entry, mock_node): config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=mock_node): c = ZLockCoordinator(hass, config_entry) c._names[f"{LOCK_ENTITY_ID}:1"] = "Frank" await c.async_setup() sensor = ZLockSlotsSensor(c, config_entry, LOCK_ENTITY_ID) slot1 = sensor.extra_state_attributes["slots"][0] assert slot1["name"] == "Frank" c.async_teardown() # --------------------------------------------------------------------------- # Group sensors # --------------------------------------------------------------------------- @pytest.fixture def group_config_entry(): from pytest_homeassistant_custom_component.common import MockConfigEntry from custom_components.zlock_slots.const import DOMAIN return MockConfigEntry( domain=DOMAIN, data={CONF_LOCK_ENTITY_IDS: [LOCK_ENTITY_ID]}, options={ CONF_GROUPS: [{ CONF_GROUP_NAME: "All Locks", CONF_LOCK_ENTITY_IDS: [LOCK_ENTITY_ID], }] }, entry_id="test_group_entry", ) async def test_group_last_action_initially_none(hass, group_config_entry, mock_node): group_config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=mock_node): c = ZLockCoordinator(hass, group_config_entry) await c.async_setup() sensor = ZLockGroupLastActionSensor(c, group_config_entry, "All Locks") assert sensor.native_value is None c.async_teardown() async def test_group_last_action_after_alarm(hass, group_config_entry, mock_node): group_config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=mock_node): c = ZLockCoordinator(hass, group_config_entry) await c.async_setup() hass.states.async_set(ALARM_TYPE_ENTITY, "24") await hass.async_block_till_done() sensor = ZLockGroupLastActionSensor(c, group_config_entry, "All Locks") assert sensor.native_value == "locked" c.async_teardown() async def test_group_last_user_after_alarm(hass, group_config_entry, mock_node): group_config_entry.add_to_hass(hass) with patch(_ZWAVE_HELPER, return_value=mock_node): c = ZLockCoordinator(hass, group_config_entry) await c.async_setup() hass.states.async_set(ALARM_TYPE_ENTITY, "22") await hass.async_block_till_done() sensor = ZLockGroupLastUserSensor(c, group_config_entry, "All Locks") assert sensor.native_value == "" c.async_teardown()