From 945afbc6d4eedbaf013ee9b18c8ed2407c59d3d5 Mon Sep 17 00:00:00 2001 From: Phil Bruckner Date: Tue, 2 Jul 2019 10:28:02 -0500 Subject: [PATCH] Fix 'same state' monitoring in numeric_state trigger (#24910) --- .../components/automation/numeric_state.py | 2 +- .../automation/test_numeric_state.py | 103 ++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py index bf45abb88f0..0ac9ae139f3 100644 --- a/homeassistant/components/automation/numeric_state.py +++ b/homeassistant/components/automation/numeric_state.py @@ -79,7 +79,7 @@ async def async_trigger(hass, config, action, automation_info): if time_delta: unsub_track_same[entity] = async_track_same_state( - hass, time_delta, call_action, entity_ids=entity_id, + hass, time_delta, call_action, entity_ids=entity, async_check_same_func=check_numeric_state) else: call_action() diff --git a/tests/components/automation/test_numeric_state.py b/tests/components/automation/test_numeric_state.py index 86a1a3daff5..8643bebd8bd 100644 --- a/tests/components/automation/test_numeric_state.py +++ b/tests/components/automation/test_numeric_state.py @@ -906,3 +906,106 @@ async def test_wait_template_with_trigger(hass, calls): assert 1 == len(calls) assert 'numeric_state - test.entity - 12' == \ calls[0].data['some'] + + +async def test_if_fires_on_entities_change_no_overlap(hass, calls): + """Test for firing on entities change with no overlap.""" + assert await async_setup_component(hass, automation.DOMAIN, { + automation.DOMAIN: { + 'trigger': { + 'platform': 'numeric_state', + 'entity_id': [ + 'test.entity_1', + 'test.entity_2', + ], + 'above': 8, + 'below': 12, + 'for': { + 'seconds': 5 + }, + }, + 'action': { + 'service': 'test.automation', + 'data_template': { + 'some': '{{ trigger.entity_id }}', + }, + } + } + }) + await hass.async_block_till_done() + + utcnow = dt_util.utcnow() + with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow: + mock_utcnow.return_value = utcnow + hass.states.async_set('test.entity_1', 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=10) + async_fire_time_changed(hass, mock_utcnow.return_value) + await hass.async_block_till_done() + assert 1 == len(calls) + assert 'test.entity_1' == calls[0].data['some'] + + hass.states.async_set('test.entity_2', 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=10) + async_fire_time_changed(hass, mock_utcnow.return_value) + await hass.async_block_till_done() + assert 2 == len(calls) + assert 'test.entity_2' == calls[1].data['some'] + + +async def test_if_fires_on_entities_change_overlap(hass, calls): + """Test for firing on entities change with overlap.""" + assert await async_setup_component(hass, automation.DOMAIN, { + automation.DOMAIN: { + 'trigger': { + 'platform': 'numeric_state', + 'entity_id': [ + 'test.entity_1', + 'test.entity_2', + ], + 'above': 8, + 'below': 12, + 'for': { + 'seconds': 5 + }, + }, + 'action': { + 'service': 'test.automation', + 'data_template': { + 'some': '{{ trigger.entity_id }}', + }, + } + } + }) + await hass.async_block_till_done() + + utcnow = dt_util.utcnow() + with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow: + mock_utcnow.return_value = utcnow + hass.states.async_set('test.entity_1', 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set('test.entity_2', 9) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set('test.entity_2', 15) + await hass.async_block_till_done() + mock_utcnow.return_value += timedelta(seconds=1) + async_fire_time_changed(hass, mock_utcnow.return_value) + hass.states.async_set('test.entity_2', 9) + await hass.async_block_till_done() + assert 0 == len(calls) + mock_utcnow.return_value += timedelta(seconds=3) + async_fire_time_changed(hass, mock_utcnow.return_value) + await hass.async_block_till_done() + assert 1 == len(calls) + assert 'test.entity_1' == calls[0].data['some'] + + mock_utcnow.return_value += timedelta(seconds=3) + async_fire_time_changed(hass, mock_utcnow.return_value) + await hass.async_block_till_done() + assert 2 == len(calls) + assert 'test.entity_2' == calls[1].data['some']