"""The tests for the Group Lock platform.""" from unittest.mock import patch from homeassistant import config as hass_config from homeassistant.components.demo import lock as demo_lock from homeassistant.components.group import DOMAIN, SERVICE_RELOAD from homeassistant.components.lock import ( DOMAIN as LOCK_DOMAIN, SERVICE_LOCK, SERVICE_OPEN, SERVICE_UNLOCK, ) from homeassistant.const import ( ATTR_ENTITY_ID, STATE_JAMMED, STATE_LOCKED, STATE_LOCKING, STATE_UNAVAILABLE, STATE_UNKNOWN, STATE_UNLOCKED, STATE_UNLOCKING, ) from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component from tests.common import get_fixture_path async def test_default_state(hass): """Test lock group default state.""" hass.states.async_set("lock.front", "locked") await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: { "platform": DOMAIN, "entities": ["lock.front", "lock.back"], "name": "Door Group", "unique_id": "unique_identifier", } }, ) await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() state = hass.states.get("lock.door_group") assert state is not None assert state.state == STATE_LOCKED assert state.attributes.get(ATTR_ENTITY_ID) == ["lock.front", "lock.back"] entity_registry = er.async_get(hass) entry = entity_registry.async_get("lock.door_group") assert entry assert entry.unique_id == "unique_identifier" async def test_state_reporting(hass): """Test the state reporting.""" await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: { "platform": DOMAIN, "entities": ["lock.test1", "lock.test2"], } }, ) await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() hass.states.async_set("lock.test1", STATE_LOCKED) hass.states.async_set("lock.test2", STATE_UNAVAILABLE) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNKNOWN hass.states.async_set("lock.test1", STATE_LOCKED) hass.states.async_set("lock.test2", STATE_UNLOCKED) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED hass.states.async_set("lock.test1", STATE_LOCKED) hass.states.async_set("lock.test2", STATE_LOCKED) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_LOCKED hass.states.async_set("lock.test1", STATE_UNLOCKED) hass.states.async_set("lock.test2", STATE_UNLOCKED) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED hass.states.async_set("lock.test1", STATE_UNLOCKED) hass.states.async_set("lock.test2", STATE_JAMMED) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_JAMMED hass.states.async_set("lock.test1", STATE_LOCKED) hass.states.async_set("lock.test2", STATE_UNLOCKING) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNLOCKING hass.states.async_set("lock.test1", STATE_UNLOCKED) hass.states.async_set("lock.test2", STATE_LOCKING) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_LOCKING hass.states.async_set("lock.test1", STATE_UNAVAILABLE) hass.states.async_set("lock.test2", STATE_UNAVAILABLE) await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNAVAILABLE @patch.object(demo_lock, "LOCK_UNLOCK_DELAY", 0) async def test_service_calls(hass, enable_custom_integrations): """Test service calls.""" await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: [ {"platform": "demo"}, { "platform": DOMAIN, "entities": [ "lock.front_door", "lock.kitchen_door", ], }, ] }, ) await hass.async_block_till_done() group_state = hass.states.get("lock.lock_group") assert group_state.state == STATE_UNLOCKED assert hass.states.get("lock.front_door").state == STATE_LOCKED assert hass.states.get("lock.kitchen_door").state == STATE_UNLOCKED await hass.services.async_call( LOCK_DOMAIN, SERVICE_OPEN, {ATTR_ENTITY_ID: "lock.lock_group"}, blocking=True, ) assert hass.states.get("lock.front_door").state == STATE_UNLOCKED assert hass.states.get("lock.kitchen_door").state == STATE_UNLOCKED await hass.services.async_call( LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.lock_group"}, blocking=True, ) assert hass.states.get("lock.front_door").state == STATE_LOCKED assert hass.states.get("lock.kitchen_door").state == STATE_LOCKED await hass.services.async_call( LOCK_DOMAIN, SERVICE_UNLOCK, {ATTR_ENTITY_ID: "lock.lock_group"}, blocking=True, ) assert hass.states.get("lock.front_door").state == STATE_UNLOCKED assert hass.states.get("lock.kitchen_door").state == STATE_UNLOCKED async def test_reload(hass): """Test the ability to reload locks.""" await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: [ {"platform": "demo"}, { "platform": DOMAIN, "entities": [ "lock.front_door", "lock.kitchen_door", ], }, ] }, ) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() assert hass.states.get("lock.lock_group").state == STATE_UNLOCKED yaml_path = get_fixture_path("configuration.yaml", "group") with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path): await hass.services.async_call( DOMAIN, SERVICE_RELOAD, {}, blocking=True, ) await hass.async_block_till_done() assert hass.states.get("lock.lock_group") is None assert hass.states.get("lock.inside_locks_g") is not None assert hass.states.get("lock.outside_locks_g") is not None async def test_reload_with_platform_not_setup(hass): """Test the ability to reload locks.""" hass.states.async_set("lock.something", STATE_UNLOCKED) await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: [ {"platform": "demo"}, ] }, ) assert await async_setup_component( hass, "group", { "group": { "group_zero": {"entities": "lock.something", "icon": "mdi:work"}, } }, ) await hass.async_block_till_done() yaml_path = get_fixture_path("configuration.yaml", "group") with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path): await hass.services.async_call( DOMAIN, SERVICE_RELOAD, {}, blocking=True, ) await hass.async_block_till_done() assert hass.states.get("lock.lock_group") is None assert hass.states.get("lock.inside_locks_g") is not None assert hass.states.get("lock.outside_locks_g") is not None async def test_reload_with_base_integration_platform_not_setup(hass): """Test the ability to reload locks.""" assert await async_setup_component( hass, "group", { "group": { "group_zero": {"entities": "lock.something", "icon": "mdi:work"}, } }, ) await hass.async_block_till_done() hass.states.async_set("lock.front_lock", STATE_LOCKED) hass.states.async_set("lock.back_lock", STATE_UNLOCKED) hass.states.async_set("lock.outside_lock", STATE_LOCKED) hass.states.async_set("lock.outside_lock_2", STATE_LOCKED) yaml_path = get_fixture_path("configuration.yaml", "group") with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path): await hass.services.async_call( DOMAIN, SERVICE_RELOAD, {}, blocking=True, ) await hass.async_block_till_done() assert hass.states.get("lock.lock_group") is None assert hass.states.get("lock.inside_locks_g") is not None assert hass.states.get("lock.outside_locks_g") is not None assert hass.states.get("lock.inside_locks_g").state == STATE_UNLOCKED assert hass.states.get("lock.outside_locks_g").state == STATE_LOCKED @patch.object(demo_lock, "LOCK_UNLOCK_DELAY", 0) async def test_nested_group(hass): """Test nested lock group.""" await async_setup_component( hass, LOCK_DOMAIN, { LOCK_DOMAIN: [ {"platform": "demo"}, { "platform": DOMAIN, "entities": ["lock.some_group"], "name": "Nested Group", }, { "platform": DOMAIN, "entities": [ "lock.front_door", "lock.kitchen_door", ], "name": "Some Group", }, ] }, ) await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() state = hass.states.get("lock.some_group") assert state is not None assert state.state == STATE_UNLOCKED assert state.attributes.get(ATTR_ENTITY_ID) == [ "lock.front_door", "lock.kitchen_door", ] state = hass.states.get("lock.nested_group") assert state is not None assert state.state == STATE_UNLOCKED assert state.attributes.get(ATTR_ENTITY_ID) == ["lock.some_group"] # Test controlling the nested group await hass.services.async_call( LOCK_DOMAIN, SERVICE_LOCK, {ATTR_ENTITY_ID: "lock.nested_group"}, blocking=True, ) assert hass.states.get("lock.front_door").state == STATE_LOCKED assert hass.states.get("lock.kitchen_door").state == STATE_LOCKED assert hass.states.get("lock.some_group").state == STATE_LOCKED assert hass.states.get("lock.nested_group").state == STATE_LOCKED