"""Test Z-Wave config panel.""" import asyncio import json from unittest.mock import MagicMock, patch import pytest from homeassistant.bootstrap import async_setup_component from homeassistant.components import config from homeassistant.components.zwave import DATA_NETWORK, const from tests.mock.zwave import MockNode, MockValue, MockEntityValues VIEW_NAME = 'api:config:zwave:device_config' @pytest.fixture def client(loop, hass, hass_client): """Client to communicate with Z-Wave config views.""" with patch.object(config, 'SECTIONS', ['zwave']): loop.run_until_complete(async_setup_component(hass, 'config', {})) return loop.run_until_complete(hass_client()) @asyncio.coroutine def test_get_device_config(client): """Test getting device config.""" 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/zwave/device_config/hello.beer') assert resp.status == 200 result = yield from resp.json() assert result == {'free': 'beer'} @asyncio.coroutine def test_update_device_config(client): """Test updating device config.""" 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/zwave/device_config/hello.beer', data=json.dumps({ 'polling_intensity': 2 })) assert resp.status == 200 result = yield from resp.json() assert result == {'result': 'ok'} orig_data['hello.beer']['polling_intensity'] = 2 assert written[0] == orig_data @asyncio.coroutine def test_update_device_config_invalid_key(client): """Test updating device config.""" 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(client): """Test updating device config.""" 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(client): """Test updating device config.""" resp = yield from client.post( '/api/config/zwave/device_config/hello.beer', data='not json') assert resp.status == 400 @asyncio.coroutine def test_get_values(hass, client): """Test getting values on node.""" node = MockNode(node_id=1) value = MockValue(value_id=123456, node=node, label='Test Label', instance=1, index=2, poll_intensity=4) values = MockEntityValues(primary=value) node2 = MockNode(node_id=2) value2 = MockValue(value_id=234567, node=node2, label='Test Label 2') values2 = MockEntityValues(primary=value2) hass.data[const.DATA_ENTITY_VALUES] = [values, values2] resp = yield from client.get('/api/zwave/values/1') assert resp.status == 200 result = yield from resp.json() assert result == { '123456': { 'label': 'Test Label', 'instance': 1, 'index': 2, 'poll_intensity': 4, } } @asyncio.coroutine def test_get_groups(hass, client): """Test getting groupdata on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=2) node.groups.associations = 'assoc' node.groups.associations_instances = 'inst' node.groups.label = 'the label' node.groups.max_associations = 'max' node.groups = {1: node.groups} network.nodes = {2: node} resp = yield from client.get('/api/zwave/groups/2') assert resp.status == 200 result = yield from resp.json() assert result == { '1': { 'association_instances': 'inst', 'associations': 'assoc', 'label': 'the label', 'max_associations': 'max' } } @asyncio.coroutine def test_get_groups_nogroups(hass, client): """Test getting groupdata on node with no groups.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=2) network.nodes = {2: node} resp = yield from client.get('/api/zwave/groups/2') assert resp.status == 200 result = yield from resp.json() assert result == {} @asyncio.coroutine def test_get_groups_nonode(hass, client): """Test getting groupdata on nonexisting node.""" network = hass.data[DATA_NETWORK] = MagicMock() network.nodes = {1: 1, 5: 5} resp = yield from client.get('/api/zwave/groups/2') assert resp.status == 404 result = yield from resp.json() assert result == {'message': 'Node not found'} @asyncio.coroutine def test_get_config(hass, client): """Test getting config on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=2) value = MockValue( index=12, command_class=const.COMMAND_CLASS_CONFIGURATION) value.label = 'label' value.help = 'help' value.type = 'type' value.data = 'data' value.data_items = ['item1', 'item2'] value.max = 'max' value.min = 'min' node.values = {12: value} network.nodes = {2: node} node.get_values.return_value = node.values resp = yield from client.get('/api/zwave/config/2') assert resp.status == 200 result = yield from resp.json() assert result == {'12': {'data': 'data', 'data_items': ['item1', 'item2'], 'help': 'help', 'label': 'label', 'max': 'max', 'min': 'min', 'type': 'type'}} @asyncio.coroutine def test_get_config_noconfig_node(hass, client): """Test getting config on node without config.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=2) network.nodes = {2: node} node.get_values.return_value = node.values resp = yield from client.get('/api/zwave/config/2') assert resp.status == 200 result = yield from resp.json() assert result == {} @asyncio.coroutine def test_get_config_nonode(hass, client): """Test getting config on nonexisting node.""" network = hass.data[DATA_NETWORK] = MagicMock() network.nodes = {1: 1, 5: 5} resp = yield from client.get('/api/zwave/config/2') assert resp.status == 404 result = yield from resp.json() assert result == {'message': 'Node not found'} @asyncio.coroutine def test_get_usercodes_nonode(hass, client): """Test getting usercodes on nonexisting node.""" network = hass.data[DATA_NETWORK] = MagicMock() network.nodes = {1: 1, 5: 5} resp = yield from client.get('/api/zwave/usercodes/2') assert resp.status == 404 result = yield from resp.json() assert result == {'message': 'Node not found'} @asyncio.coroutine def test_get_usercodes(hass, client): """Test getting usercodes on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_USER_CODE]) value = MockValue( index=0, command_class=const.COMMAND_CLASS_USER_CODE) value.genre = const.GENRE_USER value.label = 'label' value.data = '1234' node.values = {0: value} network.nodes = {18: node} node.get_values.return_value = node.values resp = yield from client.get('/api/zwave/usercodes/18') assert resp.status == 200 result = yield from resp.json() assert result == {'0': {'code': '1234', 'label': 'label', 'length': 4}} @asyncio.coroutine def test_get_usercode_nousercode_node(hass, client): """Test getting usercodes on node without usercodes.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18) network.nodes = {18: node} node.get_values.return_value = node.values resp = yield from client.get('/api/zwave/usercodes/18') assert resp.status == 200 result = yield from resp.json() assert result == {} @asyncio.coroutine def test_get_usercodes_no_genreuser(hass, client): """Test getting usercodes on node missing genre user.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_USER_CODE]) value = MockValue( index=0, command_class=const.COMMAND_CLASS_USER_CODE) value.genre = const.GENRE_SYSTEM value.label = 'label' value.data = '1234' node.values = {0: value} network.nodes = {18: node} node.get_values.return_value = node.values resp = yield from client.get('/api/zwave/usercodes/18') assert resp.status == 200 result = yield from resp.json() assert result == {} @asyncio.coroutine def test_save_config_no_network(hass, client): """Test saving configuration without network data.""" resp = yield from client.post('/api/zwave/saveconfig') assert resp.status == 404 result = yield from resp.json() assert result == {'message': 'No Z-Wave network data found'} @asyncio.coroutine def test_save_config(hass, client): """Test saving configuration.""" network = hass.data[DATA_NETWORK] = MagicMock() resp = yield from client.post('/api/zwave/saveconfig') assert resp.status == 200 result = yield from resp.json() assert network.write_config.called assert result == {'message': 'Z-Wave configuration saved to file.'} async def test_get_protection_values(hass, client): """Test getting protection values on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) value = MockValue( value_id=123456, index=0, instance=1, command_class=const.COMMAND_CLASS_PROTECTION) value.label = 'Protection Test' value.data_items = ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] value.data = 'Unprotected' network.nodes = {18: node} node.value = value node.get_protection_item.return_value = "Unprotected" node.get_protection_items.return_value = value.data_items node.get_protections.return_value = {value.value_id: 'Object'} resp = await client.get('/api/zwave/protection/18') assert resp.status == 200 result = await resp.json() assert node.get_protections.called assert node.get_protection_item.called assert node.get_protection_items.called assert result == { 'value_id': '123456', 'selected': 'Unprotected', 'options': ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] } async def test_get_protection_values_nonexisting_node(hass, client): """Test getting protection values on node with wrong nodeid.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) value = MockValue( value_id=123456, index=0, instance=1, command_class=const.COMMAND_CLASS_PROTECTION) value.label = 'Protection Test' value.data_items = ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] value.data = 'Unprotected' network.nodes = {17: node} node.value = value resp = await client.get('/api/zwave/protection/18') assert resp.status == 404 result = await resp.json() assert not node.get_protections.called assert not node.get_protection_item.called assert not node.get_protection_items.called assert result == {'message': 'Node not found'} async def test_get_protection_values_without_protectionclass(hass, client): """Test getting protection values on node without protectionclass.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18) value = MockValue( value_id=123456, index=0, instance=1) network.nodes = {18: node} node.value = value resp = await client.get('/api/zwave/protection/18') assert resp.status == 200 result = await resp.json() assert not node.get_protections.called assert not node.get_protection_item.called assert not node.get_protection_items.called assert result == {} async def test_set_protection_value(hass, client): """Test setting protection value on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) value = MockValue( value_id=123456, index=0, instance=1, command_class=const.COMMAND_CLASS_PROTECTION) value.label = 'Protection Test' value.data_items = ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] value.data = 'Unprotected' network.nodes = {18: node} node.value = value resp = await client.post( '/api/zwave/protection/18', data=json.dumps({ 'value_id': '123456', 'selection': 'Protection by Sequence'})) assert resp.status == 200 result = await resp.json() assert node.set_protection.called assert result == {'message': 'Protection setting succsessfully set'} async def test_set_protection_value_failed(hass, client): """Test setting protection value failed on node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=18, command_classes=[const.COMMAND_CLASS_PROTECTION]) value = MockValue( value_id=123456, index=0, instance=1, command_class=const.COMMAND_CLASS_PROTECTION) value.label = 'Protection Test' value.data_items = ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] value.data = 'Unprotected' network.nodes = {18: node} node.value = value node.set_protection.return_value = False resp = await client.post( '/api/zwave/protection/18', data=json.dumps({ 'value_id': '123456', 'selection': 'Protecton by Seuence'})) assert resp.status == 202 result = await resp.json() assert node.set_protection.called assert result == {'message': 'Protection setting did not complete'} async def test_set_protection_value_nonexisting_node(hass, client): """Test setting protection value on nonexisting node.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=17, command_classes=[const.COMMAND_CLASS_PROTECTION]) value = MockValue( value_id=123456, index=0, instance=1, command_class=const.COMMAND_CLASS_PROTECTION) value.label = 'Protection Test' value.data_items = ['Unprotected', 'Protection by Sequence', 'No Operation Possible'] value.data = 'Unprotected' network.nodes = {17: node} node.value = value node.set_protection.return_value = False resp = await client.post( '/api/zwave/protection/18', data=json.dumps({ 'value_id': '123456', 'selection': 'Protecton by Seuence'})) assert resp.status == 404 result = await resp.json() assert not node.set_protection.called assert result == {'message': 'Node not found'} async def test_set_protection_value_missing_class(hass, client): """Test setting protection value on node without protectionclass.""" network = hass.data[DATA_NETWORK] = MagicMock() node = MockNode(node_id=17) value = MockValue( value_id=123456, index=0, instance=1) network.nodes = {17: node} node.value = value node.set_protection.return_value = False resp = await client.post( '/api/zwave/protection/17', data=json.dumps({ 'value_id': '123456', 'selection': 'Protecton by Seuence'})) assert resp.status == 404 result = await resp.json() assert not node.set_protection.called assert result == {'message': 'No protection commandclass on this node'}