core/tests/helpers/test_template.py

526 lines
17 KiB
Python
Raw Normal View History

2016-03-09 09:25:50 +00:00
"""Test Home Assistant template helper methods."""
2015-12-10 00:20:09 +00:00
# pylint: disable=too-many-public-methods
import unittest
from unittest.mock import patch
2016-02-21 19:13:40 +00:00
from homeassistant.components import group
from homeassistant.exceptions import TemplateError
2016-02-23 20:06:50 +00:00
from homeassistant.helpers import template
import homeassistant.util.dt as dt_util
2015-12-10 00:20:09 +00:00
2016-02-14 23:08:23 +00:00
from tests.common import get_test_home_assistant
2015-12-10 00:20:09 +00:00
class TestUtilTemplate(unittest.TestCase):
2016-03-09 09:25:50 +00:00
"""Test the Template."""
2015-12-10 00:20:09 +00:00
def setUp(self): # pylint: disable=invalid-name
2016-03-09 09:25:50 +00:00
"""Setup the tests."""
2016-02-14 23:08:23 +00:00
self.hass = get_test_home_assistant()
2015-12-10 00:20:09 +00:00
def tearDown(self): # pylint: disable=invalid-name
2016-02-23 20:06:50 +00:00
"""Stop down stuff we started."""
2015-12-10 00:20:09 +00:00
self.hass.stop()
def test_referring_states_by_entity_id(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-10 00:20:09 +00:00
self.hass.states.set('test.object', 'happy')
self.assertEqual(
'happy',
template.render(self.hass, '{{ states.test.object.state }}'))
def test_iterating_all_states(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-10 00:20:09 +00:00
self.hass.states.set('test.object', 'happy')
self.hass.states.set('sensor.temperature', 10)
self.assertEqual(
'10happy',
template.render(
self.hass,
'{% for state in states %}{{ state.state }}{% endfor %}'))
def test_iterating_domain_states(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-10 00:20:09 +00:00
self.hass.states.set('test.object', 'happy')
self.hass.states.set('sensor.back_door', 'open')
self.hass.states.set('sensor.temperature', 10)
self.assertEqual(
'open10',
template.render(
self.hass,
2016-02-14 21:07:21 +00:00
"""
{% for state in states.sensor %}{{ state.state }}{% endfor %}
"""))
2015-12-10 00:20:09 +00:00
2016-02-24 18:41:49 +00:00
def test_float(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-24 18:41:49 +00:00
self.hass.states.set('sensor.temperature', '12')
self.assertEqual(
'12.0',
template.render(
self.hass,
'{{ float(states.sensor.temperature.state) }}'))
self.assertEqual(
'True',
template.render(
self.hass,
'{{ float(states.sensor.temperature.state) > 11 }}'))
2015-12-10 00:20:09 +00:00
def test_rounding_value(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-11 04:46:15 +00:00
self.hass.states.set('sensor.temperature', 12.78)
2015-12-10 00:20:09 +00:00
self.assertEqual(
2015-12-11 04:46:15 +00:00
'12.8',
2015-12-10 00:20:09 +00:00
template.render(
self.hass,
'{{ states.sensor.temperature.state | round(1) }}'))
2015-12-10 00:36:47 +00:00
self.assertEqual(
2015-12-12 02:45:53 +00:00
'128',
2015-12-10 00:36:47 +00:00
template.render(
self.hass,
2016-02-14 21:07:21 +00:00
'{{ states.sensor.temperature.state | multiply(10) | round }}'
))
2016-02-21 05:59:16 +00:00
def test_rounding_value_get_original_value_on_error(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:59:16 +00:00
self.assertEqual(
'None',
template.render(
self.hass,
'{{ None | round }}'
))
self.assertEqual(
'no_number',
template.render(
self.hass,
'{{ "no_number" | round }}'
))
2016-02-21 19:12:37 +00:00
def test_multiply(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:12:37 +00:00
tests = {
None: 'None',
10: '100',
'"abcd"': 'abcd'
}
for inp, out in tests.items():
self.assertEqual(
out,
template.render(self.hass,
'{{ %s | multiply(10) | round }}' % inp))
def test_passing_vars_as_keywords(self):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
'127', template.render(self.hass, '{{ hello }}', hello=127))
def test_passing_vars_as_vars(self):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
'127', template.render(self.hass, '{{ hello }}', {'hello': 127}))
2015-12-11 05:38:35 +00:00
def test_render_with_possible_json_value_with_valid_json(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-11 05:38:35 +00:00
self.assertEqual(
'world',
template.render_with_possible_json_value(
self.hass, '{{ value_json.hello }}', '{"hello": "world"}'))
def test_render_with_possible_json_value_with_invalid_json(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-11 05:38:35 +00:00
self.assertEqual(
'',
template.render_with_possible_json_value(
self.hass, '{{ value_json }}', '{ I AM NOT JSON }'))
def test_render_with_possible_json_value_with_template_error(self):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
'hello',
template.render_with_possible_json_value(
self.hass, '{{ value_json', 'hello'))
2016-02-14 21:07:21 +00:00
def test_render_with_possible_json_value_with_template_error_value(self):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
'-',
template.render_with_possible_json_value(
self.hass, '{{ value_json', 'hello', '-'))
def test_raise_exception_on_error(self):
2016-03-09 09:25:50 +00:00
"""."""
with self.assertRaises(TemplateError):
template.render(self.hass, '{{ invalid_syntax')
2015-12-13 06:19:12 +00:00
2015-12-13 06:19:37 +00:00
def test_if_state_exists(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-13 06:19:37 +00:00
self.hass.states.set('test.object', 'available')
self.assertEqual(
'exists',
template.render(
self.hass,
2016-02-14 21:07:21 +00:00
"""
{% if states.test.object %}exists{% else %}not exists{% endif %}
"""))
2015-12-13 06:19:37 +00:00
2015-12-13 06:19:12 +00:00
def test_is_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-13 06:19:12 +00:00
self.hass.states.set('test.object', 'available')
self.assertEqual(
'yes',
template.render(
self.hass,
2016-02-14 21:07:21 +00:00
"""
{% if is_state("test.object", "available") %}yes{% else %}no{% endif %}
"""))
2015-12-13 06:19:37 +00:00
def test_is_state_attr(self):
2016-03-09 09:25:50 +00:00
"""."""
self.hass.states.set('test.object', 'available', {'mode': 'on'})
self.assertEqual(
'yes',
template.render(
self.hass,
2016-02-14 21:07:21 +00:00
"""
{% if is_state_attr("test.object", "mode", "on") %}yes{% else %}no{% endif %}
"""))
2015-12-13 06:19:37 +00:00
def test_states_function(self):
2016-03-09 09:25:50 +00:00
"""."""
2015-12-13 06:19:37 +00:00
self.hass.states.set('test.object', 'available')
self.assertEqual(
'available',
template.render(self.hass, '{{ states("test.object") }}'))
self.assertEqual(
'unknown',
template.render(self.hass, '{{ states("test.object2") }}'))
@patch('homeassistant.core.dt_util.utcnow', return_value=dt_util.utcnow())
2016-02-23 21:06:45 +00:00
@patch('homeassistant.helpers.template.TemplateEnvironment.'
'is_safe_callable', return_value=True)
def test_now(self, mock_is_safe, mock_utcnow):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
dt_util.utcnow().isoformat(),
template.render(self.hass, '{{ now.isoformat() }}'))
@patch('homeassistant.core.dt_util.utcnow', return_value=dt_util.utcnow())
2016-02-23 21:06:45 +00:00
@patch('homeassistant.helpers.template.TemplateEnvironment.'
'is_safe_callable', return_value=True)
def test_utcnow(self, mock_is_safe, mock_utcnow):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
dt_util.utcnow().isoformat(),
template.render(self.hass, '{{ utcnow.isoformat() }}'))
def test_utcnow_is_exactly_now(self):
2016-03-09 09:25:50 +00:00
"""."""
self.assertEqual(
'True',
template.render(self.hass, '{{ utcnow == now }}'))
2016-02-21 05:58:53 +00:00
def test_distance_function_with_1_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.hass.states.set('test.object', 'happy', {
'latitude': 32.87336,
'longitude': -117.22943,
})
self.assertEqual(
'187',
template.render(
self.hass, '{{ distance(states.test.object) | round }}'))
def test_distance_function_with_2_states(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.hass.states.set('test.object', 'happy', {
'latitude': 32.87336,
'longitude': -117.22943,
})
self.hass.states.set('test.object_2', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
self.assertEqual(
'187',
template.render(
self.hass,
'{{ distance(states.test.object, states.test.object_2)'
'| round }}'))
def test_distance_function_with_1_coord(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.assertEqual(
'187',
template.render(
self.hass, '{{ distance("32.87336", "-117.22943") | round }}'))
def test_distance_function_with_2_coords(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.assertEqual(
'187',
template.render(
self.hass,
'{{ distance("32.87336", "-117.22943", %s, %s) | round }}'
% (self.hass.config.latitude, self.hass.config.longitude)))
def test_distance_function_with_1_state_1_coord(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.hass.states.set('test.object_2', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
self.assertEqual(
'187',
template.render(
self.hass,
'{{ distance("32.87336", "-117.22943", states.test.object_2) '
'| round }}'))
self.assertEqual(
'187',
template.render(
self.hass,
'{{ distance(states.test.object_2, "32.87336", "-117.22943") '
'| round }}'))
def test_distance_function_return_None_if_invalid_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.hass.states.set('test.object_2', 'happy', {
'latitude': 10,
})
self.assertEqual(
'None',
template.render(
self.hass,
'{{ distance(states.test.object_2) | round }}'))
def test_distance_function_return_None_if_invalid_coord(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 05:58:53 +00:00
self.assertEqual(
'None',
template.render(
self.hass,
2016-02-21 19:13:40 +00:00
'{{ distance("123", "abc") }}'))
self.assertEqual(
'None',
template.render(
self.hass,
'{{ distance("123") }}'))
self.hass.states.set('test.object_2', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
self.assertEqual(
'None',
template.render(
self.hass,
'{{ distance("123", states.test_object_2) }}'))
def test_closest_function_home_vs_domain(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.object', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('not_test_domain.but_closer', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
self.assertEqual(
'test_domain.object',
template.render(self.hass,
'{{ closest(states.test_domain).entity_id }}'))
def test_closest_function_home_vs_all_states(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.object', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('test_domain_2.and_closer', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
self.assertEqual(
'test_domain_2.and_closer',
template.render(self.hass,
'{{ closest(states).entity_id }}'))
def test_closest_function_home_vs_group_entity_id(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.object', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('not_in_group.but_closer', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
group.Group(self.hass, 'location group', ['test_domain.object'])
self.assertEqual(
'test_domain.object',
template.render(self.hass,
'{{ closest("group.location_group").entity_id }}'))
def test_closest_function_home_vs_group_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.object', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('not_in_group.but_closer', 'happy', {
'latitude': self.hass.config.latitude,
'longitude': self.hass.config.longitude,
})
group.Group(self.hass, 'location group', ['test_domain.object'])
self.assertEqual(
'test_domain.object',
template.render(
self.hass,
'{{ closest(states.group.location_group).entity_id }}'))
def test_closest_function_to_coord(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('test_domain.closest_zone', 'happy', {
'latitude': self.hass.config.latitude + 0.2,
'longitude': self.hass.config.longitude + 0.2,
})
self.hass.states.set('zone.far_away', 'zoning', {
'latitude': self.hass.config.latitude + 0.3,
'longitude': self.hass.config.longitude + 0.3,
})
self.assertEqual(
'test_domain.closest_zone',
template.render(
self.hass,
'{{ closest("%s", %s, states.test_domain).entity_id }}'
% (self.hass.config.latitude + 0.3,
self.hass.config.longitude + 0.3))
)
def test_closest_function_to_entity_id(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('test_domain.closest_zone', 'happy', {
'latitude': self.hass.config.latitude + 0.2,
'longitude': self.hass.config.longitude + 0.2,
})
self.hass.states.set('zone.far_away', 'zoning', {
'latitude': self.hass.config.latitude + 0.3,
'longitude': self.hass.config.longitude + 0.3,
})
self.assertEqual(
'test_domain.closest_zone',
template.render(
self.hass,
'{{ closest("zone.far_away", states.test_domain).entity_id }}')
)
def test_closest_function_to_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.hass.states.set('test_domain.closest_zone', 'happy', {
'latitude': self.hass.config.latitude + 0.2,
'longitude': self.hass.config.longitude + 0.2,
})
self.hass.states.set('zone.far_away', 'zoning', {
'latitude': self.hass.config.latitude + 0.3,
'longitude': self.hass.config.longitude + 0.3,
})
self.assertEqual(
'test_domain.closest_zone',
template.render(
self.hass,
'{{ closest(states.zone.far_away, '
'states.test_domain).entity_id }}')
)
def test_closest_function_invalid_state(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
for state in ('states.zone.non_existing', '"zone.non_existing"'):
self.assertEqual(
'None',
template.render(
self.hass, '{{ closest(%s, states) }}' % state))
def test_closest_function_state_with_invalid_location(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': 'invalid latitude',
'longitude': self.hass.config.longitude + 0.1,
})
self.assertEqual(
'None',
template.render(
self.hass,
'{{ closest(states.test_domain.closest_home, '
'states) }}'))
def test_closest_function_invalid_coordinates(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.hass.states.set('test_domain.closest_home', 'happy', {
'latitude': self.hass.config.latitude + 0.1,
'longitude': self.hass.config.longitude + 0.1,
})
self.assertEqual(
'None',
template.render(self.hass,
'{{ closest("invalid", "coord", states) }}'))
def test_closest_function_no_location_states(self):
2016-03-09 09:25:50 +00:00
"""."""
2016-02-21 19:13:40 +00:00
self.assertEqual('None',
template.render(self.hass, '{{ closest(states) }}'))