2016-03-09 09:25:50 +00:00
|
|
|
"""Test state helpers."""
|
2016-10-24 06:48:01 +00:00
|
|
|
import asyncio
|
2016-01-03 10:32:09 +00:00
|
|
|
from datetime import timedelta
|
|
|
|
import unittest
|
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
|
|
import homeassistant.core as ha
|
2019-03-26 12:38:33 +00:00
|
|
|
from homeassistant.setup import async_setup_component
|
2016-03-06 03:32:28 +00:00
|
|
|
from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TURN_OFF)
|
2018-03-11 17:01:12 +00:00
|
|
|
from homeassistant.util.async_ import run_coroutine_threadsafe
|
2016-01-03 10:32:09 +00:00
|
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from homeassistant.helpers import state
|
2016-02-11 17:10:34 +00:00
|
|
|
from homeassistant.const import (
|
2016-02-14 21:07:21 +00:00
|
|
|
STATE_OPEN, STATE_CLOSED,
|
|
|
|
STATE_LOCKED, STATE_UNLOCKED,
|
2017-07-11 04:20:17 +00:00
|
|
|
STATE_ON, STATE_OFF,
|
|
|
|
STATE_HOME, STATE_NOT_HOME)
|
2016-02-11 17:10:34 +00:00
|
|
|
from homeassistant.components.sun import (STATE_ABOVE_HORIZON,
|
|
|
|
STATE_BELOW_HORIZON)
|
2016-01-03 10:32:09 +00:00
|
|
|
|
|
|
|
from tests.common import get_test_home_assistant, mock_service
|
2018-10-24 10:10:05 +00:00
|
|
|
import pytest
|
2016-01-03 10:32:09 +00:00
|
|
|
|
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def test_async_track_states(hass):
|
2016-10-24 06:48:01 +00:00
|
|
|
"""Test AsyncTrackStates context manager."""
|
2017-05-26 04:40:36 +00:00
|
|
|
point1 = dt_util.utcnow()
|
|
|
|
point2 = point1 + timedelta(seconds=5)
|
|
|
|
point3 = point2 + timedelta(seconds=5)
|
2016-10-24 06:48:01 +00:00
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow:
|
|
|
|
mock_utcnow.return_value = point2
|
2016-10-24 06:48:01 +00:00
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
with state.AsyncTrackStates(hass) as states:
|
|
|
|
mock_utcnow.return_value = point1
|
|
|
|
hass.states.async_set('light.test', 'on')
|
2016-10-24 06:48:01 +00:00
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
mock_utcnow.return_value = point2
|
|
|
|
hass.states.async_set('light.test2', 'on')
|
|
|
|
state2 = hass.states.get('light.test2')
|
2016-10-24 06:48:01 +00:00
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
mock_utcnow.return_value = point3
|
|
|
|
hass.states.async_set('light.test3', 'on')
|
|
|
|
state3 = hass.states.get('light.test3')
|
2016-10-24 06:48:01 +00:00
|
|
|
|
2017-05-26 04:40:36 +00:00
|
|
|
assert [state2, state3] == \
|
|
|
|
sorted(states, key=lambda state: state.entity_id)
|
2016-10-24 06:48:01 +00:00
|
|
|
|
|
|
|
|
2019-02-06 01:25:27 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def test_call_to_component(hass):
|
|
|
|
"""Test calls to components state reproduction functions."""
|
|
|
|
with patch(('homeassistant.components.media_player.'
|
|
|
|
'async_reproduce_states')) as media_player_fun:
|
|
|
|
media_player_fun.return_value = asyncio.Future()
|
|
|
|
media_player_fun.return_value.set_result(None)
|
|
|
|
|
|
|
|
with patch(('homeassistant.components.climate.'
|
|
|
|
'async_reproduce_states')) as climate_fun:
|
|
|
|
climate_fun.return_value = asyncio.Future()
|
|
|
|
climate_fun.return_value.set_result(None)
|
|
|
|
|
|
|
|
state_media_player = ha.State('media_player.test', 'bad')
|
|
|
|
state_climate = ha.State('climate.test', 'bad')
|
|
|
|
context = "dummy_context"
|
|
|
|
|
|
|
|
yield from state.async_reproduce_state(
|
|
|
|
hass,
|
|
|
|
[state_media_player, state_climate],
|
|
|
|
blocking=True,
|
|
|
|
context=context)
|
|
|
|
|
|
|
|
media_player_fun.assert_called_once_with(
|
|
|
|
hass,
|
|
|
|
[state_media_player],
|
|
|
|
context=context)
|
|
|
|
|
|
|
|
climate_fun.assert_called_once_with(
|
|
|
|
hass,
|
|
|
|
[state_climate],
|
|
|
|
context=context)
|
|
|
|
|
|
|
|
|
2016-01-03 10:32:09 +00:00
|
|
|
class TestStateHelpers(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test the Home Assistant event helpers."""
|
2016-01-03 10:32:09 +00:00
|
|
|
|
|
|
|
def setUp(self): # pylint: disable=invalid-name
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Run when tests are started."""
|
2016-01-03 10:32:09 +00:00
|
|
|
self.hass = get_test_home_assistant()
|
2019-03-26 12:38:33 +00:00
|
|
|
run_coroutine_threadsafe(async_setup_component(
|
|
|
|
self.hass, 'homeassistant', {}), self.hass.loop).result()
|
2016-01-03 10:32:09 +00:00
|
|
|
|
|
|
|
def tearDown(self): # pylint: disable=invalid-name
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Stop when tests are finished."""
|
2016-01-03 10:32:09 +00:00
|
|
|
self.hass.stop()
|
|
|
|
|
|
|
|
def test_get_changed_since(self):
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Test get_changed_since."""
|
2016-01-03 10:32:09 +00:00
|
|
|
point1 = dt_util.utcnow()
|
|
|
|
point2 = point1 + timedelta(seconds=5)
|
|
|
|
point3 = point2 + timedelta(seconds=5)
|
|
|
|
|
|
|
|
with patch('homeassistant.core.dt_util.utcnow', return_value=point1):
|
|
|
|
self.hass.states.set('light.test', 'on')
|
|
|
|
state1 = self.hass.states.get('light.test')
|
|
|
|
|
|
|
|
with patch('homeassistant.core.dt_util.utcnow', return_value=point2):
|
|
|
|
self.hass.states.set('light.test2', 'on')
|
|
|
|
state2 = self.hass.states.get('light.test2')
|
|
|
|
|
|
|
|
with patch('homeassistant.core.dt_util.utcnow', return_value=point3):
|
|
|
|
self.hass.states.set('light.test3', 'on')
|
|
|
|
state3 = self.hass.states.get('light.test3')
|
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert [state2, state3] == \
|
|
|
|
state.get_changed_since([state1, state2, state3], point2)
|
2016-01-03 10:32:09 +00:00
|
|
|
|
2016-03-06 03:32:28 +00:00
|
|
|
def test_reproduce_with_no_entity(self):
|
|
|
|
"""Test reproduce_state with no entity."""
|
|
|
|
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
|
|
|
|
|
|
|
|
state.reproduce_state(self.hass, ha.State('light.test', 'on'))
|
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-03-06 03:32:28 +00:00
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert len(calls) == 0
|
|
|
|
assert self.hass.states.get('light.test') is None
|
2016-03-06 03:32:28 +00:00
|
|
|
|
|
|
|
def test_reproduce_turn_on(self):
|
|
|
|
"""Test reproduce_state with SERVICE_TURN_ON."""
|
2016-01-03 10:32:09 +00:00
|
|
|
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
|
|
|
|
|
|
|
|
self.hass.states.set('light.test', 'off')
|
|
|
|
|
|
|
|
state.reproduce_state(self.hass, ha.State('light.test', 'on'))
|
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-01-03 10:32:09 +00:00
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert len(calls) > 0
|
2016-01-03 10:32:09 +00:00
|
|
|
last_call = calls[-1]
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 'light' == last_call.domain
|
|
|
|
assert SERVICE_TURN_ON == last_call.service
|
|
|
|
assert ['light.test'] == last_call.data.get('entity_id')
|
2016-01-03 10:32:09 +00:00
|
|
|
|
2016-03-06 03:32:28 +00:00
|
|
|
def test_reproduce_turn_off(self):
|
|
|
|
"""Test reproduce_state with SERVICE_TURN_OFF."""
|
|
|
|
calls = mock_service(self.hass, 'light', SERVICE_TURN_OFF)
|
|
|
|
|
|
|
|
self.hass.states.set('light.test', 'on')
|
|
|
|
|
|
|
|
state.reproduce_state(self.hass, ha.State('light.test', 'off'))
|
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-03-06 03:32:28 +00:00
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert len(calls) > 0
|
2016-03-06 03:32:28 +00:00
|
|
|
last_call = calls[-1]
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 'light' == last_call.domain
|
|
|
|
assert SERVICE_TURN_OFF == last_call.service
|
|
|
|
assert ['light.test'] == last_call.data.get('entity_id')
|
2016-03-06 03:32:28 +00:00
|
|
|
|
|
|
|
def test_reproduce_complex_data(self):
|
|
|
|
"""Test reproduce_state with complex service data."""
|
2016-01-03 19:27:30 +00:00
|
|
|
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
|
|
|
|
|
|
|
|
self.hass.states.set('light.test', 'off')
|
|
|
|
|
|
|
|
complex_data = ['hello', {'11': '22'}]
|
|
|
|
|
|
|
|
state.reproduce_state(self.hass, ha.State('light.test', 'on', {
|
|
|
|
'complex': complex_data
|
|
|
|
}))
|
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-01-03 19:27:30 +00:00
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert len(calls) > 0
|
2016-01-03 19:27:30 +00:00
|
|
|
last_call = calls[-1]
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 'light' == last_call.domain
|
|
|
|
assert SERVICE_TURN_ON == last_call.service
|
|
|
|
assert complex_data == last_call.data.get('complex')
|
2016-01-03 19:27:30 +00:00
|
|
|
|
2016-03-06 03:32:28 +00:00
|
|
|
def test_reproduce_bad_state(self):
|
|
|
|
"""Test reproduce_state with bad state."""
|
|
|
|
calls = mock_service(self.hass, 'light', SERVICE_TURN_ON)
|
|
|
|
|
|
|
|
self.hass.states.set('light.test', 'off')
|
|
|
|
|
|
|
|
state.reproduce_state(self.hass, ha.State('light.test', 'bad'))
|
|
|
|
|
2016-09-13 02:16:14 +00:00
|
|
|
self.hass.block_till_done()
|
2016-03-06 03:32:28 +00:00
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert len(calls) == 0
|
|
|
|
assert 'off' == self.hass.states.get('light.test').state
|
2016-03-06 03:32:28 +00:00
|
|
|
|
2016-02-11 17:10:34 +00:00
|
|
|
def test_as_number_states(self):
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Test state_as_number with states."""
|
2016-02-11 17:10:34 +00:00
|
|
|
zero_states = (STATE_OFF, STATE_CLOSED, STATE_UNLOCKED,
|
2017-07-11 04:20:17 +00:00
|
|
|
STATE_BELOW_HORIZON, STATE_NOT_HOME)
|
|
|
|
one_states = (STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_ABOVE_HORIZON,
|
|
|
|
STATE_HOME)
|
2016-02-11 17:10:34 +00:00
|
|
|
for _state in zero_states:
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 0 == state.state_as_number(
|
|
|
|
ha.State('domain.test', _state, {}))
|
2016-02-11 17:10:34 +00:00
|
|
|
for _state in one_states:
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 1 == state.state_as_number(
|
|
|
|
ha.State('domain.test', _state, {}))
|
2016-02-11 17:10:34 +00:00
|
|
|
|
|
|
|
def test_as_number_coercion(self):
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Test state_as_number with number."""
|
2016-02-13 08:08:32 +00:00
|
|
|
for _state in ('0', '0.0', 0, 0.0):
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 0.0 == state.state_as_number(
|
|
|
|
ha.State('domain.test', _state, {}))
|
2016-02-13 08:08:32 +00:00
|
|
|
for _state in ('1', '1.0', 1, 1.0):
|
2018-10-24 10:10:05 +00:00
|
|
|
assert 1.0 == state.state_as_number(
|
|
|
|
ha.State('domain.test', _state, {}))
|
2016-02-11 17:10:34 +00:00
|
|
|
|
|
|
|
def test_as_number_invalid_cases(self):
|
2016-03-06 03:32:28 +00:00
|
|
|
"""Test state_as_number with invalid cases."""
|
2016-02-13 08:08:32 +00:00
|
|
|
for _state in ('', 'foo', 'foo.bar', None, False, True, object,
|
|
|
|
object()):
|
2018-10-24 10:10:05 +00:00
|
|
|
with pytest.raises(ValueError):
|
|
|
|
state.state_as_number(ha.State('domain.test', _state, {}))
|