2016-03-09 09:25:50 +00:00
|
|
|
"""Test Home Assistant template helper methods."""
|
2016-11-11 06:57:44 +00:00
|
|
|
from datetime import datetime
|
2015-12-10 00:20:09 +00:00
|
|
|
import unittest
|
2016-02-21 04:58:01 +00:00
|
|
|
from unittest.mock import patch
|
|
|
|
|
2016-02-21 19:13:40 +00:00
|
|
|
from homeassistant.components import group
|
2015-12-12 03:07:03 +00:00
|
|
|
from homeassistant.exceptions import TemplateError
|
2016-02-23 20:06:50 +00:00
|
|
|
from homeassistant.helpers import template
|
2016-08-09 03:42:25 +00:00
|
|
|
from homeassistant.util.unit_system import UnitSystem
|
2016-07-31 20:24:49 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
LENGTH_METERS,
|
|
|
|
TEMP_CELSIUS,
|
|
|
|
MASS_GRAMS,
|
|
|
|
VOLUME_LITERS,
|
2016-09-28 04:29:55 +00:00
|
|
|
MATCH_ALL,
|
2016-07-31 20:24:49 +00:00
|
|
|
)
|
2016-02-21 04:58:01 +00:00
|
|
|
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
|
|
|
|
2016-09-28 04:29:55 +00:00
|
|
|
class TestHelpersTemplate(unittest.TestCase):
|
2016-03-09 09:25:50 +00:00
|
|
|
"""Test the Template."""
|
2015-12-10 00:20:09 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def setUp(self):
|
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()
|
2016-07-31 20:24:49 +00:00
|
|
|
self.hass.config.units = UnitSystem('custom', TEMP_CELSIUS,
|
|
|
|
LENGTH_METERS, VOLUME_LITERS,
|
|
|
|
MASS_GRAMS)
|
2015-12-10 00:20:09 +00:00
|
|
|
|
2016-10-30 21:18:53 +00:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
def tearDown(self):
|
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-09-25 20:33:01 +00:00
|
|
|
"""Test referring states by entity id."""
|
2015-12-10 00:20:09 +00:00
|
|
|
self.hass.states.set('test.object', 'happy')
|
|
|
|
self.assertEqual(
|
|
|
|
'happy',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ states.test.object.state }}', self.hass).render())
|
2015-12-10 00:20:09 +00:00
|
|
|
|
|
|
|
def test_iterating_all_states(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test iterating all states."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{% for state in states %}{{ state.state }}{% endfor %}',
|
|
|
|
self.hass).render())
|
2015-12-10 00:20:09 +00:00
|
|
|
|
|
|
|
def test_iterating_domain_states(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test iterating domain states."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template("""
|
2016-02-14 21:07:21 +00:00
|
|
|
{% for state in states.sensor %}{{ state.state }}{% endfor %}
|
2016-09-28 04:29:55 +00:00
|
|
|
""", self.hass).render())
|
2015-12-10 00:20:09 +00:00
|
|
|
|
2016-02-24 18:41:49 +00:00
|
|
|
def test_float(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test float."""
|
2016-02-24 18:41:49 +00:00
|
|
|
self.hass.states.set('sensor.temperature', '12')
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'12.0',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ float(states.sensor.temperature.state) }}',
|
|
|
|
self.hass).render())
|
2016-02-24 18:41:49 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'True',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ float(states.sensor.temperature.state) > 11 }}',
|
|
|
|
self.hass).render())
|
2016-02-24 18:41:49 +00:00
|
|
|
|
2015-12-10 00:20:09 +00:00
|
|
|
def test_rounding_value(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test rounding value."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ states.sensor.temperature.state | round(1) }}',
|
|
|
|
self.hass).render())
|
2015-12-10 00:36:47 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
2015-12-12 02:45:53 +00:00
|
|
|
'128',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ states.sensor.temperature.state | multiply(10) | round }}',
|
|
|
|
self.hass).render())
|
2015-12-11 05:16:05 +00:00
|
|
|
|
2016-02-21 05:59:16 +00:00
|
|
|
def test_rounding_value_get_original_value_on_error(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test rounding value get original value on error."""
|
2016-02-21 05:59:16 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ None | round }}', self.hass).render())
|
2016-02-21 05:59:16 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'no_number',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ "no_number" | round }}', self.hass).render())
|
2016-02-21 05:59:16 +00:00
|
|
|
|
2016-02-21 19:12:37 +00:00
|
|
|
def test_multiply(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test multiply."""
|
2016-02-21 19:12:37 +00:00
|
|
|
tests = {
|
|
|
|
None: 'None',
|
|
|
|
10: '100',
|
|
|
|
'"abcd"': 'abcd'
|
|
|
|
}
|
|
|
|
|
|
|
|
for inp, out in tests.items():
|
|
|
|
self.assertEqual(
|
|
|
|
out,
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ %s | multiply(10) | round }}' % inp,
|
|
|
|
self.hass).render())
|
2016-02-21 19:12:37 +00:00
|
|
|
|
2016-11-11 06:57:44 +00:00
|
|
|
def test_strptime(self):
|
|
|
|
"""Test the parse timestamp method."""
|
|
|
|
tests = [
|
|
|
|
('2016-10-19 15:22:05.588122 UTC',
|
|
|
|
'%Y-%m-%d %H:%M:%S.%f %Z', None),
|
|
|
|
('2016-10-19 15:22:05.588122+0100',
|
|
|
|
'%Y-%m-%d %H:%M:%S.%f%z', None),
|
|
|
|
('2016-10-19 15:22:05.588122',
|
|
|
|
'%Y-%m-%d %H:%M:%S.%f', None),
|
|
|
|
('2016-10-19', '%Y-%m-%d', None),
|
|
|
|
('2016', '%Y', None),
|
|
|
|
('15:22:05', '%H:%M:%S', None),
|
|
|
|
('1469119144', '%Y', '1469119144'),
|
|
|
|
('invalid', '%Y', 'invalid')
|
|
|
|
]
|
|
|
|
|
|
|
|
for inp, fmt, expected in tests:
|
|
|
|
if expected is None:
|
|
|
|
expected = datetime.strptime(inp, fmt)
|
|
|
|
|
|
|
|
temp = '{{ strptime(\'%s\', \'%s\') }}' % (inp, fmt)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
str(expected),
|
|
|
|
template.Template(temp, self.hass).render())
|
|
|
|
|
2016-09-09 00:49:02 +00:00
|
|
|
def test_timestamp_custom(self):
|
|
|
|
"""Test the timestamps to custom filter."""
|
|
|
|
tests = [
|
|
|
|
(None, None, None, 'None'),
|
|
|
|
(1469119144, None, True, '2016-07-21 16:39:04'),
|
|
|
|
(1469119144, '%Y', True, '2016'),
|
|
|
|
(1469119144, 'invalid', True, 'invalid'),
|
|
|
|
(dt_util.as_timestamp(dt_util.utcnow()), None, False,
|
|
|
|
dt_util.now().strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
|
]
|
|
|
|
|
|
|
|
for inp, fmt, local, out in tests:
|
|
|
|
if fmt:
|
|
|
|
fil = 'timestamp_custom(\'{}\')'.format(fmt)
|
|
|
|
elif fmt and local:
|
|
|
|
fil = 'timestamp_custom(\'{0}\', {1})'.format(fmt, local)
|
|
|
|
else:
|
|
|
|
fil = 'timestamp_custom'
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
out,
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ %s | %s }}' % (inp, fil),
|
|
|
|
self.hass).render())
|
2016-09-09 00:49:02 +00:00
|
|
|
|
2016-07-23 02:47:43 +00:00
|
|
|
def test_timestamp_local(self):
|
|
|
|
"""Test the timestamps to local filter."""
|
|
|
|
tests = {
|
|
|
|
None: 'None',
|
|
|
|
1469119144: '2016-07-21 16:39:04',
|
|
|
|
}
|
|
|
|
|
|
|
|
for inp, out in tests.items():
|
|
|
|
self.assertEqual(
|
|
|
|
out,
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ %s | timestamp_local }}' % inp,
|
|
|
|
self.hass).render())
|
2016-07-23 02:47:43 +00:00
|
|
|
|
|
|
|
def test_timestamp_utc(self):
|
|
|
|
"""Test the timestamps to local filter."""
|
|
|
|
tests = {
|
|
|
|
None: 'None',
|
|
|
|
1469119144: '2016-07-21 16:39:04',
|
|
|
|
dt_util.as_timestamp(dt_util.utcnow()):
|
|
|
|
dt_util.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
}
|
|
|
|
|
|
|
|
for inp, out in tests.items():
|
|
|
|
self.assertEqual(
|
|
|
|
out,
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ %s | timestamp_utc }}' % inp,
|
|
|
|
self.hass).render())
|
2016-07-23 02:47:43 +00:00
|
|
|
|
2015-12-11 05:16:05 +00:00
|
|
|
def test_passing_vars_as_keywords(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test passing variables as keywords."""
|
2015-12-11 05:16:05 +00:00
|
|
|
self.assertEqual(
|
2016-09-28 04:29:55 +00:00
|
|
|
'127',
|
|
|
|
template.Template('{{ hello }}', self.hass).render(hello=127))
|
2015-12-11 05:16:05 +00:00
|
|
|
|
|
|
|
def test_passing_vars_as_vars(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test passing variables as variables."""
|
2015-12-11 05:16:05 +00:00
|
|
|
self.assertEqual(
|
2016-09-28 04:29:55 +00:00
|
|
|
'127',
|
|
|
|
template.Template('{{ hello }}', self.hass).render({'hello': 127}))
|
2015-12-11 05:38:35 +00:00
|
|
|
|
|
|
|
def test_render_with_possible_json_value_with_valid_json(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Render with possible JSON value with valid JSON."""
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ value_json.hello }}', self.hass)
|
2015-12-11 05:38:35 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'world',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render_with_possible_json_value('{"hello": "world"}'))
|
2015-12-11 05:38:35 +00:00
|
|
|
|
|
|
|
def test_render_with_possible_json_value_with_invalid_json(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Render with possible JSON value with invalid JSON."""
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ value_json }}', self.hass)
|
2015-12-11 05:38:35 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render_with_possible_json_value('{ I AM NOT JSON }'))
|
2015-12-12 18:35:15 +00:00
|
|
|
|
2016-02-14 21:07:21 +00:00
|
|
|
def test_render_with_possible_json_value_with_template_error_value(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Render with possible JSON value with template error value."""
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ non_existing.variable }}', self.hass)
|
2015-12-12 18:35:15 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'-',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render_with_possible_json_value('hello', '-'))
|
2015-12-12 18:35:15 +00:00
|
|
|
|
2016-10-15 13:38:11 +00:00
|
|
|
def test_render_with_possible_json_value_with_missing_json_value(self):
|
|
|
|
"""Render with possible JSON value with unknown JSON object."""
|
|
|
|
tpl = template.Template('{{ value_json.goodbye }}', self.hass)
|
|
|
|
self.assertEqual(
|
|
|
|
'',
|
|
|
|
tpl.render_with_possible_json_value('{"hello": "world"}'))
|
|
|
|
|
|
|
|
def test_render_with_possible_json_value_valid_with_is_defined(self):
|
|
|
|
"""Render with possible JSON value with known JSON object."""
|
|
|
|
tpl = template.Template('{{ value_json.hello|is_defined }}', self.hass)
|
|
|
|
self.assertEqual(
|
|
|
|
'world',
|
|
|
|
tpl.render_with_possible_json_value('{"hello": "world"}'))
|
|
|
|
|
|
|
|
def test_render_with_possible_json_value_undefined_json(self):
|
|
|
|
"""Render with possible JSON value with unknown JSON object."""
|
|
|
|
tpl = template.Template('{{ value_json.bye|is_defined }}', self.hass)
|
|
|
|
self.assertEqual(
|
|
|
|
'{"hello": "world"}',
|
|
|
|
tpl.render_with_possible_json_value('{"hello": "world"}'))
|
|
|
|
|
|
|
|
def test_render_with_possible_json_value_undefined_json_error_value(self):
|
|
|
|
"""Render with possible JSON value with unknown JSON object."""
|
|
|
|
tpl = template.Template('{{ value_json.bye|is_defined }}', self.hass)
|
|
|
|
self.assertEqual(
|
|
|
|
'',
|
|
|
|
tpl.render_with_possible_json_value('{"hello": "world"}', ''))
|
|
|
|
|
2015-12-12 03:07:03 +00:00
|
|
|
def test_raise_exception_on_error(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test raising an exception on error."""
|
2015-12-12 03:07:03 +00:00
|
|
|
with self.assertRaises(TemplateError):
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ invalid_syntax').ensure_valid()
|
2015-12-13 06:19:12 +00:00
|
|
|
|
2015-12-13 06:19:37 +00:00
|
|
|
def test_if_state_exists(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test if state exists works."""
|
2015-12-13 06:19:37 +00:00
|
|
|
self.hass.states.set('test.object', 'available')
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template(
|
|
|
|
'{% if states.test.object %}exists{% else %}not exists{% endif %}',
|
|
|
|
self.hass)
|
|
|
|
self.assertEqual('exists', tpl.render())
|
2015-12-13 06:19:37 +00:00
|
|
|
|
2015-12-13 06:19:12 +00:00
|
|
|
def test_is_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test is_state method."""
|
2015-12-13 06:19:12 +00:00
|
|
|
self.hass.states.set('test.object', 'available')
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template("""
|
2016-02-14 21:07:21 +00:00
|
|
|
{% if is_state("test.object", "available") %}yes{% else %}no{% endif %}
|
2016-09-28 04:29:55 +00:00
|
|
|
""", self.hass)
|
|
|
|
self.assertEqual('yes', tpl.render())
|
2015-12-13 06:19:37 +00:00
|
|
|
|
2015-12-31 20:58:18 +00:00
|
|
|
def test_is_state_attr(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test is_state_attr method."""
|
2015-12-31 20:58:18 +00:00
|
|
|
self.hass.states.set('test.object', 'available', {'mode': 'on'})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template("""
|
2016-02-14 21:07:21 +00:00
|
|
|
{% if is_state_attr("test.object", "mode", "on") %}yes{% else %}no{% endif %}
|
2016-09-28 04:29:55 +00:00
|
|
|
""", self.hass)
|
|
|
|
self.assertEqual('yes', tpl.render())
|
2015-12-31 20:58:18 +00:00
|
|
|
|
2015-12-13 06:19:37 +00:00
|
|
|
def test_states_function(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test using states as a function."""
|
2015-12-13 06:19:37 +00:00
|
|
|
self.hass.states.set('test.object', 'available')
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ states("test.object") }}', self.hass)
|
|
|
|
self.assertEqual('available', tpl.render())
|
|
|
|
|
|
|
|
tpl2 = template.Template('{{ states("test.object2") }}', self.hass)
|
|
|
|
self.assertEqual('unknown', tpl2.render())
|
2016-02-21 04:58:01 +00:00
|
|
|
|
2016-02-23 21:06:45 +00:00
|
|
|
@patch('homeassistant.helpers.template.TemplateEnvironment.'
|
|
|
|
'is_safe_callable', return_value=True)
|
2016-09-28 04:29:55 +00:00
|
|
|
def test_now(self, mock_is_safe):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test now method."""
|
2016-09-28 04:29:55 +00:00
|
|
|
now = dt_util.now()
|
|
|
|
with patch.dict(template.ENV.globals, {'now': lambda: now}):
|
|
|
|
self.assertEqual(
|
|
|
|
now.isoformat(),
|
|
|
|
template.Template('{{ now().isoformat() }}',
|
|
|
|
self.hass).render())
|
2016-02-21 04:58:01 +00:00
|
|
|
|
2016-02-23 21:06:45 +00:00
|
|
|
@patch('homeassistant.helpers.template.TemplateEnvironment.'
|
|
|
|
'is_safe_callable', return_value=True)
|
2016-09-28 04:29:55 +00:00
|
|
|
def test_utcnow(self, mock_is_safe):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test utcnow method."""
|
2016-09-28 04:29:55 +00:00
|
|
|
now = dt_util.utcnow()
|
|
|
|
with patch.dict(template.ENV.globals, {'utcnow': lambda: now}):
|
|
|
|
self.assertEqual(
|
|
|
|
now.isoformat(),
|
|
|
|
template.Template('{{ utcnow().isoformat() }}',
|
|
|
|
self.hass).render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_with_1_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function with 1 state."""
|
2016-02-21 05:58:53 +00:00
|
|
|
self.hass.states.set('test.object', 'happy', {
|
|
|
|
'latitude': 32.87336,
|
|
|
|
'longitude': -117.22943,
|
|
|
|
})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ distance(states.test.object) | round }}',
|
|
|
|
self.hass)
|
|
|
|
self.assertEqual('187', tpl.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_with_2_states(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function with 2 states."""
|
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,
|
|
|
|
})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template(
|
|
|
|
'{{ distance(states.test.object, states.test.object_2) | round }}',
|
|
|
|
self.hass)
|
|
|
|
self.assertEqual('187', tpl.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_with_1_coord(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function with 1 coord."""
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template(
|
|
|
|
'{{ distance("32.87336", "-117.22943") | round }}', self.hass)
|
2016-02-21 05:58:53 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'187',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_with_2_coords(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function with 2 coords."""
|
2016-02-21 05:58:53 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'187',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
2016-02-21 05:58:53 +00:00
|
|
|
'{{ distance("32.87336", "-117.22943", %s, %s) | round }}'
|
2016-09-28 04:29:55 +00:00
|
|
|
% (self.hass.config.latitude, self.hass.config.longitude),
|
|
|
|
self.hass).render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_with_1_state_1_coord(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function with 1 state 1 coord."""
|
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,
|
|
|
|
})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template(
|
|
|
|
'{{ distance("32.87336", "-117.22943", states.test.object_2) '
|
|
|
|
'| round }}', self.hass)
|
|
|
|
self.assertEqual('187', tpl.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl2 = template.Template(
|
|
|
|
'{{ distance(states.test.object_2, "32.87336", "-117.22943") '
|
|
|
|
'| round }}', self.hass)
|
|
|
|
self.assertEqual('187', tpl2.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_return_None_if_invalid_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function return None if invalid state."""
|
2016-02-21 05:58:53 +00:00
|
|
|
self.hass.states.set('test.object_2', 'happy', {
|
|
|
|
'latitude': 10,
|
|
|
|
})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ distance(states.test.object_2) | round }}',
|
|
|
|
self.hass)
|
2016-02-21 05:58:53 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render())
|
2016-02-21 05:58:53 +00:00
|
|
|
|
|
|
|
def test_distance_function_return_None_if_invalid_coord(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test distance function return None if invalid coord."""
|
2016-02-21 05:58:53 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ distance("123", "abc") }}', self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ distance("123") }}', self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
self.hass.states.set('test.object_2', 'happy', {
|
|
|
|
'latitude': self.hass.config.latitude,
|
|
|
|
'longitude': self.hass.config.longitude,
|
|
|
|
})
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template('{{ distance("123", states.test_object_2) }}',
|
|
|
|
self.hass)
|
2016-02-21 19:13:40 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_home_vs_domain(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function home vs domain."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ closest(states.test_domain).entity_id }}',
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_home_vs_all_states(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function home vs all states."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ closest(states).entity_id }}',
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_home_vs_group_entity_id(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function home vs group entity id."""
|
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,
|
|
|
|
})
|
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
group.Group.create_group(
|
|
|
|
self.hass, 'location group', ['test_domain.object'])
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'test_domain.object',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ closest("group.location_group").entity_id }}',
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_home_vs_group_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function home vs group state."""
|
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,
|
|
|
|
})
|
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
group.Group.create_group(
|
|
|
|
self.hass, 'location group', ['test_domain.object'])
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
'test_domain.object',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ closest(states.group.location_group).entity_id }}',
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_to_coord(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function to coord."""
|
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,
|
|
|
|
})
|
|
|
|
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl = template.Template(
|
|
|
|
'{{ closest("%s", %s, states.test_domain).entity_id }}'
|
|
|
|
% (self.hass.config.latitude + 0.3,
|
|
|
|
self.hass.config.longitude + 0.3), self.hass)
|
|
|
|
|
2016-02-21 19:13:40 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'test_domain.closest_zone',
|
2016-09-28 04:29:55 +00:00
|
|
|
tpl.render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_to_entity_id(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function to entity id."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
|
|
|
'{{ closest("zone.far_away", '
|
|
|
|
'states.test_domain).entity_id }}', self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_to_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function to state."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
2016-02-21 19:13:40 +00:00
|
|
|
'{{ closest(states.zone.far_away, '
|
2016-09-28 04:29:55 +00:00
|
|
|
'states.test_domain).entity_id }}', self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_invalid_state(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function invalid state."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ closest(%s, states) }}' % state,
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_state_with_invalid_location(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function state with invalid location."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template(
|
2016-02-21 19:13:40 +00:00
|
|
|
'{{ closest(states.test_domain.closest_home, '
|
2016-09-28 04:29:55 +00:00
|
|
|
'states) }}', self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_invalid_coordinates(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function invalid coordinates."""
|
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',
|
2016-09-28 04:29:55 +00:00
|
|
|
template.Template('{{ closest("invalid", "coord", states) }}',
|
|
|
|
self.hass).render())
|
2016-02-21 19:13:40 +00:00
|
|
|
|
|
|
|
def test_closest_function_no_location_states(self):
|
2016-09-25 20:33:01 +00:00
|
|
|
"""Test closest function without location states."""
|
2016-09-28 04:29:55 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'None',
|
|
|
|
template.Template('{{ closest(states) }}', self.hass).render())
|
|
|
|
|
|
|
|
def test_extract_entities_none_exclude_stuff(self):
|
|
|
|
"""Test extract entities function with none or exclude stuff."""
|
|
|
|
self.assertEqual(MATCH_ALL, template.extract_entities(None))
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
MATCH_ALL,
|
|
|
|
template.extract_entities(
|
|
|
|
'{{ closest(states.zone.far_away, '
|
|
|
|
'states.test_domain).entity_id }}'))
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
MATCH_ALL,
|
|
|
|
template.extract_entities(
|
|
|
|
'{{ distance("123", states.test_object_2) }}'))
|
|
|
|
|
|
|
|
def test_extract_entities_no_match_entities(self):
|
|
|
|
"""Test extract entities function with none entities stuff."""
|
|
|
|
self.assertEqual(
|
|
|
|
MATCH_ALL,
|
|
|
|
template.extract_entities(
|
|
|
|
"{{ value_json.tst | timestamp_custom('%Y' True) }}"))
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
MATCH_ALL,
|
|
|
|
template.extract_entities("""
|
|
|
|
{% for state in states.sensor %}
|
|
|
|
{{ state.entity_id }}={{ state.state }},
|
|
|
|
{% endfor %}
|
|
|
|
"""))
|
|
|
|
|
|
|
|
def test_extract_entities_match_entities(self):
|
|
|
|
"""Test extract entities function with entities stuff."""
|
|
|
|
self.assertListEqual(
|
|
|
|
['device_tracker.phone_1'],
|
|
|
|
template.extract_entities("""
|
|
|
|
{% if is_state('device_tracker.phone_1', 'home') %}
|
|
|
|
Ha, Hercules is home!
|
|
|
|
{% else %}
|
|
|
|
Hercules is at {{ states('device_tracker.phone_1') }}.
|
|
|
|
{% endif %}
|
|
|
|
"""))
|
|
|
|
|
|
|
|
self.assertListEqual(
|
|
|
|
['binary_sensor.garage_door'],
|
|
|
|
template.extract_entities("""
|
|
|
|
{{ as_timestamp(states.binary_sensor.garage_door.last_changed) }}
|
|
|
|
"""))
|
|
|
|
|
|
|
|
self.assertListEqual(
|
|
|
|
['binary_sensor.garage_door'],
|
|
|
|
template.extract_entities("""
|
|
|
|
{{ states("binary_sensor.garage_door") }}
|
|
|
|
"""))
|
|
|
|
|
|
|
|
self.assertListEqual(
|
|
|
|
['device_tracker.phone_2'],
|
|
|
|
template.extract_entities("""
|
|
|
|
is_state_attr('device_tracker.phone_2', 'battery', 40)
|
|
|
|
"""))
|
|
|
|
|
|
|
|
self.assertListEqual(
|
|
|
|
sorted([
|
|
|
|
'device_tracker.phone_1',
|
|
|
|
'device_tracker.phone_2',
|
|
|
|
]),
|
|
|
|
sorted(template.extract_entities("""
|
|
|
|
{% if is_state('device_tracker.phone_1', 'home') %}
|
|
|
|
Ha, Hercules is home!
|
|
|
|
{% elif states.device_tracker.phone_2.attributes.battery < 40 %}
|
|
|
|
Hercules you power goes done!.
|
|
|
|
{% endif %}
|
|
|
|
""")))
|
|
|
|
|
|
|
|
self.assertListEqual(
|
|
|
|
sorted([
|
|
|
|
'sensor.pick_humidity',
|
|
|
|
'sensor.pick_temperature',
|
|
|
|
]),
|
|
|
|
sorted(template.extract_entities("""
|
|
|
|
{{
|
|
|
|
states.sensor.pick_temperature.state ~ „°C (“ ~
|
|
|
|
states.sensor.pick_humidity.state ~ „ %“
|
|
|
|
}}
|
|
|
|
""")))
|