"""Test state helpers.""" import asyncio from datetime import timedelta from unittest.mock import patch import pytest import homeassistant.core as ha from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TURN_OFF) from homeassistant.util import dt as dt_util from homeassistant.helpers import state from homeassistant.const import ( STATE_OPEN, STATE_CLOSED, STATE_LOCKED, STATE_UNLOCKED, STATE_ON, STATE_OFF, STATE_HOME, STATE_NOT_HOME) from homeassistant.components.sun import (STATE_ABOVE_HORIZON, STATE_BELOW_HORIZON) from tests.common import async_mock_service @asyncio.coroutine def test_async_track_states(hass): """Test AsyncTrackStates context manager.""" point1 = dt_util.utcnow() point2 = point1 + timedelta(seconds=5) point3 = point2 + timedelta(seconds=5) with patch('homeassistant.core.dt_util.utcnow') as mock_utcnow: mock_utcnow.return_value = point2 with state.AsyncTrackStates(hass) as states: mock_utcnow.return_value = point1 hass.states.async_set('light.test', 'on') mock_utcnow.return_value = point2 hass.states.async_set('light.test2', 'on') state2 = hass.states.get('light.test2') mock_utcnow.return_value = point3 hass.states.async_set('light.test3', 'on') state3 = hass.states.get('light.test3') assert [state2, state3] == \ sorted(states, key=lambda state: state.entity_id) @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) async def test_get_changed_since(hass): """Test get_changed_since.""" point1 = dt_util.utcnow() point2 = point1 + timedelta(seconds=5) point3 = point2 + timedelta(seconds=5) with patch('homeassistant.core.dt_util.utcnow', return_value=point1): hass.states.async_set('light.test', 'on') state1 = hass.states.get('light.test') with patch('homeassistant.core.dt_util.utcnow', return_value=point2): hass.states.async_set('light.test2', 'on') state2 = hass.states.get('light.test2') with patch('homeassistant.core.dt_util.utcnow', return_value=point3): hass.states.async_set('light.test3', 'on') state3 = hass.states.get('light.test3') assert [state2, state3] == \ state.get_changed_since([state1, state2, state3], point2) async def test_reproduce_with_no_entity(hass): """Test reproduce_state with no entity.""" calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) await state.async_reproduce_state(hass, ha.State('light.test', 'on')) await hass.async_block_till_done() assert len(calls) == 0 assert hass.states.get('light.test') is None async def test_reproduce_turn_on(hass): """Test reproduce_state with SERVICE_TURN_ON.""" calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) hass.states.async_set('light.test', 'off') await state.async_reproduce_state(hass, ha.State('light.test', 'on')) await hass.async_block_till_done() assert len(calls) > 0 last_call = calls[-1] assert last_call.domain == 'light' assert SERVICE_TURN_ON == last_call.service assert ['light.test'] == last_call.data.get('entity_id') async def test_reproduce_turn_off(hass): """Test reproduce_state with SERVICE_TURN_OFF.""" calls = async_mock_service(hass, 'light', SERVICE_TURN_OFF) hass.states.async_set('light.test', 'on') await state.async_reproduce_state(hass, ha.State('light.test', 'off')) await hass.async_block_till_done() assert len(calls) > 0 last_call = calls[-1] assert last_call.domain == 'light' assert SERVICE_TURN_OFF == last_call.service assert ['light.test'] == last_call.data.get('entity_id') async def test_reproduce_complex_data(hass): """Test reproduce_state with complex service data.""" calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) hass.states.async_set('light.test', 'off') complex_data = ['hello', {'11': '22'}] await state.async_reproduce_state(hass, ha.State('light.test', 'on', { 'complex': complex_data })) await hass.async_block_till_done() assert len(calls) > 0 last_call = calls[-1] assert last_call.domain == 'light' assert SERVICE_TURN_ON == last_call.service assert complex_data == last_call.data.get('complex') async def test_reproduce_bad_state(hass): """Test reproduce_state with bad state.""" calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) hass.states.async_set('light.test', 'off') await state.async_reproduce_state(hass, ha.State('light.test', 'bad')) await hass.async_block_till_done() assert len(calls) == 0 assert hass.states.get('light.test').state == 'off' async def test_as_number_states(hass): """Test state_as_number with states.""" zero_states = (STATE_OFF, STATE_CLOSED, STATE_UNLOCKED, STATE_BELOW_HORIZON, STATE_NOT_HOME) one_states = (STATE_ON, STATE_OPEN, STATE_LOCKED, STATE_ABOVE_HORIZON, STATE_HOME) for _state in zero_states: assert state.state_as_number(ha.State('domain.test', _state, {})) == 0 for _state in one_states: assert state.state_as_number(ha.State('domain.test', _state, {})) == 1 async def test_as_number_coercion(hass): """Test state_as_number with number.""" for _state in ('0', '0.0', 0, 0.0): assert state.state_as_number( ha.State('domain.test', _state, {})) == 0.0 for _state in ('1', '1.0', 1, 1.0): assert state.state_as_number( ha.State('domain.test', _state, {})) == 1.0 async def test_as_number_invalid_cases(hass): """Test state_as_number with invalid cases.""" for _state in ('', 'foo', 'foo.bar', None, False, True, object, object()): with pytest.raises(ValueError): state.state_as_number(ha.State('domain.test', _state, {}))