Merge pull request #2776 from home-assistant/add-notify-test

Add notify demo data test
pull/2779/head
Paulus Schoutsen 2016-08-09 21:47:11 -07:00 committed by GitHub
commit 1726c4b45a
7 changed files with 87 additions and 32 deletions

View File

@ -11,12 +11,12 @@ from types import ModuleType
from typing import Any, Optional, Dict from typing import Any, Optional, Dict
import voluptuous as vol import voluptuous as vol
from voluptuous.humanize import humanize_error
import homeassistant.components as core_components import homeassistant.components as core_components
from homeassistant.components import group, persistent_notification from homeassistant.components import group, persistent_notification
import homeassistant.config as conf_util import homeassistant.config as conf_util
import homeassistant.core as core import homeassistant.core as core
import homeassistant.helpers.config_validation as cv
import homeassistant.loader as loader import homeassistant.loader as loader
import homeassistant.util.package as pkg_util import homeassistant.util.package as pkg_util
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
@ -103,7 +103,7 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool:
try: try:
config = component.CONFIG_SCHEMA(config) config = component.CONFIG_SCHEMA(config)
except vol.MultipleInvalid as ex: except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, domain, config) _log_exception(ex, domain, config)
return False return False
elif hasattr(component, 'PLATFORM_SCHEMA'): elif hasattr(component, 'PLATFORM_SCHEMA'):
@ -113,7 +113,7 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool:
try: try:
p_validated = component.PLATFORM_SCHEMA(p_config) p_validated = component.PLATFORM_SCHEMA(p_config)
except vol.MultipleInvalid as ex: except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, domain, p_config) _log_exception(ex, domain, p_config)
return False return False
# Not all platform components follow same pattern for platforms # Not all platform components follow same pattern for platforms
@ -134,8 +134,8 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool:
try: try:
p_validated = platform.PLATFORM_SCHEMA(p_validated) p_validated = platform.PLATFORM_SCHEMA(p_validated)
except vol.MultipleInvalid as ex: except vol.MultipleInvalid as ex:
cv.log_exception(_LOGGER, ex, '{}.{}' _log_exception(ex, '{}.{}'.format(domain, p_name),
.format(domain, p_name), p_validated) p_validated)
return False return False
platforms.append(p_validated) platforms.append(p_validated)
@ -239,7 +239,7 @@ def from_config_dict(config: Dict[str, Any],
try: try:
conf_util.process_ha_core_config(hass, core_config) conf_util.process_ha_core_config(hass, core_config)
except vol.Invalid as ex: except vol.Invalid as ex:
cv.log_exception(_LOGGER, ex, 'homeassistant', core_config) _log_exception(ex, 'homeassistant', core_config)
return None return None
conf_util.process_ha_config_upgrade(hass) conf_util.process_ha_config_upgrade(hass)
@ -374,3 +374,20 @@ def _ensure_loader_prepared(hass: core.HomeAssistant) -> None:
def _mount_local_lib_path(config_dir: str) -> None: def _mount_local_lib_path(config_dir: str) -> None:
"""Add local library to Python Path.""" """Add local library to Python Path."""
sys.path.insert(0, os.path.join(config_dir, 'deps')) sys.path.insert(0, os.path.join(config_dir, 'deps'))
def _log_exception(ex, domain, config):
"""Generate log exception for config validation."""
message = 'Invalid config for [{}]: '.format(domain)
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
.format(ex.path[-1], domain, domain,
'->'.join('%s' % m for m in ex.path))
else:
message += humanize_error(config, ex)
if hasattr(config, '__line__'):
message += " (See {}:{})".format(config.__config_file__,
config.__line__ or '?')
_LOGGER.error(message)

View File

@ -44,16 +44,19 @@ NOTIFY_SERVICE_SCHEMA = vol.Schema({
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def send_message(hass, message, title=None): def send_message(hass, message, title=None, data=None):
"""Send a notification message.""" """Send a notification message."""
data = { info = {
ATTR_MESSAGE: message ATTR_MESSAGE: message
} }
if title is not None: if title is not None:
data[ATTR_TITLE] = title info[ATTR_TITLE] = title
hass.services.call(DOMAIN, SERVICE_NOTIFY, data) if data is not None:
info[ATTR_DATA] = data
hass.services.call(DOMAIN, SERVICE_NOTIFY, info)
def setup(hass, config): def setup(hass, config):

View File

@ -4,7 +4,7 @@ Demo notification service.
For more details about this platform, please refer to the documentation For more details about this platform, please refer to the documentation
https://home-assistant.io/components/demo/ https://home-assistant.io/components/demo/
""" """
from homeassistant.components.notify import ATTR_TITLE, BaseNotificationService from homeassistant.components.notify import BaseNotificationService
EVENT_NOTIFY = "notify" EVENT_NOTIFY = "notify"
@ -24,5 +24,5 @@ class DemoNotificationService(BaseNotificationService):
def send_message(self, message="", **kwargs): def send_message(self, message="", **kwargs):
"""Send a message to a user.""" """Send a message to a user."""
title = kwargs.get(ATTR_TITLE) kwargs['message'] = message
self.hass.bus.fire(EVENT_NOTIFY, {"title": title, "message": message}) self.hass.bus.fire(EVENT_NOTIFY, kwargs)

View File

@ -19,6 +19,7 @@ from types import MappingProxyType
from typing import Optional, Any, Callable, List # NOQA from typing import Optional, Any, Callable, List # NOQA
import voluptuous as vol import voluptuous as vol
from voluptuous.humanize import humanize_error
from homeassistant.const import ( from homeassistant.const import (
ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE, ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE,
@ -571,7 +572,8 @@ class Service(object):
self.func(call) self.func(call)
except vol.MultipleInvalid as ex: except vol.MultipleInvalid as ex:
_LOGGER.error('Invalid service data for %s.%s: %s', _LOGGER.error('Invalid service data for %s.%s: %s',
call.domain, call.service, ex) call.domain, call.service,
humanize_error(call.data, ex))
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods

View File

@ -152,23 +152,6 @@ def time_period_str(value: str) -> timedelta:
time_period = vol.Any(time_period_str, timedelta, time_period_dict) time_period = vol.Any(time_period_str, timedelta, time_period_dict)
def log_exception(logger, ex, domain, config):
"""Generate log exception for config validation."""
message = 'Invalid config for [{}]: '.format(domain)
if 'extra keys not allowed' in ex.error_message:
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
.format(ex.path[-1], domain, domain,
'->'.join('%s' % m for m in ex.path))
else:
message += str(ex)
if hasattr(config, '__line__'):
message += " (See {}:{})".format(config.__config_file__,
config.__line__ or '?')
logger.error(message)
def match_all(value): def match_all(value):
"""Validator that matches all values.""" """Validator that matches all values."""
return value return value
@ -239,6 +222,8 @@ def template(value):
"""Validate a jinja2 template.""" """Validate a jinja2 template."""
if value is None: if value is None:
raise vol.Invalid('template value is None') raise vol.Invalid('template value is None')
if isinstance(value, (list, dict)):
raise vol.Invalid('template value should be a string')
value = str(value) value = str(value)
try: try:

View File

@ -1,8 +1,11 @@
"""The tests for the notify demo platform.""" """The tests for the notify demo platform."""
import tempfile
import unittest import unittest
import homeassistant.components.notify as notify import homeassistant.components.notify as notify
from homeassistant.components.notify import demo from homeassistant.components.notify import demo
from homeassistant.helpers import script
from homeassistant.util import yaml
from tests.common import get_test_home_assistant from tests.common import get_test_home_assistant
@ -45,3 +48,48 @@ class TestNotifyDemo(unittest.TestCase):
last_event = self.events[-1] last_event = self.events[-1]
self.assertEqual(last_event.data[notify.ATTR_TITLE], 'temperature') self.assertEqual(last_event.data[notify.ATTR_TITLE], 'temperature')
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], '10') self.assertEqual(last_event.data[notify.ATTR_MESSAGE], '10')
def test_method_forwards_correct_data(self):
"""Test that all data from the service gets forwarded to service."""
notify.send_message(self.hass, 'my message', 'my title',
{'hello': 'world'})
self.hass.pool.block_till_done()
self.assertTrue(len(self.events) == 1)
data = self.events[0].data
assert {
'message': 'my message',
'target': None,
'title': 'my title',
'data': {'hello': 'world'}
} == data
def test_calling_notify_from_script_loaded_from_yaml(self):
"""Test if we can call a notify from a script."""
yaml_conf = """
service: notify.notify
data:
data:
push:
sound: US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav
data_template:
message: >
Test 123 {{ 2 + 2 }}
"""
with tempfile.NamedTemporaryFile() as fp:
fp.write(yaml_conf.encode('utf-8'))
fp.flush()
conf = yaml.load_yaml(fp.name)
script.call_from_config(self.hass, conf)
self.hass.pool.block_till_done()
self.assertTrue(len(self.events) == 1)
assert {
'message': 'Test 123 4',
'target': None,
'title': 'Home Assistant',
'data': {
'push': {
'sound':
'US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav'}}
} == self.events[0].data

View File

@ -253,7 +253,7 @@ def test_template():
schema = vol.Schema(cv.template) schema = vol.Schema(cv.template)
for value in ( for value in (
None, '{{ partial_print }', '{% if True %}Hello' None, '{{ partial_print }', '{% if True %}Hello', {'dict': 'isbad'}
): ):
with pytest.raises(vol.MultipleInvalid): with pytest.raises(vol.MultipleInvalid):
schema(value) schema(value)