mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add initial group config (#6135)
This commit is contained in:
parent
1910440a3c
commit
32873508b7
@ -1,15 +1,20 @@
|
|||||||
"""Component to configure Home Assistant via an API."""
|
"""Component to configure Home Assistant via an API."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.const import EVENT_COMPONENT_LOADED
|
from homeassistant.const import EVENT_COMPONENT_LOADED
|
||||||
from homeassistant.bootstrap import (
|
from homeassistant.bootstrap import (
|
||||||
async_prepare_setup_platform, ATTR_COMPONENT)
|
async_prepare_setup_platform, ATTR_COMPONENT)
|
||||||
from homeassistant.components.frontend import register_built_in_panel
|
from homeassistant.components.frontend import register_built_in_panel
|
||||||
|
from homeassistant.components.http import HomeAssistantView
|
||||||
|
from homeassistant.util.yaml import load_yaml, dump
|
||||||
|
|
||||||
DOMAIN = 'config'
|
DOMAIN = 'config'
|
||||||
DEPENDENCIES = ['http']
|
DEPENDENCIES = ['http']
|
||||||
SECTIONS = ('core', 'hassbian')
|
SECTIONS = ('core', 'group', 'hassbian')
|
||||||
ON_DEMAND = ('zwave', )
|
ON_DEMAND = ('zwave', )
|
||||||
|
|
||||||
|
|
||||||
@ -53,3 +58,76 @@ def async_setup(hass, config):
|
|||||||
hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded)
|
hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class EditKeyBasedConfigView(HomeAssistantView):
|
||||||
|
"""Configure a Group endpoint."""
|
||||||
|
|
||||||
|
def __init__(self, component, config_type, path, key_schema, data_schema,
|
||||||
|
*, post_write_hook=None):
|
||||||
|
"""Initialize a config view."""
|
||||||
|
self.url = '/api/config/%s/%s/{config_key}' % (component, config_type)
|
||||||
|
self.name = 'api:config:%s:%s' % (component, config_type)
|
||||||
|
self.path = path
|
||||||
|
self.key_schema = key_schema
|
||||||
|
self.data_schema = data_schema
|
||||||
|
self.post_write_hook = post_write_hook
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def get(self, request, config_key):
|
||||||
|
"""Fetch device specific config."""
|
||||||
|
hass = request.app['hass']
|
||||||
|
current = yield from hass.loop.run_in_executor(
|
||||||
|
None, _read, hass.config.path(self.path))
|
||||||
|
return self.json(current.get(config_key, {}))
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def post(self, request, config_key):
|
||||||
|
"""Validate config and return results."""
|
||||||
|
try:
|
||||||
|
data = yield from request.json()
|
||||||
|
except ValueError:
|
||||||
|
return self.json_message('Invalid JSON specified', 400)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.key_schema(config_key)
|
||||||
|
except vol.Invalid as err:
|
||||||
|
return self.json_message('Key malformed: {}'.format(err), 400)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# We just validate, we don't store that data because
|
||||||
|
# we don't want to store the defaults.
|
||||||
|
self.data_schema(data)
|
||||||
|
except vol.Invalid as err:
|
||||||
|
return self.json_message('Message malformed: {}'.format(err), 400)
|
||||||
|
|
||||||
|
hass = request.app['hass']
|
||||||
|
path = hass.config.path(self.path)
|
||||||
|
|
||||||
|
current = yield from hass.loop.run_in_executor(None, _read, path)
|
||||||
|
current.setdefault(config_key, {}).update(data)
|
||||||
|
|
||||||
|
yield from hass.loop.run_in_executor(None, _write, path, current)
|
||||||
|
|
||||||
|
if self.post_write_hook is not None:
|
||||||
|
hass.async_add_job(self.post_write_hook(hass))
|
||||||
|
|
||||||
|
return self.json({
|
||||||
|
'result': 'ok',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def _read(path):
|
||||||
|
"""Read YAML helper."""
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
with open(path, 'w'):
|
||||||
|
pass
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return load_yaml(path)
|
||||||
|
|
||||||
|
|
||||||
|
def _write(path, data):
|
||||||
|
"""Write YAML helper."""
|
||||||
|
with open(path, 'w', encoding='utf-8') as outfile:
|
||||||
|
outfile.write(dump(data))
|
||||||
|
19
homeassistant/components/config/group.py
Normal file
19
homeassistant/components/config/group.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"""Provide configuration end points for Groups."""
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from homeassistant.components.config import EditKeyBasedConfigView
|
||||||
|
from homeassistant.components.group import GROUP_SCHEMA, async_reload
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_PATH = 'groups.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass):
|
||||||
|
"""Setup the Group config API."""
|
||||||
|
hass.http.register_view(EditKeyBasedConfigView(
|
||||||
|
'group', 'config', CONFIG_PATH, cv.slug,
|
||||||
|
GROUP_SCHEMA, post_write_hook=async_reload
|
||||||
|
))
|
||||||
|
return True
|
@ -1,78 +1,19 @@
|
|||||||
"""Provide configuration end points for Z-Wave."""
|
"""Provide configuration end points for Z-Wave."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import os
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.config import EditKeyBasedConfigView
|
||||||
from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY
|
from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY
|
||||||
from homeassistant.util.yaml import load_yaml, dump
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
DEVICE_CONFIG = 'zwave_device_config.yaml'
|
CONFIG_PATH = 'zwave_device_config.yaml'
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup(hass):
|
def async_setup(hass):
|
||||||
"""Setup the Z-Wave config API."""
|
"""Setup the Z-Wave config API."""
|
||||||
hass.http.register_view(DeviceConfigView)
|
hass.http.register_view(EditKeyBasedConfigView(
|
||||||
|
'zwave', 'device_config', CONFIG_PATH, cv.entity_id,
|
||||||
|
DEVICE_CONFIG_SCHEMA_ENTRY
|
||||||
|
))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class DeviceConfigView(HomeAssistantView):
|
|
||||||
"""Configure a Z-Wave device endpoint."""
|
|
||||||
|
|
||||||
url = '/api/config/zwave/device_config/{entity_id}'
|
|
||||||
name = 'api:config:zwave:device_config:update'
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def get(self, request, entity_id):
|
|
||||||
"""Fetch device specific config."""
|
|
||||||
hass = request.app['hass']
|
|
||||||
current = yield from hass.loop.run_in_executor(
|
|
||||||
None, _read, hass.config.path(DEVICE_CONFIG))
|
|
||||||
return self.json(current.get(entity_id, {}))
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def post(self, request, entity_id):
|
|
||||||
"""Validate config and return results."""
|
|
||||||
try:
|
|
||||||
data = yield from request.json()
|
|
||||||
except ValueError:
|
|
||||||
return self.json_message('Invalid JSON specified', 400)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# We just validate, we don't store that data because
|
|
||||||
# we don't want to store the defaults.
|
|
||||||
DEVICE_CONFIG_SCHEMA_ENTRY(data)
|
|
||||||
except vol.Invalid as err:
|
|
||||||
print(data, err)
|
|
||||||
return self.json_message('Message malformed: {}'.format(err), 400)
|
|
||||||
|
|
||||||
hass = request.app['hass']
|
|
||||||
path = hass.config.path(DEVICE_CONFIG)
|
|
||||||
current = yield from hass.loop.run_in_executor(
|
|
||||||
None, _read, hass.config.path(DEVICE_CONFIG))
|
|
||||||
current.setdefault(entity_id, {}).update(data)
|
|
||||||
|
|
||||||
yield from hass.loop.run_in_executor(
|
|
||||||
None, _write, hass.config.path(path), current)
|
|
||||||
|
|
||||||
return self.json({
|
|
||||||
'result': 'ok',
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def _read(path):
|
|
||||||
"""Read YAML helper."""
|
|
||||||
if not os.path.isfile(path):
|
|
||||||
with open(path, 'w'):
|
|
||||||
pass
|
|
||||||
return {}
|
|
||||||
|
|
||||||
return load_yaml(path)
|
|
||||||
|
|
||||||
|
|
||||||
def _write(path, data):
|
|
||||||
"""Write YAML helper."""
|
|
||||||
with open(path, 'w', encoding='utf-8') as outfile:
|
|
||||||
outfile.write(dump(data))
|
|
||||||
|
@ -57,14 +57,16 @@ def _conf_preprocess(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
GROUP_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(CONF_ENTITIES): vol.Any(cv.entity_ids, None),
|
||||||
|
CONF_VIEW: cv.boolean,
|
||||||
|
CONF_NAME: cv.string,
|
||||||
|
CONF_ICON: cv.icon,
|
||||||
|
CONF_CONTROL: cv.string,
|
||||||
|
})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: cv.ordered_dict(vol.All(_conf_preprocess, {
|
DOMAIN: cv.ordered_dict(vol.All(_conf_preprocess, GROUP_SCHEMA))
|
||||||
vol.Optional(CONF_ENTITIES): vol.Any(cv.entity_ids, None),
|
|
||||||
CONF_VIEW: cv.boolean,
|
|
||||||
CONF_NAME: cv.string,
|
|
||||||
CONF_ICON: cv.icon,
|
|
||||||
CONF_CONTROL: cv.string,
|
|
||||||
}, cv.match_all))
|
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
# List of ON/OFF state tuples for groupable states
|
# List of ON/OFF state tuples for groupable states
|
||||||
@ -99,6 +101,12 @@ def reload(hass):
|
|||||||
hass.services.call(DOMAIN, SERVICE_RELOAD)
|
hass.services.call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_reload(hass):
|
||||||
|
"""Reload the automation from config."""
|
||||||
|
yield from hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
|
||||||
def set_visibility(hass, entity_id=None, visible=True):
|
def set_visibility(hass, entity_id=None, visible=True):
|
||||||
"""Hide or shows a group."""
|
"""Hide or shows a group."""
|
||||||
data = {ATTR_ENTITY_ID: entity_id, ATTR_VISIBLE: visible}
|
data = {ATTR_ENTITY_ID: entity_id, ATTR_VISIBLE: visible}
|
||||||
|
149
tests/components/config/test_group.py
Normal file
149
tests/components/config/test_group.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
"""Test Z-Wave config panel."""
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import async_setup_component
|
||||||
|
from homeassistant.components import config
|
||||||
|
from tests.common import mock_http_component_app
|
||||||
|
|
||||||
|
|
||||||
|
VIEW_NAME = 'api:config:group:config'
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_get_device_config(hass, test_client):
|
||||||
|
"""Test getting device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['group']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
def mock_read(path):
|
||||||
|
"""Mock reading data."""
|
||||||
|
return {
|
||||||
|
'hello.beer': {
|
||||||
|
'free': 'beer',
|
||||||
|
},
|
||||||
|
'other.entity': {
|
||||||
|
'do': 'something',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
with patch('homeassistant.components.config._read', mock_read):
|
||||||
|
resp = yield from client.get(
|
||||||
|
'/api/config/group/config/hello.beer')
|
||||||
|
|
||||||
|
assert resp.status == 200
|
||||||
|
result = yield from resp.json()
|
||||||
|
|
||||||
|
assert result == {'free': 'beer'}
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['group']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
orig_data = {
|
||||||
|
'hello.beer': {
|
||||||
|
'ignored': True,
|
||||||
|
},
|
||||||
|
'other.entity': {
|
||||||
|
'polling_intensity': 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def mock_read(path):
|
||||||
|
"""Mock reading data."""
|
||||||
|
return orig_data
|
||||||
|
|
||||||
|
written = []
|
||||||
|
|
||||||
|
def mock_write(path, data):
|
||||||
|
"""Mock writing data."""
|
||||||
|
written.append(data)
|
||||||
|
|
||||||
|
with patch('homeassistant.components.config._read', mock_read), \
|
||||||
|
patch('homeassistant.components.config._write', mock_write):
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/group/config/hello_beer', data=json.dumps({
|
||||||
|
'name': 'Beer',
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert resp.status == 200
|
||||||
|
result = yield from resp.json()
|
||||||
|
assert result == {'result': 'ok'}
|
||||||
|
|
||||||
|
orig_data['hello_beer']['name'] = 'Beer'
|
||||||
|
|
||||||
|
assert written[0] == orig_data
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_key(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['group']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/group/config/not a slug', data=json.dumps({
|
||||||
|
'name': 'YO',
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert resp.status == 400
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_data(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['group']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/group/config/hello_beer', data=json.dumps({
|
||||||
|
'invalid_option': 2
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert resp.status == 400
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_json(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['group']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/group/config/hello_beer', data='not json')
|
||||||
|
|
||||||
|
assert resp.status == 400
|
@ -5,10 +5,12 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from homeassistant.bootstrap import async_setup_component
|
from homeassistant.bootstrap import async_setup_component
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
from homeassistant.components.config.zwave import DeviceConfigView
|
|
||||||
from tests.common import mock_http_component_app
|
from tests.common import mock_http_component_app
|
||||||
|
|
||||||
|
|
||||||
|
VIEW_NAME = 'api:config:zwave:device_config'
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_get_device_config(hass, test_client):
|
def test_get_device_config(hass, test_client):
|
||||||
"""Test getting device config."""
|
"""Test getting device config."""
|
||||||
@ -17,7 +19,7 @@ def test_get_device_config(hass, test_client):
|
|||||||
with patch.object(config, 'SECTIONS', ['zwave']):
|
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||||
yield from async_setup_component(hass, 'config', {})
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
hass.http.views[DeviceConfigView.name].register(app.router)
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
client = yield from test_client(app)
|
client = yield from test_client(app)
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ def test_get_device_config(hass, test_client):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
with patch('homeassistant.components.config.zwave._read', mock_read):
|
with patch('homeassistant.components.config._read', mock_read):
|
||||||
resp = yield from client.get(
|
resp = yield from client.get(
|
||||||
'/api/config/zwave/device_config/hello.beer')
|
'/api/config/zwave/device_config/hello.beer')
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ def test_update_device_config(hass, test_client):
|
|||||||
with patch.object(config, 'SECTIONS', ['zwave']):
|
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||||
yield from async_setup_component(hass, 'config', {})
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
hass.http.views[DeviceConfigView.name].register(app.router)
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
client = yield from test_client(app)
|
client = yield from test_client(app)
|
||||||
|
|
||||||
@ -73,8 +75,8 @@ def test_update_device_config(hass, test_client):
|
|||||||
"""Mock writing data."""
|
"""Mock writing data."""
|
||||||
written.append(data)
|
written.append(data)
|
||||||
|
|
||||||
with patch('homeassistant.components.config.zwave._read', mock_read), \
|
with patch('homeassistant.components.config._read', mock_read), \
|
||||||
patch('homeassistant.components.config.zwave._write', mock_write):
|
patch('homeassistant.components.config._write', mock_write):
|
||||||
resp = yield from client.post(
|
resp = yield from client.post(
|
||||||
'/api/config/zwave/device_config/hello.beer', data=json.dumps({
|
'/api/config/zwave/device_config/hello.beer', data=json.dumps({
|
||||||
'polling_intensity': 2
|
'polling_intensity': 2
|
||||||
@ -87,3 +89,61 @@ def test_update_device_config(hass, test_client):
|
|||||||
orig_data['hello.beer']['polling_intensity'] = 2
|
orig_data['hello.beer']['polling_intensity'] = 2
|
||||||
|
|
||||||
assert written[0] == orig_data
|
assert written[0] == orig_data
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_key(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/zwave/device_config/invalid_entity', data=json.dumps({
|
||||||
|
'polling_intensity': 2
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert resp.status == 400
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_data(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/zwave/device_config/hello.beer', data=json.dumps({
|
||||||
|
'invalid_option': 2
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert resp.status == 400
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_update_device_config_invalid_json(hass, test_client):
|
||||||
|
"""Test updating device config."""
|
||||||
|
app = mock_http_component_app(hass)
|
||||||
|
|
||||||
|
with patch.object(config, 'SECTIONS', ['zwave']):
|
||||||
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
hass.http.views[VIEW_NAME].register(app.router)
|
||||||
|
|
||||||
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
resp = yield from client.post(
|
||||||
|
'/api/config/zwave/device_config/hello.beer', data='not json')
|
||||||
|
|
||||||
|
assert resp.status == 400
|
||||||
|
Loading…
x
Reference in New Issue
Block a user