diff --git a/homeassistant/components/light/zwave.py b/homeassistant/components/light/zwave.py index 7e23a68b887..59df6d8a745 100644 --- a/homeassistant/components/light/zwave.py +++ b/homeassistant/components/light/zwave.py @@ -67,7 +67,7 @@ def get_device(node, value, node_config, **kwargs): def brightness_state(value): """Return the brightness and state.""" if value.data > 0: - return (value.data / 99) * 255, STATE_ON + return round((value.data / 99) * 255, 0), STATE_ON else: return 0, STATE_OFF diff --git a/tests/components/light/test_zwave.py b/tests/components/light/test_zwave.py new file mode 100644 index 00000000000..5a1b5ee183d --- /dev/null +++ b/tests/components/light/test_zwave.py @@ -0,0 +1,62 @@ +"""Test Z-Wave lights.""" +from homeassistant.components.zwave import const +from homeassistant.components.light import zwave, ATTR_BRIGHTNESS + +from tests.mock.zwave import MockNode, MockValue, value_changed + + +def test_get_device_detects_dimmer(mock_openzwave): + """Test get_device returns a color light.""" + node = MockNode() + value = MockValue(data=0, node=node) + + device = zwave.get_device(node, value, {}) + assert isinstance(device, zwave.ZwaveDimmer) + + +def test_get_device_detects_colorlight(mock_openzwave): + """Test get_device returns a color light.""" + node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) + value = MockValue(data=0, node=node) + + device = zwave.get_device(node, value, {}) + assert isinstance(device, zwave.ZwaveColorLight) + + +def test_dimmer_turn_on(mock_openzwave): + """Test turning on a dimmable Z-Wave light.""" + node = MockNode() + value = MockValue(data=0, node=node) + device = zwave.get_device(node, value, {}) + + device.turn_on() + + assert node.set_dimmer.called + value_id, brightness = node.set_dimmer.mock_calls[0][1] + assert value_id == value.value_id + assert brightness == 255 + + node.reset_mock() + + device.turn_on(**{ATTR_BRIGHTNESS: 120}) + + assert node.set_dimmer.called + value_id, brightness = node.set_dimmer.mock_calls[0][1] + + assert value_id == value.value_id + assert brightness == 46 # int(120 / 255 * 99) + + +def test_dimmer_value_changed(mock_openzwave): + """Test value changed for dimmer lights.""" + node = MockNode() + value = MockValue(data=0, node=node) + device = zwave.get_device(node, value, {}) + + assert not device.is_on + + value.data = 46 + value_changed(value) + + assert device.is_on + assert device.brightness == 118 diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py index bf46fd33619..b982b357849 100644 --- a/tests/components/zwave/test_init.py +++ b/tests/components/zwave/test_init.py @@ -1,28 +1,11 @@ """Tests for the Z-Wave init.""" import asyncio -from unittest.mock import MagicMock, patch - -import pytest from homeassistant.bootstrap import async_setup_component -@pytest.fixture(autouse=True) -def mock_openzwave(): - """Mock out Open Z-Wave.""" - libopenzwave = MagicMock() - libopenzwave.__file__ = 'test' - with patch.dict('sys.modules', { - 'libopenzwave': libopenzwave, - 'openzwave.option': MagicMock(), - 'openzwave.network': MagicMock(), - 'openzwave.group': MagicMock(), - }): - yield - - @asyncio.coroutine -def test_valid_device_config(hass): +def test_valid_device_config(hass, mock_openzwave): """Test valid device config.""" device_config = { 'light.kitchen': { @@ -38,7 +21,7 @@ def test_valid_device_config(hass): @asyncio.coroutine -def test_invalid_device_config(hass): +def test_invalid_device_config(hass, mock_openzwave): """Test invalid device config.""" device_config = { 'light.kitchen': { diff --git a/tests/conftest.py b/tests/conftest.py index bc773de8489..4fb60dce1bf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ import asyncio import functools import logging import os -from unittest.mock import patch +from unittest.mock import patch, MagicMock import pytest import requests_mock as _requests_mock @@ -14,6 +14,7 @@ from homeassistant.components import mqtt from .common import async_test_home_assistant, mock_coro from .test_util.aiohttp import mock_aiohttp_client +from .mock.zwave import SIGNAL_VALUE_CHANGED if os.environ.get('UVLOOP') == '1': import uvloop @@ -91,3 +92,20 @@ def mqtt_mock(loop, hass): client = mock_mqtt() client.reset_mock() return client + + +@pytest.fixture +def mock_openzwave(): + """Mock out Open Z-Wave.""" + base_mock = MagicMock() + libopenzwave = base_mock.libopenzwave + libopenzwave.__file__ = 'test' + base_mock.network.ZWaveNetwork.SIGNAL_VALUE_CHANGED = SIGNAL_VALUE_CHANGED + + with patch.dict('sys.modules', { + 'libopenzwave': libopenzwave, + 'openzwave.option': base_mock.option, + 'openzwave.network': base_mock.network, + 'openzwave.group': base_mock.group, + }): + yield base_mock diff --git a/tests/mock/zwave.py b/tests/mock/zwave.py new file mode 100644 index 00000000000..6c1454be16b --- /dev/null +++ b/tests/mock/zwave.py @@ -0,0 +1,71 @@ +"""Mock helpers for Z-Wave component.""" +from unittest.mock import MagicMock + +from pydispatch import dispatcher + +SIGNAL_VALUE_CHANGED = 'mock_value_changed' + + +def value_changed(value): + """Fire a value changed.""" + dispatcher.send( + SIGNAL_VALUE_CHANGED, + value=value, + node=value.node, + network=value.node._network + ) + + +class MockNode(MagicMock): + """Mock Z-Wave node.""" + + def __init__(self, *, + node_id='567', + name='Mock Node', + manufacturer_id='ABCD', + product_id='123', + command_classes=None): + """Initialize a Z-Wave mock node.""" + super().__init__() + self.node_id = node_id + self.name = name + self.manufacturer_id = manufacturer_id + self.product_id = product_id + self._command_classes = command_classes or [] + + def has_command_class(self, command_class): + """Test if mock has a command class.""" + return command_class in self._command_classes + + def _get_child_mock(self, **kw): + """Create child mocks with right MagicMock class.""" + return MagicMock(**kw) + + +class MockValue(MagicMock): + """Mock Z-Wave value.""" + + _mock_value_id = 1234 + + def __init__(self, *, + label='Mock Value', + data=None, + node=None, + instance=0, + index=0, + value_id=None): + """Initialize a Z-Wave mock value.""" + super().__init__() + self.label = label + self.data = data + self.node = node + self.instance = instance + self.index = 0 + if value_id is None: + MockValue._mock_value_id += 1 + value_id = MockValue._mock_value_id + self.value_id = value_id + + def _get_child_mock(self, **kw): + """Create child mocks with right MagicMock class.""" + return MagicMock(**kw)