From 555654fe98675502aaf570387e28988d01ccc4f0 Mon Sep 17 00:00:00 2001 From: Rolf K Date: Sat, 12 Oct 2019 18:33:33 +0200 Subject: [PATCH 1/3] Add improved scene support for input_text. --- .../components/input_text/reproduce_state.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 homeassistant/components/input_text/reproduce_state.py diff --git a/homeassistant/components/input_text/reproduce_state.py b/homeassistant/components/input_text/reproduce_state.py new file mode 100644 index 0000000000000..8781929904aa4 --- /dev/null +++ b/homeassistant/components/input_text/reproduce_state.py @@ -0,0 +1,44 @@ +"""Reproduce an Input text state.""" +import asyncio +import logging +from typing import Iterable, Optional + +from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.core import Context, State +from homeassistant.helpers.typing import HomeAssistantType + +from . import DOMAIN, SERVICE_SET_VALUE, ATTR_VALUE + +_LOGGER = logging.getLogger(__name__) + + +async def _async_reproduce_state( + hass: HomeAssistantType, state: State, context: Optional[Context] = None +) -> None: + """Reproduce a single state.""" + cur_state = hass.states.get(state.entity_id) + + if cur_state is None: + _LOGGER.warning("Unable to find entity %s", state.entity_id) + return + + # Return if we are already at the right state. + if cur_state.state == state.state: + return + + service = SERVICE_SET_VALUE + service_data = {ATTR_ENTITY_ID: state.entity_id, ATTR_VALUE: state.state} + + await hass.services.async_call( + DOMAIN, service, service_data, context=context, blocking=True + ) + + +async def async_reproduce_states( + hass: HomeAssistantType, states: Iterable[State], context: Optional[Context] = None +) -> None: + """Reproduce Input text states.""" + # Reproduce states in parallel. + await asyncio.gather( + *(_async_reproduce_state(hass, state, context) for state in states) + ) From e5c11d6eae133422542fa3fc62c4b1bc5b7de612 Mon Sep 17 00:00:00 2001 From: Rolf K Date: Sat, 12 Oct 2019 18:34:07 +0200 Subject: [PATCH 2/3] Add tests for reproducing input_text states. --- .../input_text/test_reproduce_state.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/components/input_text/test_reproduce_state.py diff --git a/tests/components/input_text/test_reproduce_state.py b/tests/components/input_text/test_reproduce_state.py new file mode 100644 index 0000000000000..eb4b81d1cc64b --- /dev/null +++ b/tests/components/input_text/test_reproduce_state.py @@ -0,0 +1,62 @@ +"""Test reproduce state for Input text.""" +from homeassistant.core import State +from homeassistant.setup import async_setup_component + +VALID_TEXT1 = "Test text" +VALID_TEXT2 = "LoremIpsum" +INVALID_TEXT1 = "This text is too long!" +INVALID_TEXT2 = "Short" + + +async def test_reproducing_states(hass, caplog): + """Test reproducing Input text states.""" + + assert await async_setup_component( + hass, + "input_text", + { + "input_text": { + "test_text": {"min": "6", "max": "10", "initial": VALID_TEXT1} + } + }, + ) + + # These calls should do nothing as entities already in desired state + await hass.helpers.state.async_reproduce_state( + [ + State("input_text.test_text", VALID_TEXT1), + # Should not raise + State("input_text.non_existing", VALID_TEXT1), + ], + blocking=True, + ) + + assert hass.states.get("input_text.test_text").state == VALID_TEXT1 + + # Test reproducing with different state + await hass.helpers.state.async_reproduce_state( + [ + State("input_text.test_text", VALID_TEXT2), + # Should not raise + State("input_text.non_existing", VALID_TEXT2), + ], + blocking=True, + ) + + assert hass.states.get("input_text.test_text").state == VALID_TEXT2 + + # Test setting state to invalid state (length too long) + await hass.helpers.state.async_reproduce_state( + [State("input_text.test_text", INVALID_TEXT1)], blocking=True + ) + + # The entity state should be unchanged + assert hass.states.get("input_text.test_text").state == VALID_TEXT2 + + # Test setting state to invalid state (length too short) + await hass.helpers.state.async_reproduce_state( + [State("input_text.test_text", INVALID_TEXT2)], blocking=True + ) + + # The entity state should be unchanged + assert hass.states.get("input_text.test_text").state == VALID_TEXT2 From 1560dff1e1b483824684e3d05febfc3c5de7aa29 Mon Sep 17 00:00:00 2001 From: Rolf K Date: Tue, 15 Oct 2019 10:36:52 +0200 Subject: [PATCH 3/3] Add some comments. --- homeassistant/components/input_text/reproduce_state.py | 2 ++ tests/components/input_text/test_reproduce_state.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/input_text/reproduce_state.py b/homeassistant/components/input_text/reproduce_state.py index 8781929904aa4..f64c5c019f65d 100644 --- a/homeassistant/components/input_text/reproduce_state.py +++ b/homeassistant/components/input_text/reproduce_state.py @@ -18,6 +18,7 @@ async def _async_reproduce_state( """Reproduce a single state.""" cur_state = hass.states.get(state.entity_id) + # Return if we can't find the entity if cur_state is None: _LOGGER.warning("Unable to find entity %s", state.entity_id) return @@ -26,6 +27,7 @@ async def _async_reproduce_state( if cur_state.state == state.state: return + # Call service service = SERVICE_SET_VALUE service_data = {ATTR_ENTITY_ID: state.entity_id, ATTR_VALUE: state.state} diff --git a/tests/components/input_text/test_reproduce_state.py b/tests/components/input_text/test_reproduce_state.py index eb4b81d1cc64b..fd75948d4618c 100644 --- a/tests/components/input_text/test_reproduce_state.py +++ b/tests/components/input_text/test_reproduce_state.py @@ -11,6 +11,7 @@ async def test_reproducing_states(hass, caplog): """Test reproducing Input text states.""" + # Setup entity for testing assert await async_setup_component( hass, "input_text", @@ -31,9 +32,10 @@ async def test_reproducing_states(hass, caplog): blocking=True, ) + # Test that entity is in desired state assert hass.states.get("input_text.test_text").state == VALID_TEXT1 - # Test reproducing with different state + # Try reproducing with different state await hass.helpers.state.async_reproduce_state( [ State("input_text.test_text", VALID_TEXT2), @@ -43,6 +45,7 @@ async def test_reproducing_states(hass, caplog): blocking=True, ) + # Test that the state was changed assert hass.states.get("input_text.test_text").state == VALID_TEXT2 # Test setting state to invalid state (length too long)