"""The tests the cover command line platform.""" import logging import pytest from homeassistant import setup from homeassistant.components.cover import ( ATTR_POSITION, ATTR_TILT_POSITION, DOMAIN) from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_CLOSE_COVER, SERVICE_CLOSE_COVER_TILT, SERVICE_OPEN_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_SET_COVER_POSITION, SERVICE_SET_COVER_TILT_POSITION, SERVICE_STOP_COVER, STATE_CLOSED, STATE_OPEN) from tests.common import assert_setup_component, async_mock_service _LOGGER = logging.getLogger(__name__) ENTITY_COVER = 'cover.test_template_cover' @pytest.fixture def calls(hass): """Track calls to a mock serivce.""" return async_mock_service(hass, 'test', 'automation') async def test_template_state_text(hass, calls): """Test the state text of a template.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ states.cover.test_state.state }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.async_set('cover.test_state', STATE_OPEN) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_OPEN state = hass.states.async_set('cover.test_state', STATE_CLOSED) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_CLOSED async def test_template_state_boolean(hass, calls): """Test the value_template attribute.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ 1 == 1 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_OPEN async def test_template_position(hass, calls): """Test the position_template attribute.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ states.cover.test.attributes.position }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.async_set('cover.test', STATE_CLOSED) await hass.async_block_till_done() entity = hass.states.get('cover.test') attrs = dict() attrs['position'] = 42 hass.states.async_set( entity.entity_id, entity.state, attributes=attrs) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 42.0 assert state.state == STATE_OPEN state = hass.states.async_set('cover.test', STATE_OPEN) await hass.async_block_till_done() entity = hass.states.get('cover.test') attrs['position'] = 0.0 hass.states.async_set( entity.entity_id, entity.state, attributes=attrs) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 0.0 assert state.state == STATE_CLOSED async def test_template_tilt(hass, calls): """Test the tilt_template attribute.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ 1 == 1 }}", 'tilt_template': "{{ 42 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') == 42.0 async def test_template_out_of_bounds(hass, calls): """Test template out-of-bounds condition.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ -1 }}", 'tilt_template': "{{ 110 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') is None assert state.attributes.get('current_position') is None async def test_template_mutex(hass, calls): """Test that only value or position template can be used.""" with assert_setup_component(0, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ 1 == 1 }}", 'position_template': "{{ 42 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'icon_template': "{% if states.cover.test_state.state %}" "mdi:check" "{% endif %}" } } } }) await hass.async_start() await hass.async_block_till_done() assert hass.states.async_all() == [] async def test_template_open_or_position(hass, calls): """Test that at least one of open_cover or set_position is used.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ 1 == 1 }}", } } } }) await hass.async_start() await hass.async_block_till_done() assert hass.states.async_all() == [] async def test_template_open_and_close(hass, calls): """Test that if open_cover is specified, close_cover is too.""" with assert_setup_component(0, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ 1 == 1 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, }, } } }) await hass.async_start() await hass.async_block_till_done() assert hass.states.async_all() == [] async def test_template_non_numeric(hass, calls): """Test that tilt_template values are numeric.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ on }}", 'tilt_template': "{% if states.cover.test_state.state %}" "on" "{% else %}" "off" "{% endif %}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') is None assert state.attributes.get('current_position') is None async def test_open_action(hass, calls): """Test the open_cover command.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 0 }}", 'open_cover': { 'service': 'test.automation', }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_CLOSED await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() assert len(calls) == 1 async def test_close_stop_action(hass, calls): """Test the close-cover and stop_cover commands.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 100 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'test.automation', }, 'stop_cover': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_OPEN await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() await hass.services.async_call( DOMAIN, SERVICE_STOP_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() assert len(calls) == 2 async def test_set_position(hass, calls): """Test the set_position command.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'input_number', { 'input_number': { 'test': { 'min': '0', 'max': '100', 'initial': '42', } } }) assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ states.input_number.test.state | int }}", 'set_cover_position': { 'service': 'input_number.set_value', 'entity_id': 'input_number.test', 'data_template': { 'value': '{{ position }}' }, }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.async_set('input_number.test', 42) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_OPEN await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 100.0 await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 0.0 await hass.services.async_call( DOMAIN, SERVICE_SET_COVER_POSITION, {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_POSITION: 25}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 25.0 async def test_set_tilt_position(hass, calls): """Test the set_tilt_position command.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 100 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'set_cover_tilt_position': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() await hass.services.async_call( DOMAIN, SERVICE_SET_COVER_TILT_POSITION, {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_TILT_POSITION: 42}, blocking=True) await hass.async_block_till_done() assert len(calls) == 1 async def test_open_tilt_action(hass, calls): """Test the open_cover_tilt command.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 100 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'set_cover_tilt_position': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() assert len(calls) == 1 async def test_close_tilt_action(hass, calls): """Test the close_cover_tilt command.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 100 }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'set_cover_tilt_position': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() assert len(calls) == 1 async def test_set_position_optimistic(hass, calls): """Test optimistic position mode.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'set_cover_position': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') is None await hass.services.async_call( DOMAIN, SERVICE_SET_COVER_POSITION, {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_POSITION: 42}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_position') == 42.0 await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_CLOSED await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.state == STATE_OPEN async def test_set_tilt_position_optimistic(hass, calls): """Test the optimistic tilt_position mode.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'position_template': "{{ 100 }}", 'set_cover_position': { 'service': 'test.automation', }, 'set_cover_tilt_position': { 'service': 'test.automation', }, } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') is None await hass.services.async_call( DOMAIN, SERVICE_SET_COVER_TILT_POSITION, {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_TILT_POSITION: 42}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') == 42.0 await hass.services.async_call( DOMAIN, SERVICE_CLOSE_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') == 0.0 await hass.services.async_call( DOMAIN, SERVICE_OPEN_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('current_tilt_position') == 100.0 async def test_icon_template(hass, calls): """Test icon template.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ states.cover.test_state.state }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'icon_template': "{% if states.cover.test_state.state %}" "mdi:check" "{% endif %}" } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('icon') == '' state = hass.states.async_set('cover.test_state', STATE_OPEN) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes['icon'] == 'mdi:check' async def test_entity_picture_template(hass, calls): """Test icon template.""" with assert_setup_component(1, 'cover'): assert await setup.async_setup_component(hass, 'cover', { 'cover': { 'platform': 'template', 'covers': { 'test_template_cover': { 'value_template': "{{ states.cover.test_state.state }}", 'open_cover': { 'service': 'cover.open_cover', 'entity_id': 'cover.test_state' }, 'close_cover': { 'service': 'cover.close_cover', 'entity_id': 'cover.test_state' }, 'entity_picture_template': "{% if states.cover.test_state.state %}" "/local/cover.png" "{% endif %}" } } } }) await hass.async_start() await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes.get('entity_picture') == '' state = hass.states.async_set('cover.test_state', STATE_OPEN) await hass.async_block_till_done() state = hass.states.get('cover.test_template_cover') assert state.attributes['entity_picture'] == '/local/cover.png'