Rewritten HomeKit tests (#14377)

* Use pytest fixtures and parametrize
* Use async
This commit is contained in:
cdce8p 2018-05-11 01:21:59 +02:00 committed by GitHub
parent 6843893d9f
commit 8fcf085829
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1255 additions and 1591 deletions

View File

@ -3,8 +3,7 @@
This includes tests for all mock object types. This includes tests for all mock object types.
""" """
from datetime import datetime, timedelta from datetime import datetime, timedelta
import unittest from unittest.mock import patch, Mock
from unittest.mock import call, patch, Mock
from homeassistant.components.homekit.accessories import ( from homeassistant.components.homekit.accessories import (
debounce, HomeAccessory, HomeBridge, HomeDriver) debounce, HomeAccessory, HomeBridge, HomeDriver)
@ -15,8 +14,6 @@ from homeassistant.components.homekit.const import (
from homeassistant.const import __version__, ATTR_NOW, EVENT_TIME_CHANGED from homeassistant.const import __version__, ATTR_NOW, EVENT_TIME_CHANGED
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import get_test_home_assistant
def patch_debounce(): def patch_debounce():
"""Return patch for debounce method.""" """Return patch for debounce method."""
@ -24,141 +21,122 @@ def patch_debounce():
lambda f: lambda *args, **kwargs: f(*args, **kwargs)) lambda f: lambda *args, **kwargs: f(*args, **kwargs))
class TestAccessories(unittest.TestCase): async def test_debounce(hass):
"""Test pyhap adapter methods.""" """Test add_timeout decorator function."""
def demo_func(*args):
nonlocal arguments, counter
counter += 1
arguments = args
def test_debounce(self): arguments = None
"""Test add_timeout decorator function.""" counter = 0
def demo_func(*args): mock = Mock(hass=hass)
nonlocal arguments, counter
counter += 1
arguments = args
arguments = None debounce_demo = debounce(demo_func)
counter = 0 assert debounce_demo.__name__ == 'demo_func'
hass = get_test_home_assistant() now = datetime(2018, 1, 1, 20, 0, 0, tzinfo=dt_util.UTC)
mock = Mock(hass=hass)
debounce_demo = debounce(demo_func) with patch('homeassistant.util.dt.utcnow', return_value=now):
self.assertEqual(debounce_demo.__name__, 'demo_func') await hass.async_add_job(debounce_demo, mock, 'value')
now = datetime(2018, 1, 1, 20, 0, 0, tzinfo=dt_util.UTC) hass.bus.async_fire(
EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)})
await hass.async_block_till_done()
assert counter == 1
assert len(arguments) == 2
with patch('homeassistant.util.dt.utcnow', return_value=now): with patch('homeassistant.util.dt.utcnow', return_value=now):
debounce_demo(mock, 'value') await hass.async_add_job(debounce_demo, mock, 'value')
hass.bus.fire( await hass.async_add_job(debounce_demo, mock, 'value')
EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)})
hass.block_till_done()
assert counter == 1
assert len(arguments) == 2
with patch('homeassistant.util.dt.utcnow', return_value=now): hass.bus.async_fire(
debounce_demo(mock, 'value') EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)})
debounce_demo(mock, 'value') await hass.async_block_till_done()
assert counter == 2
hass.bus.fire(
EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)})
hass.block_till_done()
assert counter == 2
hass.stop() async def test_home_accessory(hass):
"""Test HomeAccessory class."""
acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2)
assert acc.hass == hass
assert acc.display_name == 'Home Accessory'
assert acc.category == 1 # Category.OTHER
assert len(acc.services) == 1
serv = acc.services[0] # SERV_ACCESSORY_INFO
assert serv.display_name == SERV_ACCESSORY_INFO
assert serv.get_characteristic(CHAR_NAME).value == 'Home Accessory'
assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
assert serv.get_characteristic(CHAR_MODEL).value == 'Homekit'
assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == \
'homekit.accessory'
def test_home_accessory(self): hass.states.async_set('homekit.accessory', 'on')
"""Test HomeAccessory class.""" await hass.async_block_till_done()
hass = get_test_home_assistant() await hass.async_add_job(acc.run)
hass.states.async_set('homekit.accessory', 'off')
await hass.async_block_till_done()
acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2) acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2)
self.assertEqual(acc.hass, hass) assert acc.display_name == 'test_name'
self.assertEqual(acc.display_name, 'Home Accessory') assert acc.aid == 2
self.assertEqual(acc.category, 1) # Category.OTHER assert len(acc.services) == 1
self.assertEqual(len(acc.services), 1) serv = acc.services[0] # SERV_ACCESSORY_INFO
serv = acc.services[0] # SERV_ACCESSORY_INFO assert serv.get_characteristic(CHAR_MODEL).value == 'Test Model'
self.assertEqual(serv.display_name, SERV_ACCESSORY_INFO)
self.assertEqual(
serv.get_characteristic(CHAR_NAME).value, 'Home Accessory')
self.assertEqual(
serv.get_characteristic(CHAR_MANUFACTURER).value, MANUFACTURER)
self.assertEqual(
serv.get_characteristic(CHAR_MODEL).value, 'Homekit')
self.assertEqual(serv.get_characteristic(CHAR_SERIAL_NUMBER).value,
'homekit.accessory')
hass.states.set('homekit.accessory', 'on')
hass.block_till_done()
acc.run()
hass.states.set('homekit.accessory', 'off')
hass.block_till_done()
acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2) def test_home_bridge():
self.assertEqual(acc.display_name, 'test_name') """Test HomeBridge class."""
self.assertEqual(acc.aid, 2) bridge = HomeBridge('hass')
self.assertEqual(len(acc.services), 1) assert bridge.hass == 'hass'
serv = acc.services[0] # SERV_ACCESSORY_INFO assert bridge.display_name == BRIDGE_NAME
self.assertEqual( assert bridge.category == 2 # Category.BRIDGE
serv.get_characteristic(CHAR_MODEL).value, 'Test Model') assert len(bridge.services) == 1
serv = bridge.services[0] # SERV_ACCESSORY_INFO
assert serv.display_name == SERV_ACCESSORY_INFO
assert serv.get_characteristic(CHAR_NAME).value == BRIDGE_NAME
assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == __version__
assert serv.get_characteristic(CHAR_MANUFACTURER).value == MANUFACTURER
assert serv.get_characteristic(CHAR_MODEL).value == BRIDGE_MODEL
assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == \
BRIDGE_SERIAL_NUMBER
hass.stop() bridge = HomeBridge('hass', 'test_name')
assert bridge.display_name == 'test_name'
assert len(bridge.services) == 1
serv = bridge.services[0] # SERV_ACCESSORY_INFO
def test_home_bridge(self): # setup_message
"""Test HomeBridge class.""" bridge.setup_message()
bridge = HomeBridge('hass')
self.assertEqual(bridge.hass, 'hass')
self.assertEqual(bridge.display_name, BRIDGE_NAME)
self.assertEqual(bridge.category, 2) # Category.BRIDGE
self.assertEqual(len(bridge.services), 1)
serv = bridge.services[0] # SERV_ACCESSORY_INFO
self.assertEqual(serv.display_name, SERV_ACCESSORY_INFO)
self.assertEqual(
serv.get_characteristic(CHAR_NAME).value, BRIDGE_NAME)
self.assertEqual(
serv.get_characteristic(CHAR_FIRMWARE_REVISION).value, __version__)
self.assertEqual(
serv.get_characteristic(CHAR_MANUFACTURER).value, MANUFACTURER)
self.assertEqual(
serv.get_characteristic(CHAR_MODEL).value, BRIDGE_MODEL)
self.assertEqual(
serv.get_characteristic(CHAR_SERIAL_NUMBER).value,
BRIDGE_SERIAL_NUMBER)
bridge = HomeBridge('hass', 'test_name') # add_paired_client
self.assertEqual(bridge.display_name, 'test_name') with patch('pyhap.accessory.Accessory.add_paired_client') \
self.assertEqual(len(bridge.services), 1) as mock_add_paired_client, \
serv = bridge.services[0] # SERV_ACCESSORY_INFO patch('homeassistant.components.homekit.accessories.'
'dismiss_setup_message') as mock_dissmiss_msg:
bridge.add_paired_client('client_uuid', 'client_public')
# setup_message mock_add_paired_client.assert_called_with('client_uuid', 'client_public')
bridge.setup_message() mock_dissmiss_msg.assert_called_with('hass')
# add_paired_client # remove_paired_client
with patch('pyhap.accessory.Accessory.add_paired_client') \ with patch('pyhap.accessory.Accessory.remove_paired_client') \
as mock_add_paired_client, \ as mock_remove_paired_client, \
patch('homeassistant.components.homekit.accessories.' patch('homeassistant.components.homekit.accessories.'
'dismiss_setup_message') as mock_dissmiss_msg: 'show_setup_message') as mock_show_msg:
bridge.add_paired_client('client_uuid', 'client_public') bridge.remove_paired_client('client_uuid')
self.assertEqual(mock_add_paired_client.call_args, mock_remove_paired_client.assert_called_with('client_uuid')
call('client_uuid', 'client_public')) mock_show_msg.assert_called_with('hass', bridge)
self.assertEqual(mock_dissmiss_msg.call_args, call('hass'))
# remove_paired_client
with patch('pyhap.accessory.Accessory.remove_paired_client') \
as mock_remove_paired_client, \
patch('homeassistant.components.homekit.accessories.'
'show_setup_message') as mock_show_msg:
bridge.remove_paired_client('client_uuid')
self.assertEqual( def test_home_driver():
mock_remove_paired_client.call_args, call('client_uuid')) """Test HomeDriver class."""
self.assertEqual(mock_show_msg.call_args, call('hass', bridge)) bridge = HomeBridge('hass')
ip_address = '127.0.0.1'
port = 51826
path = '.homekit.state'
def test_home_driver(self): with patch('pyhap.accessory_driver.AccessoryDriver.__init__') \
"""Test HomeDriver class.""" as mock_driver:
bridge = HomeBridge('hass') HomeDriver(bridge, ip_address, port, path)
ip_address = '127.0.0.1'
port = 51826
path = '.homekit.state'
with patch('pyhap.accessory_driver.AccessoryDriver.__init__') \ mock_driver.assert_called_with(bridge, ip_address, port, path)
as mock_driver:
HomeDriver(bridge, ip_address, port, path)
self.assertEqual(
mock_driver.call_args, call(bridge, ip_address, port, path))

View File

@ -1,22 +1,20 @@
"""Package to test the get_accessory method.""" """Package to test the get_accessory method."""
import logging import logging
import unittest
from unittest.mock import patch, Mock from unittest.mock import patch, Mock
import pytest
from homeassistant.core import State from homeassistant.core import State
from homeassistant.components.cover import ( from homeassistant.components.cover import SUPPORT_OPEN, SUPPORT_CLOSE
SUPPORT_OPEN, SUPPORT_CLOSE)
from homeassistant.components.climate import ( from homeassistant.components.climate import (
SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW) SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW)
from homeassistant.components.homekit import get_accessory, TYPES from homeassistant.components.homekit import get_accessory, TYPES
from homeassistant.const import ( from homeassistant.const import (
ATTR_CODE, ATTR_UNIT_OF_MEASUREMENT, ATTR_SUPPORTED_FEATURES, ATTR_CODE, ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES,
TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_DEVICE_CLASS) ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CONFIG = {}
def test_get_accessory_invalid_aid(caplog): def test_get_accessory_invalid_aid(caplog):
"""Test with unsupported component.""" """Test with unsupported component."""
@ -32,182 +30,93 @@ def test_not_supported():
is None is None
class TestGetAccessories(unittest.TestCase): @pytest.mark.parametrize('type_name, entity_id, state, attrs, config', [
"""Methods to test the get_accessory method.""" ('Light', 'light.test', 'on', {}, None),
('Lock', 'lock.test', 'locked', {}, None),
def setUp(self): ('Thermostat', 'climate.test', 'auto', {}, None),
"""Setup Mock type.""" ('Thermostat', 'climate.test', 'auto',
self.mock_type = Mock() {ATTR_SUPPORTED_FEATURES: SUPPORT_TARGET_TEMPERATURE_LOW |
SUPPORT_TARGET_TEMPERATURE_HIGH}, None),
def tearDown(self): ('SecuritySystem', 'alarm_control_panel.test', 'armed', {},
"""Test if mock type was called.""" {ATTR_CODE: '1234'}),
self.assertTrue(self.mock_type.called) ])
def test_types(type_name, entity_id, state, attrs, config):
"""Test if types are associated correctly."""
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, config)
assert mock_type.called
def test_sensor_temperature(self): if config:
"""Test temperature sensor with device class temperature.""" assert mock_type.call_args[1]['config'] == config
with patch.dict(TYPES, {'TemperatureSensor': self.mock_type}):
state = State('sensor.temperature', '23',
{ATTR_DEVICE_CLASS: 'temperature'})
get_accessory(None, state, 2, {})
def test_sensor_temperature_celsius(self):
"""Test temperature sensor with Celsius as unit."""
with patch.dict(TYPES, {'TemperatureSensor': self.mock_type}):
state = State('sensor.temperature', '23',
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
get_accessory(None, state, 2, {})
def test_sensor_temperature_fahrenheit(self): @pytest.mark.parametrize('type_name, entity_id, state, attrs', [
"""Test temperature sensor with Fahrenheit as unit.""" ('GarageDoorOpener', 'cover.garage_door', 'open',
with patch.dict(TYPES, {'TemperatureSensor': self.mock_type}): {ATTR_DEVICE_CLASS: 'garage',
state = State('sensor.temperature', '74', ATTR_SUPPORTED_FEATURES: SUPPORT_OPEN | SUPPORT_CLOSE}),
{ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT}) ('WindowCovering', 'cover.set_position', 'open',
get_accessory(None, state, 2, {}) {ATTR_SUPPORTED_FEATURES: 4}),
('WindowCoveringBasic', 'cover.open_window', 'open',
{ATTR_SUPPORTED_FEATURES: 3}),
])
def test_type_covers(type_name, entity_id, state, attrs):
"""Test if cover types are associated correctly."""
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None)
assert mock_type.called
def test_sensor_humidity(self):
"""Test humidity sensor with device class humidity."""
with patch.dict(TYPES, {'HumiditySensor': self.mock_type}):
state = State('sensor.humidity', '20',
{ATTR_DEVICE_CLASS: 'humidity',
ATTR_UNIT_OF_MEASUREMENT: '%'})
get_accessory(None, state, 2, {})
def test_air_quality_sensor(self): @pytest.mark.parametrize('type_name, entity_id, state, attrs', [
"""Test air quality sensor with pm25 class.""" ('BinarySensor', 'binary_sensor.opening', 'on',
with patch.dict(TYPES, {'AirQualitySensor': self.mock_type}): {ATTR_DEVICE_CLASS: 'opening'}),
state = State('sensor.air_quality', '40', ('BinarySensor', 'device_tracker.someone', 'not_home', {}),
{ATTR_DEVICE_CLASS: 'pm25'})
get_accessory(None, state, 2, {})
def test_air_quality_sensor_entity_id(self): ('AirQualitySensor', 'sensor.air_quality_pm25', '40', {}),
"""Test air quality sensor with entity_id contains pm25.""" ('AirQualitySensor', 'sensor.air_quality', '40',
with patch.dict(TYPES, {'AirQualitySensor': self.mock_type}): {ATTR_DEVICE_CLASS: 'pm25'}),
state = State('sensor.air_quality_pm25', '40', {})
get_accessory(None, state, 2, {})
def test_co2_sensor(self): ('CarbonDioxideSensor', 'sensor.airmeter_co2', '500', {}),
"""Test co2 sensor with device class co2.""" ('CarbonDioxideSensor', 'sensor.airmeter', '500',
with patch.dict(TYPES, {'CarbonDioxideSensor': self.mock_type}): {ATTR_DEVICE_CLASS: 'co2'}),
state = State('sensor.airmeter', '500',
{ATTR_DEVICE_CLASS: 'co2'})
get_accessory(None, state, 2, {})
def test_co2_sensor_entity_id(self): ('HumiditySensor', 'sensor.humidity', '20',
"""Test co2 sensor with entity_id contains co2.""" {ATTR_DEVICE_CLASS: 'humidity', ATTR_UNIT_OF_MEASUREMENT: '%'}),
with patch.dict(TYPES, {'CarbonDioxideSensor': self.mock_type}):
state = State('sensor.airmeter_co2', '500', {})
get_accessory(None, state, 2, {})
def test_light_sensor(self): ('LightSensor', 'sensor.light', '900', {ATTR_DEVICE_CLASS: 'illuminance'}),
"""Test light sensor with device class illuminance.""" ('LightSensor', 'sensor.light', '900', {ATTR_UNIT_OF_MEASUREMENT: 'lm'}),
with patch.dict(TYPES, {'LightSensor': self.mock_type}): ('LightSensor', 'sensor.light', '900', {ATTR_UNIT_OF_MEASUREMENT: 'lx'}),
state = State('sensor.light', '900',
{ATTR_DEVICE_CLASS: 'illuminance'})
get_accessory(None, state, 2, {})
def test_light_sensor_unit_lm(self): ('TemperatureSensor', 'sensor.temperature', '23',
"""Test light sensor with lm as unit.""" {ATTR_DEVICE_CLASS: 'temperature'}),
with patch.dict(TYPES, {'LightSensor': self.mock_type}): ('TemperatureSensor', 'sensor.temperature', '23',
state = State('sensor.light', '900', {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}),
{ATTR_UNIT_OF_MEASUREMENT: 'lm'}) ('TemperatureSensor', 'sensor.temperature', '74',
get_accessory(None, state, 2, {}) {ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT}),
])
def test_type_sensors(type_name, entity_id, state, attrs):
"""Test if sensor types are associated correctly."""
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None)
assert mock_type.called
def test_light_sensor_unit_lx(self):
"""Test light sensor with lx as unit."""
with patch.dict(TYPES, {'LightSensor': self.mock_type}):
state = State('sensor.light', '900',
{ATTR_UNIT_OF_MEASUREMENT: 'lx'})
get_accessory(None, state, 2, {})
def test_binary_sensor(self): @pytest.mark.parametrize('type_name, entity_id, state, attrs', [
"""Test binary sensor with opening class.""" ('Switch', 'switch.test', 'on', {}),
with patch.dict(TYPES, {'BinarySensor': self.mock_type}): ('Switch', 'remote.test', 'on', {}),
state = State('binary_sensor.opening', 'on', ('Switch', 'input_boolean.test', 'on', {}),
{ATTR_DEVICE_CLASS: 'opening'}) ])
get_accessory(None, state, 2, {}) def test_type_switches(type_name, entity_id, state, attrs):
"""Test if switch types are associated correctly."""
def test_device_tracker(self): mock_type = Mock()
"""Test binary sensor with opening class.""" with patch.dict(TYPES, {type_name: mock_type}):
with patch.dict(TYPES, {'BinarySensor': self.mock_type}): entity_state = State(entity_id, state, attrs)
state = State('device_tracker.someone', 'not_home', {}) get_accessory(None, entity_state, 2, None)
get_accessory(None, state, 2, {}) assert mock_type.called
def test_garage_door(self):
"""Test cover with device_class: 'garage' and required features."""
with patch.dict(TYPES, {'GarageDoorOpener': self.mock_type}):
state = State('cover.garage_door', 'open', {
ATTR_DEVICE_CLASS: 'garage',
ATTR_SUPPORTED_FEATURES:
SUPPORT_OPEN | SUPPORT_CLOSE})
get_accessory(None, state, 2, {})
def test_cover_set_position(self):
"""Test cover with support for set_cover_position."""
with patch.dict(TYPES, {'WindowCovering': self.mock_type}):
state = State('cover.set_position', 'open',
{ATTR_SUPPORTED_FEATURES: 4})
get_accessory(None, state, 2, {})
def test_cover_open_close(self):
"""Test cover with support for open and close."""
with patch.dict(TYPES, {'WindowCoveringBasic': self.mock_type}):
state = State('cover.open_window', 'open',
{ATTR_SUPPORTED_FEATURES: 3})
get_accessory(None, state, 2, {})
def test_alarm_control_panel(self):
"""Test alarm control panel."""
config = {ATTR_CODE: '1234'}
with patch.dict(TYPES, {'SecuritySystem': self.mock_type}):
state = State('alarm_control_panel.test', 'armed')
get_accessory(None, state, 2, config)
# pylint: disable=unsubscriptable-object
print(self.mock_type.call_args[1])
self.assertEqual(
self.mock_type.call_args[1]['config'][ATTR_CODE], '1234')
def test_climate(self):
"""Test climate devices."""
with patch.dict(TYPES, {'Thermostat': self.mock_type}):
state = State('climate.test', 'auto')
get_accessory(None, state, 2, {})
def test_light(self):
"""Test light devices."""
with patch.dict(TYPES, {'Light': self.mock_type}):
state = State('light.test', 'on')
get_accessory(None, state, 2, {})
def test_climate_support_auto(self):
"""Test climate devices with support for auto mode."""
with patch.dict(TYPES, {'Thermostat': self.mock_type}):
state = State('climate.test', 'auto', {
ATTR_SUPPORTED_FEATURES:
SUPPORT_TARGET_TEMPERATURE_LOW |
SUPPORT_TARGET_TEMPERATURE_HIGH})
get_accessory(None, state, 2, {})
def test_switch(self):
"""Test switch."""
with patch.dict(TYPES, {'Switch': self.mock_type}):
state = State('switch.test', 'on')
get_accessory(None, state, 2, {})
def test_remote(self):
"""Test remote."""
with patch.dict(TYPES, {'Switch': self.mock_type}):
state = State('remote.test', 'on')
get_accessory(None, state, 2, {})
def test_input_boolean(self):
"""Test input_boolean."""
with patch.dict(TYPES, {'Switch': self.mock_type}):
state = State('input_boolean.test', 'on')
get_accessory(None, state, 2, {})
def test_lock(self):
"""Test lock."""
with patch.dict(TYPES, {'Lock': self.mock_type}):
state = State('lock.test', 'locked')
get_accessory(None, state, 2, {})

View File

@ -1,6 +1,7 @@
"""Tests for the HomeKit component.""" """Tests for the HomeKit component."""
import unittest from unittest.mock import patch, ANY, Mock
from unittest.mock import call, patch, ANY, Mock
import pytest
from homeassistant import setup from homeassistant import setup
from homeassistant.core import State from homeassistant.core import State
@ -16,208 +17,193 @@ from homeassistant.const import (
CONF_IP_ADDRESS, CONF_PORT, CONF_IP_ADDRESS, CONF_PORT,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
from tests.common import get_test_home_assistant
from tests.components.homekit.test_accessories import patch_debounce from tests.components.homekit.test_accessories import patch_debounce
IP_ADDRESS = '127.0.0.1' IP_ADDRESS = '127.0.0.1'
PATH_HOMEKIT = 'homeassistant.components.homekit' PATH_HOMEKIT = 'homeassistant.components.homekit'
class TestHomeKit(unittest.TestCase): @pytest.fixture('module')
"""Test setup of HomeKit component and HomeKit class.""" def debounce_patcher(request):
"""Patch debounce method."""
patcher = patch_debounce()
patcher.start()
request.addfinalizer(patcher.stop)
@classmethod
def setUpClass(cls):
"""Setup debounce patcher."""
cls.patcher = patch_debounce()
cls.patcher.start()
@classmethod def test_generate_aid():
def tearDownClass(cls): """Test generate aid method."""
"""Stop debounce patcher.""" aid = generate_aid('demo.entity')
cls.patcher.stop() assert isinstance(aid, int)
assert aid >= 2 and aid <= 18446744073709551615
def setUp(self): with patch(PATH_HOMEKIT + '.adler32') as mock_adler32:
"""Setup things to be run when tests are started.""" mock_adler32.side_effect = [0, 1]
self.hass = get_test_home_assistant() assert generate_aid('demo.entity') is None
def tearDown(self):
"""Stop down everything that was started."""
self.hass.stop()
def test_generate_aid(self): async def test_setup_min(hass):
"""Test generate aid method.""" """Test async_setup with min config options."""
aid = generate_aid('demo.entity') with patch(PATH_HOMEKIT + '.HomeKit') as mock_homekit:
self.assertIsInstance(aid, int) assert await setup.async_setup_component(
self.assertTrue(aid >= 2 and aid <= 18446744073709551615) hass, DOMAIN, {DOMAIN: {}})
with patch(PATH_HOMEKIT + '.adler32') as mock_adler32: mock_homekit.assert_any_call(hass, DEFAULT_PORT, None, ANY, {})
mock_adler32.side_effect = [0, 1] assert mock_homekit().setup.called is True
self.assertIsNone(generate_aid('demo.entity'))
@patch(PATH_HOMEKIT + '.HomeKit') # Test auto start enabled
def test_setup_min(self, mock_homekit): mock_homekit.reset_mock()
"""Test async_setup with min config options.""" hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
self.assertTrue(setup.setup_component( await hass.async_block_till_done()
self.hass, DOMAIN, {DOMAIN: {}}))
self.assertEqual(mock_homekit.mock_calls, [ mock_homekit().start.assert_called_with(ANY)
call(self.hass, DEFAULT_PORT, None, ANY, {}),
call().setup()])
# Test auto start enabled
mock_homekit.reset_mock()
self.hass.bus.fire(EVENT_HOMEASSISTANT_START)
self.hass.block_till_done()
self.assertEqual(mock_homekit.mock_calls, [call().start(ANY)]) async def test_setup_auto_start_disabled(hass):
"""Test async_setup with auto start disabled and test service calls."""
config = {DOMAIN: {CONF_AUTO_START: False, CONF_PORT: 11111,
CONF_IP_ADDRESS: '172.0.0.0'}}
@patch(PATH_HOMEKIT + '.HomeKit') with patch(PATH_HOMEKIT + '.HomeKit') as mock_homekit:
def test_setup_auto_start_disabled(self, mock_homekit):
"""Test async_setup with auto start disabled and test service calls."""
mock_homekit.return_value = homekit = Mock() mock_homekit.return_value = homekit = Mock()
assert await setup.async_setup_component(
hass, DOMAIN, config)
config = {DOMAIN: {CONF_AUTO_START: False, CONF_PORT: 11111, mock_homekit.assert_any_call(hass, 11111, '172.0.0.0', ANY, {})
CONF_IP_ADDRESS: '172.0.0.0'}} assert mock_homekit().setup.called is True
self.assertTrue(setup.setup_component(
self.hass, DOMAIN, config))
self.hass.block_till_done()
self.assertEqual(mock_homekit.mock_calls, [ # Test auto_start disabled
call(self.hass, 11111, '172.0.0.0', ANY, {}), homekit.reset_mock()
call().setup()]) hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
assert homekit.start.called is False
# Test auto_start disabled # Test start call with driver is ready
homekit.reset_mock() homekit.reset_mock()
self.hass.bus.fire(EVENT_HOMEASSISTANT_START) homekit.status = STATUS_READY
self.hass.block_till_done()
self.assertEqual(homekit.mock_calls, [])
# Test start call with driver is ready await hass.services.async_call(
homekit.reset_mock() DOMAIN, SERVICE_HOMEKIT_START, blocking=True)
homekit.status = STATUS_READY assert homekit.start.called is True
self.hass.services.call('homekit', 'start') # Test start call with driver started
self.assertEqual(homekit.mock_calls, [call.start()]) homekit.reset_mock()
homekit.status = STATUS_STOPPED
# Test start call with driver started await hass.services.async_call(
homekit.reset_mock() DOMAIN, SERVICE_HOMEKIT_START, blocking=True)
homekit.status = STATUS_STOPPED assert homekit.start.called is False
self.hass.services.call(DOMAIN, SERVICE_HOMEKIT_START)
self.assertEqual(homekit.mock_calls, [])
def test_homekit_setup(self): async def test_homekit_setup(hass):
"""Test setup of bridge and driver.""" """Test setup of bridge and driver."""
homekit = HomeKit(self.hass, DEFAULT_PORT, None, {}, {}) homekit = HomeKit(hass, DEFAULT_PORT, None, {}, {})
with patch(PATH_HOMEKIT + '.accessories.HomeDriver') as mock_driver, \ with patch(PATH_HOMEKIT + '.accessories.HomeDriver') as mock_driver, \
patch('homeassistant.util.get_local_ip') as mock_ip: patch('homeassistant.util.get_local_ip') as mock_ip:
mock_ip.return_value = IP_ADDRESS mock_ip.return_value = IP_ADDRESS
homekit.setup() await hass.async_add_job(homekit.setup)
path = self.hass.config.path(HOMEKIT_FILE) path = hass.config.path(HOMEKIT_FILE)
self.assertTrue(isinstance(homekit.bridge, HomeBridge)) assert isinstance(homekit.bridge, HomeBridge)
self.assertEqual(mock_driver.mock_calls, [ mock_driver.assert_called_with(
call(homekit.bridge, DEFAULT_PORT, IP_ADDRESS, path)]) homekit.bridge, DEFAULT_PORT, IP_ADDRESS, path)
# Test if stop listener is setup # Test if stop listener is setup
self.assertEqual( assert hass.bus.async_listeners().get(EVENT_HOMEASSISTANT_STOP) == 1
self.hass.bus.listeners.get(EVENT_HOMEASSISTANT_STOP), 1)
def test_homekit_setup_ip_address(self):
"""Test setup with given IP address."""
homekit = HomeKit(self.hass, DEFAULT_PORT, '172.0.0.0', {}, {})
with patch(PATH_HOMEKIT + '.accessories.HomeDriver') as mock_driver: async def test_homekit_setup_ip_address(hass):
homekit.setup() """Test setup with given IP address."""
mock_driver.assert_called_with(ANY, DEFAULT_PORT, '172.0.0.0', ANY) homekit = HomeKit(hass, DEFAULT_PORT, '172.0.0.0', {}, {})
def test_homekit_add_accessory(self): with patch(PATH_HOMEKIT + '.accessories.HomeDriver') as mock_driver:
"""Add accessory if config exists and get_acc returns an accessory.""" await hass.async_add_job(homekit.setup)
homekit = HomeKit(self.hass, None, None, lambda entity_id: True, {}) mock_driver.assert_called_with(ANY, DEFAULT_PORT, '172.0.0.0', ANY)
homekit.bridge = HomeBridge(self.hass)
with patch(PATH_HOMEKIT + '.accessories.HomeBridge.add_accessory') \
as mock_add_acc, \
patch(PATH_HOMEKIT + '.get_accessory') as mock_get_acc:
mock_get_acc.side_effect = [None, 'acc', None]
homekit.add_bridge_accessory(State('light.demo', 'on'))
self.assertEqual(mock_get_acc.call_args,
call(self.hass, ANY, 363398124, {}))
self.assertFalse(mock_add_acc.called)
homekit.add_bridge_accessory(State('demo.test', 'on'))
self.assertEqual(mock_get_acc.call_args,
call(self.hass, ANY, 294192020, {}))
self.assertTrue(mock_add_acc.called)
homekit.add_bridge_accessory(State('demo.test_2', 'on'))
self.assertEqual(mock_get_acc.call_args,
call(self.hass, ANY, 429982757, {}))
self.assertEqual(mock_add_acc.mock_calls, [call('acc')])
def test_homekit_entity_filter(self): async def test_homekit_add_accessory(hass):
"""Test the entity filter.""" """Add accessory if config exists and get_acc returns an accessory."""
entity_filter = generate_filter(['cover'], ['demo.test'], [], []) homekit = HomeKit(hass, None, None, lambda entity_id: True, {})
homekit = HomeKit(self.hass, None, None, entity_filter, {}) homekit.bridge = HomeBridge(hass)
with patch(PATH_HOMEKIT + '.get_accessory') as mock_get_acc: with patch(PATH_HOMEKIT + '.accessories.HomeBridge.add_accessory') \
mock_get_acc.return_value = None as mock_add_acc, \
patch(PATH_HOMEKIT + '.get_accessory') as mock_get_acc:
homekit.add_bridge_accessory(State('cover.test', 'open')) mock_get_acc.side_effect = [None, 'acc', None]
self.assertTrue(mock_get_acc.called) homekit.add_bridge_accessory(State('light.demo', 'on'))
mock_get_acc.reset_mock() mock_get_acc.assert_called_with(hass, ANY, 363398124, {})
assert mock_add_acc.called is False
homekit.add_bridge_accessory(State('demo.test', 'on')) homekit.add_bridge_accessory(State('demo.test', 'on'))
self.assertTrue(mock_get_acc.called) mock_get_acc.assert_called_with(hass, ANY, 294192020, {})
mock_get_acc.reset_mock() assert mock_add_acc.called is True
homekit.add_bridge_accessory(State('light.demo', 'light')) homekit.add_bridge_accessory(State('demo.test_2', 'on'))
self.assertFalse(mock_get_acc.called) mock_get_acc.assert_called_with(hass, ANY, 429982757, {})
mock_add_acc.assert_called_with('acc')
@patch(PATH_HOMEKIT + '.show_setup_message')
@patch(PATH_HOMEKIT + '.HomeKit.add_bridge_accessory')
def test_homekit_start(self, mock_add_bridge_acc, mock_show_setup_msg):
"""Test HomeKit start method."""
homekit = HomeKit(self.hass, None, None, {}, {'cover.demo': {}})
homekit.bridge = HomeBridge(self.hass)
homekit.driver = Mock()
self.hass.states.set('light.demo', 'on') async def test_homekit_entity_filter(hass):
state = self.hass.states.all()[0] """Test the entity filter."""
entity_filter = generate_filter(['cover'], ['demo.test'], [], [])
homekit = HomeKit(hass, None, None, entity_filter, {})
homekit.start() with patch(PATH_HOMEKIT + '.get_accessory') as mock_get_acc:
self.hass.block_till_done() mock_get_acc.return_value = None
self.assertEqual(mock_add_bridge_acc.mock_calls, [call(state)]) homekit.add_bridge_accessory(State('cover.test', 'open'))
self.assertEqual(mock_show_setup_msg.mock_calls, [ assert mock_get_acc.called is True
call(self.hass, homekit.bridge)]) mock_get_acc.reset_mock()
self.assertEqual(homekit.driver.mock_calls, [call.start()])
self.assertEqual(homekit.status, STATUS_RUNNING)
# Test start() if already started homekit.add_bridge_accessory(State('demo.test', 'on'))
homekit.driver.reset_mock() assert mock_get_acc.called is True
homekit.start() mock_get_acc.reset_mock()
self.hass.block_till_done()
self.assertEqual(homekit.driver.mock_calls, [])
def test_homekit_stop(self): homekit.add_bridge_accessory(State('light.demo', 'light'))
"""Test HomeKit stop method.""" assert mock_get_acc.called is False
homekit = HomeKit(self.hass, None, None, None, None)
homekit.driver = Mock()
self.assertEqual(homekit.status, STATUS_READY)
homekit.stop()
self.hass.block_till_done()
homekit.status = STATUS_WAIT
homekit.stop()
self.hass.block_till_done()
homekit.status = STATUS_STOPPED
homekit.stop()
self.hass.block_till_done()
self.assertFalse(homekit.driver.stop.called)
# Test if driver is started async def test_homekit_start(hass, debounce_patcher):
homekit.status = STATUS_RUNNING """Test HomeKit start method."""
homekit.stop() homekit = HomeKit(hass, None, None, {}, {'cover.demo': {}})
self.hass.block_till_done() homekit.bridge = HomeBridge(hass)
self.assertTrue(homekit.driver.stop.called) homekit.driver = Mock()
hass.states.async_set('light.demo', 'on')
state = hass.states.async_all()[0]
with patch(PATH_HOMEKIT + '.HomeKit.add_bridge_accessory') as \
mock_add_acc, \
patch(PATH_HOMEKIT + '.show_setup_message') as mock_setup_msg:
await hass.async_add_job(homekit.start)
mock_add_acc.assert_called_with(state)
mock_setup_msg.assert_called_with(hass, homekit.bridge)
assert homekit.driver.start.called is True
assert homekit.status == STATUS_RUNNING
# Test start() if already started
homekit.driver.reset_mock()
await hass.async_add_job(homekit.start)
assert homekit.driver.start.called is False
async def test_homekit_stop(hass):
"""Test HomeKit stop method."""
homekit = HomeKit(hass, None, None, None, None)
homekit.driver = Mock()
assert homekit.status == STATUS_READY
await hass.async_add_job(homekit.stop)
homekit.status = STATUS_WAIT
await hass.async_add_job(homekit.stop)
homekit.status = STATUS_STOPPED
await hass.async_add_job(homekit.stop)
assert homekit.driver.stop.called is False
# Test if driver is started
homekit.status = STATUS_RUNNING
await hass.async_add_job(homekit.stop)
assert homekit.driver.stop.called is True

View File

@ -1,265 +1,231 @@
"""Test different accessory types: Covers.""" """Test different accessory types: Covers."""
import unittest from collections import namedtuple
import pytest
from homeassistant.core import callback
from homeassistant.components.cover import ( from homeassistant.components.cover import (
ATTR_POSITION, ATTR_CURRENT_POSITION, SUPPORT_STOP) DOMAIN, ATTR_CURRENT_POSITION, ATTR_POSITION, SUPPORT_STOP)
from homeassistant.const import ( from homeassistant.const import (
STATE_CLOSED, STATE_UNAVAILABLE, STATE_UNKNOWN, STATE_OPEN, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES,
ATTR_SERVICE, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE, STATE_CLOSED, STATE_OPEN, STATE_UNAVAILABLE, STATE_UNKNOWN)
ATTR_SUPPORTED_FEATURES)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
from tests.components.homekit.test_accessories import patch_debounce from tests.components.homekit.test_accessories import patch_debounce
class TestHomekitCovers(unittest.TestCase): @pytest.fixture(scope='module')
"""Test class for all accessory types regarding covers.""" def cls(request):
"""Patch debounce decorator during import of type_covers."""
patcher = patch_debounce()
patcher.start()
_import = __import__('homeassistant.components.homekit.type_covers',
fromlist=['GarageDoorOpener', 'WindowCovering,',
'WindowCoveringBasic'])
request.addfinalizer(patcher.stop)
patcher_tuple = namedtuple('Cls', ['window', 'window_basic', 'garage'])
return patcher_tuple(window=_import.WindowCovering,
window_basic=_import.WindowCoveringBasic,
garage=_import.GarageDoorOpener)
@classmethod
def setUpClass(cls):
"""Setup Light class import and debounce patcher."""
cls.patcher = patch_debounce()
cls.patcher.start()
_import = __import__('homeassistant.components.homekit.type_covers',
fromlist=['GarageDoorOpener', 'WindowCovering,',
'WindowCoveringBasic'])
cls.garage_cls = _import.GarageDoorOpener
cls.window_cls = _import.WindowCovering
cls.window_basic_cls = _import.WindowCoveringBasic
@classmethod async def test_garage_door_open_close(hass, cls):
def tearDownClass(cls): """Test if accessory and HA are updated accordingly."""
"""Stop debounce patcher.""" entity_id = 'cover.garage_door'
cls.patcher.stop()
def setUp(self): acc = cls.garage(hass, 'Garage Door', entity_id, 2, config=None)
"""Setup things to be run when tests are started.""" await hass.async_add_job(acc.run)
self.hass = get_test_home_assistant()
self.events = []
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 4 # GarageDoorOpener
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
def tearDown(self): hass.states.async_set(entity_id, STATE_CLOSED)
"""Stop down everything that was started.""" await hass.async_block_till_done()
self.hass.stop() assert acc.char_current_state.value == 1
assert acc.char_target_state.value == 1
def test_garage_door_open_close(self): hass.states.async_set(entity_id, STATE_OPEN)
"""Test if accessory and HA are updated accordingly.""" await hass.async_block_till_done()
garage_door = 'cover.garage_door' assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
acc = self.garage_cls(self.hass, 'Cover', garage_door, 2, config=None) hass.states.async_set(entity_id, STATE_UNAVAILABLE)
acc.run() await hass.async_block_till_done()
assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, STATE_UNKNOWN)
self.assertEqual(acc.category, 4) # GarageDoorOpener await hass.async_block_till_done()
assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
self.assertEqual(acc.char_current_state.value, 0) # Set from HomeKit
self.assertEqual(acc.char_target_state.value, 0) call_close_cover = async_mock_service(hass, DOMAIN, 'close_cover')
call_open_cover = async_mock_service(hass, DOMAIN, 'open_cover')
self.hass.states.set(garage_door, STATE_CLOSED) await hass.async_add_job(acc.char_target_state.client_update_value, 1)
self.hass.block_till_done() await hass.async_block_till_done()
assert call_close_cover
assert call_close_cover[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_state.value == 2
assert acc.char_target_state.value == 1
self.assertEqual(acc.char_current_state.value, 1) hass.states.async_set(entity_id, STATE_CLOSED)
self.assertEqual(acc.char_target_state.value, 1) await hass.async_block_till_done()
self.hass.states.set(garage_door, STATE_OPEN) await hass.async_add_job(acc.char_target_state.client_update_value, 0)
self.hass.block_till_done() await hass.async_block_till_done()
assert call_open_cover
assert call_open_cover[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 0
self.assertEqual(acc.char_current_state.value, 0)
self.assertEqual(acc.char_target_state.value, 0)
self.hass.states.set(garage_door, STATE_UNAVAILABLE) async def test_window_set_cover_position(hass, cls):
self.hass.block_till_done() """Test if accessory and HA are updated accordingly."""
entity_id = 'cover.window'
self.assertEqual(acc.char_current_state.value, 0) acc = cls.window(hass, 'Cover', entity_id, 2, config=None)
self.assertEqual(acc.char_target_state.value, 0) await hass.async_add_job(acc.run)
self.hass.states.set(garage_door, STATE_UNKNOWN) assert acc.aid == 2
self.hass.block_till_done() assert acc.category == 14 # WindowCovering
self.assertEqual(acc.char_current_state.value, 0) assert acc.char_current_position.value == 0
self.assertEqual(acc.char_target_state.value, 0) assert acc.char_target_position.value == 0
# Set closed from HomeKit hass.states.async_set(entity_id, STATE_UNKNOWN,
acc.char_target_state.client_update_value(1) {ATTR_CURRENT_POSITION: None})
self.hass.block_till_done() await hass.async_block_till_done()
assert acc.char_current_position.value == 0
assert acc.char_target_position.value == 0
self.assertEqual(acc.char_current_state.value, 2) hass.states.async_set(entity_id, STATE_OPEN,
self.assertEqual(acc.char_target_state.value, 1) {ATTR_CURRENT_POSITION: 50})
self.assertEqual( await hass.async_block_till_done()
self.events[0].data[ATTR_SERVICE], 'close_cover') assert acc.char_current_position.value == 50
assert acc.char_target_position.value == 50
self.hass.states.set(garage_door, STATE_CLOSED) # Set from HomeKit
self.hass.block_till_done() call_set_cover_position = async_mock_service(hass, DOMAIN,
'set_cover_position')
# Set open from HomeKit await hass.async_add_job(acc.char_target_position.client_update_value, 25)
acc.char_target_state.client_update_value(0) await hass.async_block_till_done()
self.hass.block_till_done() assert call_set_cover_position[0]
assert call_set_cover_position[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_cover_position[0].data[ATTR_POSITION] == 25
assert acc.char_current_position.value == 50
assert acc.char_target_position.value == 25
self.assertEqual(acc.char_current_state.value, 3) await hass.async_add_job(acc.char_target_position.client_update_value, 75)
self.assertEqual(acc.char_target_state.value, 0) await hass.async_block_till_done()
self.assertEqual( assert call_set_cover_position[1]
self.events[1].data[ATTR_SERVICE], 'open_cover') assert call_set_cover_position[1].data[ATTR_ENTITY_ID] == entity_id
assert call_set_cover_position[1].data[ATTR_POSITION] == 75
assert acc.char_current_position.value == 50
assert acc.char_target_position.value == 75
def test_window_set_cover_position(self):
"""Test if accessory and HA are updated accordingly."""
window_cover = 'cover.window'
acc = self.window_cls(self.hass, 'Cover', window_cover, 2, config=None) async def test_window_open_close(hass, cls):
acc.run() """Test if accessory and HA are updated accordingly."""
entity_id = 'cover.window'
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, STATE_UNKNOWN,
self.assertEqual(acc.category, 14) # WindowCovering {ATTR_SUPPORTED_FEATURES: 0})
acc = cls.window_basic(hass, 'Cover', entity_id, 2, config=None)
await hass.async_add_job(acc.run)
self.assertEqual(acc.char_current_position.value, 0) assert acc.aid == 2
self.assertEqual(acc.char_target_position.value, 0) assert acc.category == 14 # WindowCovering
self.hass.states.set(window_cover, STATE_UNKNOWN, assert acc.char_current_position.value == 0
{ATTR_CURRENT_POSITION: None}) assert acc.char_target_position.value == 0
self.hass.block_till_done() assert acc.char_position_state.value == 2
self.assertEqual(acc.char_current_position.value, 0) hass.states.async_set(entity_id, STATE_UNKNOWN)
self.assertEqual(acc.char_target_position.value, 0) await hass.async_block_till_done()
assert acc.char_current_position.value == 0
assert acc.char_target_position.value == 0
assert acc.char_position_state.value == 2
self.hass.states.set(window_cover, STATE_OPEN, hass.states.async_set(entity_id, STATE_OPEN)
{ATTR_CURRENT_POSITION: 50}) await hass.async_block_till_done()
self.hass.block_till_done() assert acc.char_current_position.value == 100
assert acc.char_target_position.value == 100
assert acc.char_position_state.value == 2
self.assertEqual(acc.char_current_position.value, 50) hass.states.async_set(entity_id, STATE_CLOSED)
self.assertEqual(acc.char_target_position.value, 50) await hass.async_block_till_done()
assert acc.char_current_position.value == 0
assert acc.char_target_position.value == 0
assert acc.char_position_state.value == 2
# Set from HomeKit # Set from HomeKit
acc.char_target_position.client_update_value(25) call_close_cover = async_mock_service(hass, DOMAIN, 'close_cover')
self.hass.block_till_done() call_open_cover = async_mock_service(hass, DOMAIN, 'open_cover')
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'set_cover_position')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_POSITION], 25)
self.assertEqual(acc.char_current_position.value, 50) await hass.async_add_job(acc.char_target_position.client_update_value, 25)
self.assertEqual(acc.char_target_position.value, 25) await hass.async_block_till_done()
assert call_close_cover
assert call_close_cover[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_position.value == 0
assert acc.char_target_position.value == 0
assert acc.char_position_state.value == 2
# Set from HomeKit await hass.async_add_job(acc.char_target_position.client_update_value, 90)
acc.char_target_position.client_update_value(75) await hass.async_block_till_done()
self.hass.block_till_done() assert call_open_cover[0]
self.assertEqual( assert call_open_cover[0].data[ATTR_ENTITY_ID] == entity_id
self.events[1].data[ATTR_SERVICE], 'set_cover_position') assert acc.char_current_position.value == 100
self.assertEqual( assert acc.char_target_position.value == 100
self.events[1].data[ATTR_SERVICE_DATA][ATTR_POSITION], 75) assert acc.char_position_state.value == 2
self.assertEqual(acc.char_current_position.value, 50) await hass.async_add_job(acc.char_target_position.client_update_value, 55)
self.assertEqual(acc.char_target_position.value, 75) await hass.async_block_till_done()
assert call_open_cover[1]
assert call_open_cover[1].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_position.value == 100
assert acc.char_target_position.value == 100
assert acc.char_position_state.value == 2
def test_window_open_close(self):
"""Test if accessory and HA are updated accordingly."""
window_cover = 'cover.window'
self.hass.states.set(window_cover, STATE_UNKNOWN, async def test_window_open_close_stop(hass, cls):
{ATTR_SUPPORTED_FEATURES: 0}) """Test if accessory and HA are updated accordingly."""
acc = self.window_basic_cls(self.hass, 'Cover', window_cover, 2, entity_id = 'cover.window'
config=None)
acc.run()
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, STATE_UNKNOWN,
self.assertEqual(acc.category, 14) # WindowCovering {ATTR_SUPPORTED_FEATURES: SUPPORT_STOP})
acc = cls.window_basic(hass, 'Cover', entity_id, 2, config=None)
await hass.async_add_job(acc.run)
self.assertEqual(acc.char_current_position.value, 0) # Set from HomeKit
self.assertEqual(acc.char_target_position.value, 0) call_close_cover = async_mock_service(hass, DOMAIN, 'close_cover')
self.assertEqual(acc.char_position_state.value, 2) call_open_cover = async_mock_service(hass, DOMAIN, 'open_cover')
call_stop_cover = async_mock_service(hass, DOMAIN, 'stop_cover')
self.hass.states.set(window_cover, STATE_UNKNOWN) await hass.async_add_job(acc.char_target_position.client_update_value, 25)
self.hass.block_till_done() await hass.async_block_till_done()
assert call_close_cover
assert call_close_cover[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_position.value == 0
assert acc.char_target_position.value == 0
assert acc.char_position_state.value == 2
self.assertEqual(acc.char_current_position.value, 0) await hass.async_add_job(acc.char_target_position.client_update_value, 90)
self.assertEqual(acc.char_target_position.value, 0) await hass.async_block_till_done()
self.assertEqual(acc.char_position_state.value, 2) assert call_open_cover
assert call_open_cover[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_current_position.value == 100
assert acc.char_target_position.value == 100
assert acc.char_position_state.value == 2
self.hass.states.set(window_cover, STATE_OPEN) await hass.async_add_job(acc.char_target_position.client_update_value, 55)
self.hass.block_till_done() await hass.async_block_till_done()
assert call_stop_cover
self.assertEqual(acc.char_current_position.value, 100) assert call_stop_cover[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(acc.char_target_position.value, 100) assert acc.char_current_position.value == 50
self.assertEqual(acc.char_position_state.value, 2) assert acc.char_target_position.value == 50
assert acc.char_position_state.value == 2
self.hass.states.set(window_cover, STATE_CLOSED)
self.hass.block_till_done()
self.assertEqual(acc.char_current_position.value, 0)
self.assertEqual(acc.char_target_position.value, 0)
self.assertEqual(acc.char_position_state.value, 2)
# Set from HomeKit
acc.char_target_position.client_update_value(25)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'close_cover')
self.assertEqual(acc.char_current_position.value, 0)
self.assertEqual(acc.char_target_position.value, 0)
self.assertEqual(acc.char_position_state.value, 2)
# Set from HomeKit
acc.char_target_position.client_update_value(90)
self.hass.block_till_done()
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'open_cover')
self.assertEqual(acc.char_current_position.value, 100)
self.assertEqual(acc.char_target_position.value, 100)
self.assertEqual(acc.char_position_state.value, 2)
# Set from HomeKit
acc.char_target_position.client_update_value(55)
self.hass.block_till_done()
self.assertEqual(
self.events[2].data[ATTR_SERVICE], 'open_cover')
self.assertEqual(acc.char_current_position.value, 100)
self.assertEqual(acc.char_target_position.value, 100)
self.assertEqual(acc.char_position_state.value, 2)
def test_window_open_close_stop(self):
"""Test if accessory and HA are updated accordingly."""
window_cover = 'cover.window'
self.hass.states.set(window_cover, STATE_UNKNOWN,
{ATTR_SUPPORTED_FEATURES: SUPPORT_STOP})
acc = self.window_basic_cls(self.hass, 'Cover', window_cover, 2,
config=None)
acc.run()
# Set from HomeKit
acc.char_target_position.client_update_value(25)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'close_cover')
self.assertEqual(acc.char_current_position.value, 0)
self.assertEqual(acc.char_target_position.value, 0)
self.assertEqual(acc.char_position_state.value, 2)
# Set from HomeKit
acc.char_target_position.client_update_value(90)
self.hass.block_till_done()
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'open_cover')
self.assertEqual(acc.char_current_position.value, 100)
self.assertEqual(acc.char_target_position.value, 100)
self.assertEqual(acc.char_position_state.value, 2)
# Set from HomeKit
acc.char_target_position.client_update_value(55)
self.hass.block_till_done()
self.assertEqual(
self.events[2].data[ATTR_SERVICE], 'stop_cover')
self.assertEqual(acc.char_current_position.value, 50)
self.assertEqual(acc.char_target_position.value, 50)
self.assertEqual(acc.char_position_state.value, 2)

View File

@ -1,188 +1,174 @@
"""Test different accessory types: Lights.""" """Test different accessory types: Lights."""
import unittest from collections import namedtuple
import pytest
from homeassistant.core import callback
from homeassistant.components.light import ( from homeassistant.components.light import (
DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_TEMP, DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_TEMP,
ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR) ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR)
from homeassistant.const import ( from homeassistant.const import (
ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES,
ATTR_SUPPORTED_FEATURES, EVENT_CALL_SERVICE, SERVICE_TURN_ON, STATE_ON, STATE_OFF, STATE_UNKNOWN)
SERVICE_TURN_OFF, STATE_ON, STATE_OFF, STATE_UNKNOWN)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
from tests.components.homekit.test_accessories import patch_debounce from tests.components.homekit.test_accessories import patch_debounce
class TestHomekitLights(unittest.TestCase): @pytest.fixture(scope='module')
"""Test class for all accessory types regarding lights.""" def cls(request):
"""Patch debounce decorator during import of type_lights."""
patcher = patch_debounce()
patcher.start()
_import = __import__('homeassistant.components.homekit.type_lights',
fromlist=['Light'])
request.addfinalizer(patcher.stop)
patcher_tuple = namedtuple('Cls', ['light'])
return patcher_tuple(light=_import.Light)
@classmethod
def setUpClass(cls):
"""Setup Light class import and debounce patcher."""
cls.patcher = patch_debounce()
cls.patcher.start()
_import = __import__('homeassistant.components.homekit.type_lights',
fromlist=['Light'])
cls.light_cls = _import.Light
@classmethod async def test_light_basic(hass, cls):
def tearDownClass(cls): """Test light with char state."""
"""Stop debounce patcher.""" entity_id = 'light.demo'
cls.patcher.stop()
def setUp(self): hass.states.async_set(entity_id, STATE_ON,
"""Setup things to be run when tests are started.""" {ATTR_SUPPORTED_FEATURES: 0})
self.hass = get_test_home_assistant() await hass.async_block_till_done()
self.events = [] acc = cls.light(hass, 'Light', entity_id, 2, config=None)
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 5 # Lightbulb
"""Track called event.""" assert acc.char_on.value == 0
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) await hass.async_add_job(acc.run)
await hass.async_block_till_done()
assert acc.char_on.value == 1
def tearDown(self): hass.states.async_set(entity_id, STATE_OFF,
"""Stop down everything that was started.""" {ATTR_SUPPORTED_FEATURES: 0})
self.hass.stop() await hass.async_block_till_done()
assert acc.char_on.value == 0
def test_light_basic(self): hass.states.async_set(entity_id, STATE_UNKNOWN)
"""Test light with char state.""" await hass.async_block_till_done()
entity_id = 'light.demo' assert acc.char_on.value == 0
self.hass.states.set(entity_id, STATE_ON, hass.states.async_remove(entity_id)
{ATTR_SUPPORTED_FEATURES: 0}) await hass.async_block_till_done()
self.hass.block_till_done() assert acc.char_on.value == 0
acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None)
self.assertEqual(acc.aid, 2)
self.assertEqual(acc.category, 5) # Lightbulb
self.assertEqual(acc.char_on.value, 0)
acc.run() # Set from HomeKit
self.hass.block_till_done() call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
self.assertEqual(acc.char_on.value, 1) call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off')
self.hass.states.set(entity_id, STATE_OFF, await hass.async_add_job(acc.char_on.client_update_value, 1)
{ATTR_SUPPORTED_FEATURES: 0}) await hass.async_block_till_done()
self.hass.block_till_done() assert call_turn_on
self.assertEqual(acc.char_on.value, 0) assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
self.hass.states.set(entity_id, STATE_UNKNOWN) hass.states.async_set(entity_id, STATE_ON)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_on.value, 0)
# Set from HomeKit await hass.async_add_job(acc.char_on.client_update_value, 0)
acc.char_on.client_update_value(1) await hass.async_block_till_done()
self.hass.block_till_done() assert call_turn_off
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN) assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.hass.states.set(entity_id, STATE_ON)
self.hass.block_till_done()
acc.char_on.client_update_value(0) async def test_light_brightness(hass, cls):
self.hass.block_till_done() """Test light with brightness."""
self.assertEqual(self.events[1].data[ATTR_DOMAIN], DOMAIN) entity_id = 'light.demo'
self.assertEqual(self.events[1].data[ATTR_SERVICE], SERVICE_TURN_OFF)
self.hass.states.set(entity_id, STATE_OFF) hass.states.async_set(entity_id, STATE_ON, {
self.hass.block_till_done() ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255})
await hass.async_block_till_done()
acc = cls.light(hass, 'Light', entity_id, 2, config=None)
# Remove entity assert acc.char_brightness.value == 0
self.hass.states.remove(entity_id)
self.hass.block_till_done()
def test_light_brightness(self): await hass.async_add_job(acc.run)
"""Test light with brightness.""" await hass.async_block_till_done()
entity_id = 'light.demo' assert acc.char_brightness.value == 100
self.hass.states.set(entity_id, STATE_ON, { hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102})
ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) await hass.async_block_till_done()
self.hass.block_till_done() assert acc.char_brightness.value == 40
acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None)
self.assertEqual(acc.char_brightness.value, 0)
acc.run() # Set from HomeKit
self.hass.block_till_done() call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
self.assertEqual(acc.char_brightness.value, 100) call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off')
self.hass.states.set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102}) await hass.async_add_job(acc.char_brightness.client_update_value, 20)
self.hass.block_till_done() await hass.async_add_job(acc.char_on.client_update_value, 1)
self.assertEqual(acc.char_brightness.value, 40) await hass.async_block_till_done()
assert call_turn_on[0]
assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
assert call_turn_on[0].data[ATTR_BRIGHTNESS_PCT] == 20
# Set from HomeKit await hass.async_add_job(acc.char_on.client_update_value, 1)
acc.char_brightness.client_update_value(20) await hass.async_add_job(acc.char_brightness.client_update_value, 40)
acc.char_on.client_update_value(1) await hass.async_block_till_done()
self.hass.block_till_done() assert call_turn_on[1]
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN) assert call_turn_on[1].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON) assert call_turn_on[1].data[ATTR_BRIGHTNESS_PCT] == 40
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA], {
ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS_PCT: 20})
acc.char_on.client_update_value(1) await hass.async_add_job(acc.char_on.client_update_value, 1)
acc.char_brightness.client_update_value(40) await hass.async_add_job(acc.char_brightness.client_update_value, 0)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(self.events[1].data[ATTR_DOMAIN], DOMAIN) assert call_turn_off
self.assertEqual(self.events[1].data[ATTR_SERVICE], SERVICE_TURN_ON) assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(
self.events[1].data[ATTR_SERVICE_DATA], {
ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS_PCT: 40})
acc.char_on.client_update_value(1)
acc.char_brightness.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(self.events[2].data[ATTR_DOMAIN], DOMAIN)
self.assertEqual(self.events[2].data[ATTR_SERVICE], SERVICE_TURN_OFF)
def test_light_color_temperature(self): async def test_light_color_temperature(hass, cls):
"""Test light with color temperature.""" """Test light with color temperature."""
entity_id = 'light.demo' entity_id = 'light.demo'
self.hass.states.set(entity_id, STATE_ON, { hass.states.async_set(entity_id, STATE_ON, {
ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP, ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP,
ATTR_COLOR_TEMP: 190}) ATTR_COLOR_TEMP: 190})
self.hass.block_till_done() await hass.async_block_till_done()
acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) acc = cls.light(hass, 'Light', entity_id, 2, config=None)
self.assertEqual(acc.char_color_temperature.value, 153)
acc.run() assert acc.char_color_temperature.value == 153
self.hass.block_till_done()
self.assertEqual(acc.char_color_temperature.value, 190)
# Set from HomeKit await hass.async_add_job(acc.run)
acc.char_color_temperature.client_update_value(250) await hass.async_block_till_done()
self.hass.block_till_done() assert acc.char_color_temperature.value == 190
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN)
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA], {
ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 250})
def test_light_rgb_color(self): # Set from HomeKit
"""Test light with rgb_color.""" call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
entity_id = 'light.demo'
self.hass.states.set(entity_id, STATE_ON, { await hass.async_add_job(
ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, acc.char_color_temperature.client_update_value, 250)
ATTR_HS_COLOR: (260, 90)}) await hass.async_block_till_done()
self.hass.block_till_done() assert call_turn_on
acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(acc.char_hue.value, 0) assert call_turn_on[0].data[ATTR_COLOR_TEMP] == 250
self.assertEqual(acc.char_saturation.value, 75)
acc.run()
self.hass.block_till_done()
self.assertEqual(acc.char_hue.value, 260)
self.assertEqual(acc.char_saturation.value, 90)
# Set from HomeKit async def test_light_rgb_color(hass, cls):
acc.char_hue.client_update_value(145) """Test light with rgb_color."""
acc.char_saturation.client_update_value(75) entity_id = 'light.demo'
self.hass.block_till_done()
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN) hass.states.async_set(entity_id, STATE_ON, {
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON) ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR,
self.assertEqual( ATTR_HS_COLOR: (260, 90)})
self.events[0].data[ATTR_SERVICE_DATA], { await hass.async_block_till_done()
ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (145, 75)}) acc = cls.light(hass, 'Light', entity_id, 2, config=None)
assert acc.char_hue.value == 0
assert acc.char_saturation.value == 75
await hass.async_add_job(acc.run)
await hass.async_block_till_done()
assert acc.char_hue.value == 260
assert acc.char_saturation.value == 90
# Set from HomeKit
call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
await hass.async_add_job(acc.char_hue.client_update_value, 145)
await hass.async_add_job(acc.char_saturation.client_update_value, 75)
await hass.async_block_till_done()
assert call_turn_on
assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
assert call_turn_on[0].data[ATTR_HS_COLOR] == (145, 75)

View File

@ -1,77 +1,57 @@
"""Test different accessory types: Locks.""" """Test different accessory types: Locks."""
import unittest
from homeassistant.core import callback
from homeassistant.components.homekit.type_locks import Lock from homeassistant.components.homekit.type_locks import Lock
from homeassistant.components.lock import DOMAIN
from homeassistant.const import ( from homeassistant.const import (
STATE_UNKNOWN, STATE_UNLOCKED, STATE_LOCKED, ATTR_ENTITY_ID, STATE_UNKNOWN, STATE_UNLOCKED, STATE_LOCKED)
ATTR_SERVICE, EVENT_CALL_SERVICE)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
class TestHomekitSensors(unittest.TestCase): async def test_lock_unlock(hass):
"""Test class for all accessory types regarding covers.""" """Test if accessory and HA are updated accordingly."""
entity_id = 'lock.kitchen_door'
def setUp(self): acc = Lock(hass, 'Lock', entity_id, 2, config=None)
"""Setup things to be run when tests are started.""" await hass.async_add_job(acc.run)
self.hass = get_test_home_assistant()
self.events = []
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 6 # DoorLock
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 1
def tearDown(self): hass.states.async_set(entity_id, STATE_LOCKED)
"""Stop down everything that was started.""" await hass.async_block_till_done()
self.hass.stop() assert acc.char_current_state.value == 1
assert acc.char_target_state.value == 1
def test_lock_unlock(self): hass.states.async_set(entity_id, STATE_UNLOCKED)
"""Test if accessory and HA are updated accordingly.""" await hass.async_block_till_done()
kitchen_lock = 'lock.kitchen_door' assert acc.char_current_state.value == 0
assert acc.char_target_state.value == 0
acc = Lock(self.hass, 'Lock', kitchen_lock, 2, config=None) hass.states.async_set(entity_id, STATE_UNKNOWN)
acc.run() await hass.async_block_till_done()
assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_remove(entity_id)
self.assertEqual(acc.category, 6) # DoorLock await hass.async_block_till_done()
assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 0
self.assertEqual(acc.char_current_state.value, 3) # Set from HomeKit
self.assertEqual(acc.char_target_state.value, 1) call_lock = async_mock_service(hass, DOMAIN, 'lock')
call_unlock = async_mock_service(hass, DOMAIN, 'unlock')
self.hass.states.set(kitchen_lock, STATE_LOCKED) await hass.async_add_job(acc.char_target_state.client_update_value, 1)
self.hass.block_till_done() await hass.async_block_till_done()
assert call_lock
assert call_lock[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_target_state.value == 1
self.assertEqual(acc.char_current_state.value, 1) await hass.async_add_job(acc.char_target_state.client_update_value, 0)
self.assertEqual(acc.char_target_state.value, 1) await hass.async_block_till_done()
assert call_unlock
self.hass.states.set(kitchen_lock, STATE_UNLOCKED) assert call_unlock[0].data[ATTR_ENTITY_ID] == entity_id
self.hass.block_till_done() assert acc.char_target_state.value == 0
self.assertEqual(acc.char_current_state.value, 0)
self.assertEqual(acc.char_target_state.value, 0)
self.hass.states.set(kitchen_lock, STATE_UNKNOWN)
self.hass.block_till_done()
self.assertEqual(acc.char_current_state.value, 3)
self.assertEqual(acc.char_target_state.value, 0)
# Set from HomeKit
acc.char_target_state.client_update_value(1)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'lock')
self.assertEqual(acc.char_target_state.value, 1)
acc.char_target_state.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'unlock')
self.assertEqual(acc.char_target_state.value, 0)
self.hass.states.remove(kitchen_lock)
self.hass.block_till_done()

View File

@ -1,134 +1,110 @@
"""Test different accessory types: Security Systems.""" """Test different accessory types: Security Systems."""
import unittest import pytest
from homeassistant.core import callback from homeassistant.components.alarm_control_panel import DOMAIN
from homeassistant.components.homekit.type_security_systems import ( from homeassistant.components.homekit.type_security_systems import (
SecuritySystem) SecuritySystem)
from homeassistant.const import ( from homeassistant.const import (
ATTR_CODE, ATTR_SERVICE, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE, ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
STATE_UNKNOWN)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
class TestHomekitSecuritySystems(unittest.TestCase): async def test_switch_set_state(hass):
"""Test class for all accessory types regarding security systems.""" """Test if accessory and HA are updated accordingly."""
code = '1234'
config = {ATTR_CODE: code}
entity_id = 'alarm_control_panel.test'
def setUp(self): acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config=config)
"""Setup things to be run when tests are started.""" await hass.async_add_job(acc.run)
self.hass = get_test_home_assistant()
self.events = []
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 11 # AlarmSystem
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert acc.char_current_state.value == 3
assert acc.char_target_state.value == 3
def tearDown(self): hass.states.async_set(entity_id, STATE_ALARM_ARMED_AWAY)
"""Stop down everything that was started.""" await hass.async_block_till_done()
self.hass.stop() assert acc.char_target_state.value == 1
assert acc.char_current_state.value == 1
def test_switch_set_state(self): hass.states.async_set(entity_id, STATE_ALARM_ARMED_HOME)
"""Test if accessory and HA are updated accordingly.""" await hass.async_block_till_done()
acp = 'alarm_control_panel.test' assert acc.char_target_state.value == 0
assert acc.char_current_state.value == 0
acc = SecuritySystem(self.hass, 'SecuritySystem', acp, hass.states.async_set(entity_id, STATE_ALARM_ARMED_NIGHT)
2, config={ATTR_CODE: '1234'}) await hass.async_block_till_done()
acc.run() assert acc.char_target_state.value == 2
assert acc.char_current_state.value == 2
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, STATE_ALARM_DISARMED)
self.assertEqual(acc.category, 11) # AlarmSystem await hass.async_block_till_done()
assert acc.char_target_state.value == 3
assert acc.char_current_state.value == 3
self.assertEqual(acc.char_current_state.value, 3) hass.states.async_set(entity_id, STATE_ALARM_TRIGGERED)
self.assertEqual(acc.char_target_state.value, 3) await hass.async_block_till_done()
assert acc.char_target_state.value == 3
assert acc.char_current_state.value == 4
self.hass.states.set(acp, STATE_ALARM_ARMED_AWAY) hass.states.async_set(entity_id, STATE_UNKNOWN)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_target_state.value, 1) assert acc.char_target_state.value == 3
self.assertEqual(acc.char_current_state.value, 1) assert acc.char_current_state.value == 4
self.hass.states.set(acp, STATE_ALARM_ARMED_HOME) # Set from HomeKit
self.hass.block_till_done() call_arm_home = async_mock_service(hass, DOMAIN, 'alarm_arm_home')
self.assertEqual(acc.char_target_state.value, 0) call_arm_away = async_mock_service(hass, DOMAIN, 'alarm_arm_away')
self.assertEqual(acc.char_current_state.value, 0) call_arm_night = async_mock_service(hass, DOMAIN, 'alarm_arm_night')
call_disarm = async_mock_service(hass, DOMAIN, 'alarm_disarm')
self.hass.states.set(acp, STATE_ALARM_ARMED_NIGHT) await hass.async_add_job(acc.char_target_state.client_update_value, 0)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_target_state.value, 2) assert call_arm_home
self.assertEqual(acc.char_current_state.value, 2) assert call_arm_home[0].data[ATTR_ENTITY_ID] == entity_id
assert call_arm_home[0].data[ATTR_CODE] == code
assert acc.char_target_state.value == 0
self.hass.states.set(acp, STATE_ALARM_DISARMED) await hass.async_add_job(acc.char_target_state.client_update_value, 1)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_target_state.value, 3) assert call_arm_away
self.assertEqual(acc.char_current_state.value, 3) assert call_arm_away[0].data[ATTR_ENTITY_ID] == entity_id
assert call_arm_away[0].data[ATTR_CODE] == code
assert acc.char_target_state.value == 1
self.hass.states.set(acp, STATE_ALARM_TRIGGERED) await hass.async_add_job(acc.char_target_state.client_update_value, 2)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_target_state.value, 3) assert call_arm_night
self.assertEqual(acc.char_current_state.value, 4) assert call_arm_night[0].data[ATTR_ENTITY_ID] == entity_id
assert call_arm_night[0].data[ATTR_CODE] == code
assert acc.char_target_state.value == 2
self.hass.states.set(acp, STATE_UNKNOWN) await hass.async_add_job(acc.char_target_state.client_update_value, 3)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_target_state.value, 3) assert call_disarm
self.assertEqual(acc.char_current_state.value, 4) assert call_disarm[0].data[ATTR_ENTITY_ID] == entity_id
assert call_disarm[0].data[ATTR_CODE] == code
assert acc.char_target_state.value == 3
# Set from HomeKit
acc.char_target_state.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'alarm_arm_home')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_CODE], '1234')
self.assertEqual(acc.char_target_state.value, 0)
acc.char_target_state.client_update_value(1) @pytest.mark.parametrize('config', [{}, {ATTR_CODE: None}])
self.hass.block_till_done() async def test_no_alarm_code(hass, config):
self.assertEqual( """Test accessory if security_system doesn't require a alarm_code."""
self.events[1].data[ATTR_SERVICE], 'alarm_arm_away') entity_id = 'alarm_control_panel.test'
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_CODE], '1234')
self.assertEqual(acc.char_target_state.value, 1)
acc.char_target_state.client_update_value(2) acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config=config)
self.hass.block_till_done()
self.assertEqual(
self.events[2].data[ATTR_SERVICE], 'alarm_arm_night')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_CODE], '1234')
self.assertEqual(acc.char_target_state.value, 2)
acc.char_target_state.client_update_value(3) # Set from HomeKit
self.hass.block_till_done() call_arm_home = async_mock_service(hass, DOMAIN, 'alarm_arm_home')
self.assertEqual(
self.events[3].data[ATTR_SERVICE], 'alarm_disarm')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_CODE], '1234')
self.assertEqual(acc.char_target_state.value, 3)
def test_no_alarm_code(self): await hass.async_add_job(acc.char_target_state.client_update_value, 0)
"""Test accessory if security_system doesn't require a alarm_code.""" await hass.async_block_till_done()
acp = 'alarm_control_panel.test' assert call_arm_home
assert call_arm_home[0].data[ATTR_ENTITY_ID] == entity_id
acc = SecuritySystem(self.hass, 'SecuritySystem', acp, assert ATTR_CODE not in call_arm_home[0].data
2, config={ATTR_CODE: None}) assert acc.char_target_state.value == 0
# Set from HomeKit
acc.char_target_state.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'alarm_arm_home')
self.assertNotIn(ATTR_CODE, self.events[0].data[ATTR_SERVICE_DATA])
self.assertEqual(acc.char_target_state.value, 0)
acc = SecuritySystem(self.hass, 'SecuritySystem', acp,
2, config={})
# Set from HomeKit
acc.char_target_state.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'alarm_arm_home')
self.assertNotIn(ATTR_CODE, self.events[0].data[ATTR_SERVICE_DATA])
self.assertEqual(acc.char_target_state.value, 0)

View File

@ -1,6 +1,4 @@
"""Test different accessory types: Sensors.""" """Test different accessory types: Sensors."""
import unittest
from homeassistant.components.homekit.const import PROP_CELSIUS from homeassistant.components.homekit.const import PROP_CELSIUS
from homeassistant.components.homekit.type_sensors import ( from homeassistant.components.homekit.type_sensors import (
TemperatureSensor, HumiditySensor, AirQualitySensor, CarbonDioxideSensor, TemperatureSensor, HumiditySensor, AirQualitySensor, CarbonDioxideSensor,
@ -9,201 +7,191 @@ from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, ATTR_DEVICE_CLASS, STATE_UNKNOWN, STATE_ON, ATTR_UNIT_OF_MEASUREMENT, ATTR_DEVICE_CLASS, STATE_UNKNOWN, STATE_ON,
STATE_OFF, STATE_HOME, STATE_NOT_HOME, TEMP_CELSIUS, TEMP_FAHRENHEIT) STATE_OFF, STATE_HOME, STATE_NOT_HOME, TEMP_CELSIUS, TEMP_FAHRENHEIT)
from tests.common import get_test_home_assistant
async def test_temperature(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.temperature'
acc = TemperatureSensor(hass, 'Temperature', entity_id, 2, config=None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
assert acc.category == 10 # Sensor
assert acc.char_temp.value == 0.0
for key, value in PROP_CELSIUS.items():
assert acc.char_temp.properties[key] == value
hass.states.async_set(entity_id, STATE_UNKNOWN,
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_temp.value == 0.0
hass.states.async_set(entity_id, '20',
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_temp.value == 20
hass.states.async_set(entity_id, '75.2',
{ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT})
await hass.async_block_till_done()
assert acc.char_temp.value == 24
class TestHomekitSensors(unittest.TestCase): async def test_humidity(hass):
"""Test class for all accessory types regarding sensors.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.humidity'
def setUp(self): acc = HumiditySensor(hass, 'Humidity', entity_id, 2, config=None)
"""Setup things to be run when tests are started.""" await hass.async_add_job(acc.run)
self.hass = get_test_home_assistant()
def tearDown(self): assert acc.aid == 2
"""Stop down everything that was started.""" assert acc.category == 10 # Sensor
self.hass.stop()
def test_temperature(self): assert acc.char_humidity.value == 0
"""Test if accessory is updated after state change."""
entity_id = 'sensor.temperature'
acc = TemperatureSensor(self.hass, 'Temperature', entity_id, hass.states.async_set(entity_id, STATE_UNKNOWN)
2, config=None) await hass.async_block_till_done()
acc.run() assert acc.char_humidity.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, '20')
self.assertEqual(acc.category, 10) # Sensor await hass.async_block_till_done()
assert acc.char_humidity.value == 20
self.assertEqual(acc.char_temp.value, 0.0)
for key, value in PROP_CELSIUS.items():
self.assertEqual(acc.char_temp.properties[key], value)
self.hass.states.set(entity_id, STATE_UNKNOWN, async def test_air_quality(hass):
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) """Test if accessory is updated after state change."""
self.hass.block_till_done() entity_id = 'sensor.air_quality'
self.assertEqual(acc.char_temp.value, 0.0)
self.hass.states.set(entity_id, '20', acc = AirQualitySensor(hass, 'Air Quality', entity_id, 2, config=None)
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) await hass.async_add_job(acc.run)
self.hass.block_till_done()
self.assertEqual(acc.char_temp.value, 20)
self.hass.states.set(entity_id, '75.2', assert acc.aid == 2
{ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT}) assert acc.category == 10 # Sensor
self.hass.block_till_done()
self.assertEqual(acc.char_temp.value, 24)
def test_humidity(self): assert acc.char_density.value == 0
"""Test if accessory is updated after state change.""" assert acc.char_quality.value == 0
entity_id = 'sensor.humidity'
acc = HumiditySensor(self.hass, 'Humidity', entity_id, 2, config=None) hass.states.async_set(entity_id, STATE_UNKNOWN)
acc.run() await hass.async_block_till_done()
assert acc.char_density.value == 0
assert acc.char_quality.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, '34')
self.assertEqual(acc.category, 10) # Sensor await hass.async_block_till_done()
assert acc.char_density.value == 34
assert acc.char_quality.value == 1
self.assertEqual(acc.char_humidity.value, 0) hass.states.async_set(entity_id, '200')
await hass.async_block_till_done()
assert acc.char_density.value == 200
assert acc.char_quality.value == 5
self.hass.states.set(entity_id, STATE_UNKNOWN)
self.hass.block_till_done()
self.assertEqual(acc.char_humidity.value, 0)
self.hass.states.set(entity_id, '20') async def test_co2(hass):
self.hass.block_till_done() """Test if accessory is updated after state change."""
self.assertEqual(acc.char_humidity.value, 20) entity_id = 'sensor.co2'
def test_air_quality(self): acc = CarbonDioxideSensor(hass, 'CO2', entity_id, 2, config=None)
"""Test if accessory is updated after state change.""" await hass.async_add_job(acc.run)
entity_id = 'sensor.air_quality'
acc = AirQualitySensor(self.hass, 'Air Quality', entity_id, assert acc.aid == 2
2, config=None) assert acc.category == 10 # Sensor
acc.run()
self.assertEqual(acc.aid, 2) assert acc.char_co2.value == 0
self.assertEqual(acc.category, 10) # Sensor assert acc.char_peak.value == 0
assert acc.char_detected.value == 0
self.assertEqual(acc.char_density.value, 0) hass.states.async_set(entity_id, STATE_UNKNOWN)
self.assertEqual(acc.char_quality.value, 0) await hass.async_block_till_done()
assert acc.char_co2.value == 0
assert acc.char_peak.value == 0
assert acc.char_detected.value == 0
self.hass.states.set(entity_id, STATE_UNKNOWN) hass.states.async_set(entity_id, '1100')
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_density.value, 0) assert acc.char_co2.value == 1100
self.assertEqual(acc.char_quality.value, 0) assert acc.char_peak.value == 1100
assert acc.char_detected.value == 1
self.hass.states.set(entity_id, '34') hass.states.async_set(entity_id, '800')
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_density.value, 34) assert acc.char_co2.value == 800
self.assertEqual(acc.char_quality.value, 1) assert acc.char_peak.value == 1100
assert acc.char_detected.value == 0
self.hass.states.set(entity_id, '200')
self.hass.block_till_done()
self.assertEqual(acc.char_density.value, 200)
self.assertEqual(acc.char_quality.value, 5)
def test_co2(self): async def test_light(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.co2' entity_id = 'sensor.light'
acc = CarbonDioxideSensor(self.hass, 'CO2', entity_id, 2, config=None) acc = LightSensor(hass, 'Light', entity_id, 2, config=None)
acc.run() await hass.async_add_job(acc.run)
self.assertEqual(acc.aid, 2) assert acc.aid == 2
self.assertEqual(acc.category, 10) # Sensor assert acc.category == 10 # Sensor
self.assertEqual(acc.char_co2.value, 0) assert acc.char_light.value == 0.0001
self.assertEqual(acc.char_peak.value, 0)
self.assertEqual(acc.char_detected.value, 0)
self.hass.states.set(entity_id, STATE_UNKNOWN) hass.states.async_set(entity_id, STATE_UNKNOWN)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_co2.value, 0) assert acc.char_light.value == 0.0001
self.assertEqual(acc.char_peak.value, 0)
self.assertEqual(acc.char_detected.value, 0)
self.hass.states.set(entity_id, '1100') hass.states.async_set(entity_id, '300')
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_co2.value, 1100) assert acc.char_light.value == 300
self.assertEqual(acc.char_peak.value, 1100)
self.assertEqual(acc.char_detected.value, 1)
self.hass.states.set(entity_id, '800')
self.hass.block_till_done()
self.assertEqual(acc.char_co2.value, 800)
self.assertEqual(acc.char_peak.value, 1100)
self.assertEqual(acc.char_detected.value, 0)
def test_light(self): async def test_binary(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.light' entity_id = 'binary_sensor.opening'
acc = LightSensor(self.hass, 'Light', entity_id, 2, config=None) hass.states.async_set(entity_id, STATE_UNKNOWN,
acc.run() {ATTR_DEVICE_CLASS: 'opening'})
await hass.async_block_till_done()
self.assertEqual(acc.aid, 2) acc = BinarySensor(hass, 'Window Opening', entity_id, 2, config=None)
self.assertEqual(acc.category, 10) # Sensor await hass.async_add_job(acc.run)
self.assertEqual(acc.char_light.value, 0.0001) assert acc.aid == 2
assert acc.category == 10 # Sensor
self.hass.states.set(entity_id, STATE_UNKNOWN) assert acc.char_detected.value == 0
self.hass.block_till_done()
self.assertEqual(acc.char_light.value, 0.0001)
self.hass.states.set(entity_id, '300') hass.states.async_set(entity_id, STATE_ON,
self.hass.block_till_done() {ATTR_DEVICE_CLASS: 'opening'})
self.assertEqual(acc.char_light.value, 300) await hass.async_block_till_done()
assert acc.char_detected.value == 1
def test_binary(self): hass.states.async_set(entity_id, STATE_OFF,
"""Test if accessory is updated after state change.""" {ATTR_DEVICE_CLASS: 'opening'})
entity_id = 'binary_sensor.opening' await hass.async_block_till_done()
assert acc.char_detected.value == 0
self.hass.states.set(entity_id, STATE_UNKNOWN, hass.states.async_set(entity_id, STATE_HOME,
{ATTR_DEVICE_CLASS: "opening"}) {ATTR_DEVICE_CLASS: 'opening'})
self.hass.block_till_done() await hass.async_block_till_done()
assert acc.char_detected.value == 1
acc = BinarySensor(self.hass, 'Window Opening', entity_id, hass.states.async_set(entity_id, STATE_NOT_HOME,
2, config=None) {ATTR_DEVICE_CLASS: 'opening'})
acc.run() await hass.async_block_till_done()
assert acc.char_detected.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_remove(entity_id)
self.assertEqual(acc.category, 10) # Sensor await hass.async_block_till_done()
assert acc.char_detected.value == 0
self.assertEqual(acc.char_detected.value, 0)
self.hass.states.set(entity_id, STATE_ON, async def test_binary_device_classes(hass):
{ATTR_DEVICE_CLASS: "opening"}) """Test if services and characteristics are assigned correctly."""
self.hass.block_till_done() entity_id = 'binary_sensor.demo'
self.assertEqual(acc.char_detected.value, 1)
self.hass.states.set(entity_id, STATE_OFF, for device_class, (service, char) in BINARY_SENSOR_SERVICE_MAP.items():
{ATTR_DEVICE_CLASS: "opening"}) hass.states.async_set(entity_id, STATE_OFF,
self.hass.block_till_done() {ATTR_DEVICE_CLASS: device_class})
self.assertEqual(acc.char_detected.value, 0) await hass.async_block_till_done()
self.hass.states.set(entity_id, STATE_HOME, acc = BinarySensor(hass, 'Binary Sensor', entity_id, 2, config=None)
{ATTR_DEVICE_CLASS: "opening"}) assert acc.get_service(service).display_name == service
self.hass.block_till_done() assert acc.char_detected.display_name == char
self.assertEqual(acc.char_detected.value, 1)
self.hass.states.set(entity_id, STATE_NOT_HOME,
{ATTR_DEVICE_CLASS: "opening"})
self.hass.block_till_done()
self.assertEqual(acc.char_detected.value, 0)
self.hass.states.remove(entity_id)
self.hass.block_till_done()
def test_binary_device_classes(self):
"""Test if services and characteristics are assigned correctly."""
entity_id = 'binary_sensor.demo'
for device_class, (service, char) in BINARY_SENSOR_SERVICE_MAP.items():
self.hass.states.set(entity_id, STATE_OFF,
{ATTR_DEVICE_CLASS: device_class})
self.hass.block_till_done()
acc = BinarySensor(self.hass, 'Binary Sensor', entity_id,
2, config=None)
self.assertEqual(acc.get_service(service).display_name, service)
self.assertEqual(acc.char_detected.display_name, char)

View File

@ -1,104 +1,45 @@
"""Test different accessory types: Switches.""" """Test different accessory types: Switches."""
import unittest import pytest
from homeassistant.core import callback, split_entity_id from homeassistant.core import split_entity_id
from homeassistant.components.homekit.type_switches import Switch from homeassistant.components.homekit.type_switches import Switch
from homeassistant.const import ( from homeassistant.const import ATTR_ENTITY_ID, STATE_ON, STATE_OFF
ATTR_DOMAIN, ATTR_SERVICE, EVENT_CALL_SERVICE,
SERVICE_TURN_ON, SERVICE_TURN_OFF, STATE_ON, STATE_OFF)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
class TestHomekitSwitches(unittest.TestCase): @pytest.mark.parametrize('entity_id', [
"""Test class for all accessory types regarding switches.""" 'switch.test', 'remote.test', 'input_boolean.test'])
async def test_switch_set_state(hass, entity_id):
"""Test if accessory and HA are updated accordingly."""
domain = split_entity_id(entity_id)[0]
def setUp(self): acc = Switch(hass, 'Switch', entity_id, 2, config=None)
"""Setup things to be run when tests are started.""" await hass.async_add_job(acc.run)
self.hass = get_test_home_assistant()
self.events = []
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 8 # Switch
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert acc.char_on.value is False
def tearDown(self): hass.states.async_set(entity_id, STATE_ON)
"""Stop down everything that was started.""" await hass.async_block_till_done()
self.hass.stop() assert acc.char_on.value is True
def test_switch_set_state(self): hass.states.async_set(entity_id, STATE_OFF)
"""Test if accessory and HA are updated accordingly.""" await hass.async_block_till_done()
entity_id = 'switch.test' assert acc.char_on.value is False
domain = split_entity_id(entity_id)[0]
acc = Switch(self.hass, 'Switch', entity_id, 2, config=None) # Set from HomeKit
acc.run() call_turn_on = async_mock_service(hass, domain, 'turn_on')
call_turn_off = async_mock_service(hass, domain, 'turn_off')
self.assertEqual(acc.aid, 2) await hass.async_add_job(acc.char_on.client_update_value, True)
self.assertEqual(acc.category, 8) # Switch await hass.async_block_till_done()
assert call_turn_on
assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(acc.char_on.value, False) await hass.async_add_job(acc.char_on.client_update_value, False)
await hass.async_block_till_done()
self.hass.states.set(entity_id, STATE_ON) assert call_turn_off
self.hass.block_till_done() assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual(acc.char_on.value, True)
self.hass.states.set(entity_id, STATE_OFF)
self.hass.block_till_done()
self.assertEqual(acc.char_on.value, False)
# Set from HomeKit
acc.char_on.client_update_value(True)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_DOMAIN], domain)
self.assertEqual(
self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
acc.char_on.client_update_value(False)
self.hass.block_till_done()
self.assertEqual(
self.events[1].data[ATTR_DOMAIN], domain)
self.assertEqual(
self.events[1].data[ATTR_SERVICE], SERVICE_TURN_OFF)
def test_remote_set_state(self):
"""Test service call for remote as domain."""
entity_id = 'remote.test'
domain = split_entity_id(entity_id)[0]
acc = Switch(self.hass, 'Switch', entity_id, 2, config=None)
acc.run()
self.assertEqual(acc.char_on.value, False)
# Set from HomeKit
acc.char_on.client_update_value(True)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_DOMAIN], domain)
self.assertEqual(
self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.assertEqual(acc.char_on.value, True)
def test_input_boolean_set_state(self):
"""Test service call for remote as domain."""
entity_id = 'input_boolean.test'
domain = split_entity_id(entity_id)[0]
acc = Switch(self.hass, 'Switch', entity_id, 2, config=None)
acc.run()
self.assertEqual(acc.char_on.value, False)
# Set from HomeKit
acc.char_on.client_update_value(True)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_DOMAIN], domain)
self.assertEqual(
self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.assertEqual(acc.char_on.value, True)

View File

@ -1,364 +1,347 @@
"""Test different accessory types: Thermostats.""" """Test different accessory types: Thermostats."""
import unittest from collections import namedtuple
import pytest
from homeassistant.core import callback
from homeassistant.components.climate import ( from homeassistant.components.climate import (
ATTR_CURRENT_TEMPERATURE, ATTR_TEMPERATURE, DOMAIN, ATTR_CURRENT_TEMPERATURE, ATTR_TEMPERATURE,
ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE, ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE,
ATTR_OPERATION_LIST, STATE_COOL, STATE_HEAT, STATE_AUTO) ATTR_OPERATION_LIST, STATE_COOL, STATE_HEAT, STATE_AUTO)
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_SUPPORTED_FEATURES, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
ATTR_UNIT_OF_MEASUREMENT, EVENT_CALL_SERVICE,
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
from tests.components.homekit.test_accessories import patch_debounce from tests.components.homekit.test_accessories import patch_debounce
class TestHomekitThermostats(unittest.TestCase): @pytest.fixture(scope='module')
"""Test class for all accessory types regarding thermostats.""" def cls(request):
"""Patch debounce decorator during import of type_thermostats."""
patcher = patch_debounce()
patcher.start()
_import = __import__('homeassistant.components.homekit.type_thermostats',
fromlist=['Thermostat'])
request.addfinalizer(patcher.stop)
patcher_tuple = namedtuple('Cls', ['thermostat'])
return patcher_tuple(thermostat=_import.Thermostat)
@classmethod
def setUpClass(cls):
"""Setup Thermostat class import and debounce patcher."""
cls.patcher = patch_debounce()
cls.patcher.start()
_import = __import__(
'homeassistant.components.homekit.type_thermostats',
fromlist=['Thermostat'])
cls.thermostat_cls = _import.Thermostat
@classmethod async def test_default_thermostat(hass, cls):
def tearDownClass(cls): """Test if accessory and HA are updated accordingly."""
"""Stop debounce patcher.""" entity_id = 'climate.test'
cls.patcher.stop()
def setUp(self): hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0})
"""Setup things to be run when tests are started.""" await hass.async_block_till_done()
self.hass = get_test_home_assistant() acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
self.events = [] await hass.async_add_job(acc.run)
@callback assert acc.aid == 2
def record_event(event): assert acc.category == 9 # Thermostat
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 0
assert acc.char_current_temp.value == 21.0
assert acc.char_target_temp.value == 21.0
assert acc.char_display_units.value == 0
assert acc.char_cooling_thresh_temp is None
assert acc.char_heating_thresh_temp is None
def tearDown(self): hass.states.async_set(entity_id, STATE_HEAT,
"""Stop down everything that was started.""" {ATTR_OPERATION_MODE: STATE_HEAT,
self.hass.stop() ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 18.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 1
assert acc.char_target_heat_cool.value == 1
assert acc.char_current_temp.value == 18.0
assert acc.char_display_units.value == 0
def test_default_thermostat(self): hass.states.async_set(entity_id, STATE_HEAT,
"""Test if accessory and HA are updated accordingly.""" {ATTR_OPERATION_MODE: STATE_HEAT,
climate = 'climate.test' ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 23.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 1
assert acc.char_current_temp.value == 23.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0}) hass.states.async_set(entity_id, STATE_COOL,
self.hass.block_till_done() {ATTR_OPERATION_MODE: STATE_COOL,
acc = self.thermostat_cls(self.hass, 'Climate', climate, ATTR_TEMPERATURE: 20.0,
2, config=None) ATTR_CURRENT_TEMPERATURE: 25.0,
acc.run() ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 20.0
assert acc.char_current_heat_cool.value == 2
assert acc.char_target_heat_cool.value == 2
assert acc.char_current_temp.value == 25.0
assert acc.char_display_units.value == 0
self.assertEqual(acc.aid, 2) hass.states.async_set(entity_id, STATE_COOL,
self.assertEqual(acc.category, 9) # Thermostat {ATTR_OPERATION_MODE: STATE_COOL,
ATTR_TEMPERATURE: 20.0,
ATTR_CURRENT_TEMPERATURE: 19.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 20.0
assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 2
assert acc.char_current_temp.value == 19.0
assert acc.char_display_units.value == 0
self.assertEqual(acc.char_current_heat_cool.value, 0) hass.states.async_set(entity_id, STATE_OFF,
self.assertEqual(acc.char_target_heat_cool.value, 0) {ATTR_OPERATION_MODE: STATE_OFF,
self.assertEqual(acc.char_current_temp.value, 21.0) ATTR_TEMPERATURE: 22.0,
self.assertEqual(acc.char_target_temp.value, 21.0) ATTR_CURRENT_TEMPERATURE: 18.0,
self.assertEqual(acc.char_display_units.value, 0) ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.assertEqual(acc.char_cooling_thresh_temp, None) await hass.async_block_till_done()
self.assertEqual(acc.char_heating_thresh_temp, None) assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 0
assert acc.char_current_temp.value == 18.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_HEAT, hass.states.async_set(entity_id, STATE_AUTO,
{ATTR_OPERATION_MODE: STATE_HEAT, {ATTR_OPERATION_MODE: STATE_AUTO,
ATTR_TEMPERATURE: 22.0, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_CURRENT_TEMPERATURE: 18.0, ATTR_TEMPERATURE: 22.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) ATTR_CURRENT_TEMPERATURE: 18.0,
self.hass.block_till_done() ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.assertEqual(acc.char_target_temp.value, 22.0) await hass.async_block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 1) assert acc.char_target_temp.value == 22.0
self.assertEqual(acc.char_target_heat_cool.value, 1) assert acc.char_current_heat_cool.value == 1
self.assertEqual(acc.char_current_temp.value, 18.0) assert acc.char_target_heat_cool.value == 3
self.assertEqual(acc.char_display_units.value, 0) assert acc.char_current_temp.value == 18.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_HEAT, hass.states.async_set(entity_id, STATE_AUTO,
{ATTR_OPERATION_MODE: STATE_HEAT, {ATTR_OPERATION_MODE: STATE_AUTO,
ATTR_TEMPERATURE: 22.0, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_CURRENT_TEMPERATURE: 23.0, ATTR_TEMPERATURE: 22.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) ATTR_CURRENT_TEMPERATURE: 25.0,
self.hass.block_till_done() ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.assertEqual(acc.char_target_temp.value, 22.0) await hass.async_block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 0) assert acc.char_target_temp.value == 22.0
self.assertEqual(acc.char_target_heat_cool.value, 1) assert acc.char_current_heat_cool.value == 2
self.assertEqual(acc.char_current_temp.value, 23.0) assert acc.char_target_heat_cool.value == 3
self.assertEqual(acc.char_display_units.value, 0) assert acc.char_current_temp.value == 25.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_COOL, hass.states.async_set(entity_id, STATE_AUTO,
{ATTR_OPERATION_MODE: STATE_COOL, {ATTR_OPERATION_MODE: STATE_AUTO,
ATTR_TEMPERATURE: 20.0, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_CURRENT_TEMPERATURE: 25.0, ATTR_TEMPERATURE: 22.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) ATTR_CURRENT_TEMPERATURE: 22.0,
self.hass.block_till_done() ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.assertEqual(acc.char_target_temp.value, 20.0) await hass.async_block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 2) assert acc.char_target_temp.value == 22.0
self.assertEqual(acc.char_target_heat_cool.value, 2) assert acc.char_current_heat_cool.value == 0
self.assertEqual(acc.char_current_temp.value, 25.0) assert acc.char_target_heat_cool.value == 3
self.assertEqual(acc.char_display_units.value, 0) assert acc.char_current_temp.value == 22.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_COOL, # Set from HomeKit
{ATTR_OPERATION_MODE: STATE_COOL, call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
ATTR_TEMPERATURE: 20.0, call_set_operation_mode = async_mock_service(hass, DOMAIN,
ATTR_CURRENT_TEMPERATURE: 19.0, 'set_operation_mode')
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.hass.block_till_done()
self.assertEqual(acc.char_target_temp.value, 20.0)
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 2)
self.assertEqual(acc.char_current_temp.value, 19.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_OFF, await hass.async_add_job(acc.char_target_temp.client_update_value, 19.0)
{ATTR_OPERATION_MODE: STATE_OFF, await hass.async_block_till_done()
ATTR_TEMPERATURE: 22.0, assert call_set_temperature
ATTR_CURRENT_TEMPERATURE: 18.0, assert call_set_temperature[0].data[ATTR_ENTITY_ID] == entity_id
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) assert call_set_temperature[0].data[ATTR_TEMPERATURE] == 19.0
self.hass.block_till_done() assert acc.char_target_temp.value == 19.0
self.assertEqual(acc.char_target_temp.value, 22.0)
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 0)
self.assertEqual(acc.char_current_temp.value, 18.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_AUTO, await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 1)
{ATTR_OPERATION_MODE: STATE_AUTO, await hass.async_block_till_done()
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], assert call_set_operation_mode
ATTR_TEMPERATURE: 22.0, assert call_set_operation_mode[0].data[ATTR_ENTITY_ID] == entity_id
ATTR_CURRENT_TEMPERATURE: 18.0, assert call_set_operation_mode[0].data[ATTR_OPERATION_MODE] == STATE_HEAT
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) assert acc.char_target_heat_cool.value == 1
self.hass.block_till_done()
self.assertEqual(acc.char_target_temp.value, 22.0)
self.assertEqual(acc.char_current_heat_cool.value, 1)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 18.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_AUTO,
{ATTR_OPERATION_MODE: STATE_AUTO,
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 25.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.hass.block_till_done()
self.assertEqual(acc.char_target_temp.value, 22.0)
self.assertEqual(acc.char_current_heat_cool.value, 2)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 25.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_AUTO, async def test_auto_thermostat(hass, cls):
{ATTR_OPERATION_MODE: STATE_AUTO, """Test if accessory and HA are updated accordingly."""
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], entity_id = 'climate.test'
ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 22.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.hass.block_till_done()
self.assertEqual(acc.char_target_temp.value, 22.0)
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 22.0)
self.assertEqual(acc.char_display_units.value, 0)
# Set from HomeKit # support_auto = True
acc.char_target_temp.client_update_value(19.0) hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual( acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
self.events[0].data[ATTR_SERVICE], 'set_temperature') await hass.async_add_job(acc.run)
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_TEMPERATURE], 19.0)
self.assertEqual(acc.char_target_temp.value, 19.0)
acc.char_target_heat_cool.client_update_value(1) assert acc.char_cooling_thresh_temp.value == 23.0
self.hass.block_till_done() assert acc.char_heating_thresh_temp.value == 19.0
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'set_operation_mode')
self.assertEqual(
self.events[1].data[ATTR_SERVICE_DATA][ATTR_OPERATION_MODE],
STATE_HEAT)
self.assertEqual(acc.char_target_heat_cool.value, 1)
def test_auto_thermostat(self): hass.states.async_set(entity_id, STATE_AUTO,
"""Test if accessory and HA are updated accordingly.""" {ATTR_OPERATION_MODE: STATE_AUTO,
climate = 'climate.test' ATTR_TARGET_TEMP_HIGH: 22.0,
ATTR_TARGET_TEMP_LOW: 20.0,
ATTR_CURRENT_TEMPERATURE: 18.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 20.0
assert acc.char_cooling_thresh_temp.value == 22.0
assert acc.char_current_heat_cool.value == 1
assert acc.char_target_heat_cool.value == 3
assert acc.char_current_temp.value == 18.0
assert acc.char_display_units.value == 0
# support_auto = True hass.states.async_set(entity_id, STATE_AUTO,
self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) {ATTR_OPERATION_MODE: STATE_AUTO,
self.hass.block_till_done() ATTR_TARGET_TEMP_HIGH: 23.0,
acc = self.thermostat_cls(self.hass, 'Climate', climate, ATTR_TARGET_TEMP_LOW: 19.0,
2, config=None) ATTR_CURRENT_TEMPERATURE: 24.0,
acc.run() ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 19.0
assert acc.char_cooling_thresh_temp.value == 23.0
assert acc.char_current_heat_cool.value == 2
assert acc.char_target_heat_cool.value == 3
assert acc.char_current_temp.value == 24.0
assert acc.char_display_units.value == 0
self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) hass.states.async_set(entity_id, STATE_AUTO,
self.assertEqual(acc.char_heating_thresh_temp.value, 19.0) {ATTR_OPERATION_MODE: STATE_AUTO,
ATTR_TARGET_TEMP_HIGH: 23.0,
ATTR_TARGET_TEMP_LOW: 19.0,
ATTR_CURRENT_TEMPERATURE: 21.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 19.0
assert acc.char_cooling_thresh_temp.value == 23.0
assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 3
assert acc.char_current_temp.value == 21.0
assert acc.char_display_units.value == 0
self.hass.states.set(climate, STATE_AUTO, # Set from HomeKit
{ATTR_OPERATION_MODE: STATE_AUTO, call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
ATTR_TARGET_TEMP_HIGH: 22.0,
ATTR_TARGET_TEMP_LOW: 20.0,
ATTR_CURRENT_TEMPERATURE: 18.0,
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
self.hass.block_till_done()
self.assertEqual(acc.char_heating_thresh_temp.value, 20.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 22.0)
self.assertEqual(acc.char_current_heat_cool.value, 1)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 18.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_AUTO, await hass.async_add_job(
{ATTR_OPERATION_MODE: STATE_AUTO, acc.char_heating_thresh_temp.client_update_value, 20.0)
ATTR_TARGET_TEMP_HIGH: 23.0, await hass.async_block_till_done()
ATTR_TARGET_TEMP_LOW: 19.0, assert call_set_temperature[0]
ATTR_CURRENT_TEMPERATURE: 24.0, assert call_set_temperature[0].data[ATTR_ENTITY_ID] == entity_id
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) assert call_set_temperature[0].data[ATTR_TARGET_TEMP_LOW] == 20.0
self.hass.block_till_done() assert acc.char_heating_thresh_temp.value == 20.0
self.assertEqual(acc.char_heating_thresh_temp.value, 19.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0)
self.assertEqual(acc.char_current_heat_cool.value, 2)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 24.0)
self.assertEqual(acc.char_display_units.value, 0)
self.hass.states.set(climate, STATE_AUTO, await hass.async_add_job(
{ATTR_OPERATION_MODE: STATE_AUTO, acc.char_cooling_thresh_temp.client_update_value, 25.0)
ATTR_TARGET_TEMP_HIGH: 23.0, await hass.async_block_till_done()
ATTR_TARGET_TEMP_LOW: 19.0, assert call_set_temperature[1]
ATTR_CURRENT_TEMPERATURE: 21.0, assert call_set_temperature[1].data[ATTR_ENTITY_ID] == entity_id
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) assert call_set_temperature[1].data[ATTR_TARGET_TEMP_HIGH] == 25.0
self.hass.block_till_done() assert acc.char_cooling_thresh_temp.value == 25.0
self.assertEqual(acc.char_heating_thresh_temp.value, 19.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0)
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 3)
self.assertEqual(acc.char_current_temp.value, 21.0)
self.assertEqual(acc.char_display_units.value, 0)
# Set from HomeKit
acc.char_heating_thresh_temp.client_update_value(20.0)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'set_temperature')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_TARGET_TEMP_LOW], 20.0)
self.assertEqual(acc.char_heating_thresh_temp.value, 20.0)
acc.char_cooling_thresh_temp.client_update_value(25.0) async def test_power_state(hass, cls):
self.hass.block_till_done() """Test if accessory and HA are updated accordingly."""
self.assertEqual( entity_id = 'climate.test'
self.events[1].data[ATTR_SERVICE], 'set_temperature')
self.assertEqual(
self.events[1].data[ATTR_SERVICE_DATA][ATTR_TARGET_TEMP_HIGH],
25.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 25.0)
def test_power_state(self): # SUPPORT_ON_OFF = True
"""Test if accessory and HA are updated accordingly.""" hass.states.async_set(entity_id, STATE_HEAT,
climate = 'climate.test' {ATTR_SUPPORTED_FEATURES: 4096,
ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
await hass.async_block_till_done()
acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
await hass.async_add_job(acc.run)
assert acc.support_power_state is True
# SUPPORT_ON_OFF = True assert acc.char_current_heat_cool.value == 1
self.hass.states.set(climate, STATE_HEAT, assert acc.char_target_heat_cool.value == 1
{ATTR_SUPPORTED_FEATURES: 4096,
ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
self.hass.block_till_done()
acc = self.thermostat_cls(self.hass, 'Climate', climate,
2, config=None)
acc.run()
self.assertTrue(acc.support_power_state)
self.assertEqual(acc.char_current_heat_cool.value, 1) hass.states.async_set(entity_id, STATE_OFF,
self.assertEqual(acc.char_target_heat_cool.value, 1) {ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
await hass.async_block_till_done()
assert acc.char_current_heat_cool.value == 0
assert acc.char_target_heat_cool.value == 0
self.hass.states.set(climate, STATE_OFF, hass.states.async_set(entity_id, STATE_OFF,
{ATTR_OPERATION_MODE: STATE_HEAT, {ATTR_OPERATION_MODE: STATE_OFF,
ATTR_TEMPERATURE: 23.0, ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0}) ATTR_CURRENT_TEMPERATURE: 18.0})
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 0) assert acc.char_current_heat_cool.value == 0
self.assertEqual(acc.char_target_heat_cool.value, 0) assert acc.char_target_heat_cool.value == 0
self.hass.states.set(climate, STATE_OFF, # Set from HomeKit
{ATTR_OPERATION_MODE: STATE_OFF, call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
ATTR_TEMPERATURE: 23.0, call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off')
ATTR_CURRENT_TEMPERATURE: 18.0}) call_set_operation_mode = async_mock_service(hass, DOMAIN,
self.hass.block_till_done() 'set_operation_mode')
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 0)
# Set from HomeKit await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 1)
acc.char_target_heat_cool.client_update_value(1) await hass.async_block_till_done()
self.hass.block_till_done() assert call_turn_on
self.assertEqual( assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id
self.events[0].data[ATTR_SERVICE], 'turn_on') assert call_set_operation_mode
self.assertEqual( assert call_set_operation_mode[0].data[ATTR_ENTITY_ID] == entity_id
self.events[0].data[ATTR_SERVICE_DATA][ATTR_ENTITY_ID], assert call_set_operation_mode[0].data[ATTR_OPERATION_MODE] == STATE_HEAT
climate) assert acc.char_target_heat_cool.value == 1
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'set_operation_mode')
self.assertEqual(
self.events[1].data[ATTR_SERVICE_DATA][ATTR_OPERATION_MODE],
STATE_HEAT)
self.assertEqual(acc.char_target_heat_cool.value, 1)
acc.char_target_heat_cool.client_update_value(0) await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 0)
self.hass.block_till_done() await hass.async_block_till_done()
self.assertEqual( assert call_turn_off
self.events[2].data[ATTR_SERVICE], 'turn_off') assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id
self.assertEqual( assert acc.char_target_heat_cool.value == 0
self.events[2].data[ATTR_SERVICE_DATA][ATTR_ENTITY_ID],
climate)
self.assertEqual(acc.char_target_heat_cool.value, 0)
def test_thermostat_fahrenheit(self):
"""Test if accessory and HA are updated accordingly."""
climate = 'climate.test'
# support_auto = True async def test_thermostat_fahrenheit(hass, cls):
self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) """Test if accessory and HA are updated accordingly."""
self.hass.block_till_done() entity_id = 'climate.test'
acc = self.thermostat_cls(self.hass, 'Climate', climate,
2, config=None)
acc.run()
self.hass.states.set(climate, STATE_AUTO, # support_auto = True
{ATTR_OPERATION_MODE: STATE_AUTO, hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
ATTR_TARGET_TEMP_HIGH: 75.2, await hass.async_block_till_done()
ATTR_TARGET_TEMP_LOW: 68, acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
ATTR_TEMPERATURE: 71.6, await hass.async_add_job(acc.run)
ATTR_CURRENT_TEMPERATURE: 73.4,
ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT})
self.hass.block_till_done()
self.assertEqual(acc.char_heating_thresh_temp.value, 20.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 24.0)
self.assertEqual(acc.char_current_temp.value, 23.0)
self.assertEqual(acc.char_target_temp.value, 22.0)
self.assertEqual(acc.char_display_units.value, 1)
# Set from HomeKit hass.states.async_set(entity_id, STATE_AUTO,
acc.char_cooling_thresh_temp.client_update_value(23) {ATTR_OPERATION_MODE: STATE_AUTO,
self.hass.block_till_done() ATTR_TARGET_TEMP_HIGH: 75.2,
service_data = self.events[-1].data[ATTR_SERVICE_DATA] ATTR_TARGET_TEMP_LOW: 68,
self.assertEqual(service_data[ATTR_TARGET_TEMP_HIGH], 73.4) ATTR_TEMPERATURE: 71.6,
self.assertEqual(service_data[ATTR_TARGET_TEMP_LOW], 68) ATTR_CURRENT_TEMPERATURE: 73.4,
ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT})
await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 20.0
assert acc.char_cooling_thresh_temp.value == 24.0
assert acc.char_current_temp.value == 23.0
assert acc.char_target_temp.value == 22.0
assert acc.char_display_units.value == 1
acc.char_heating_thresh_temp.client_update_value(22) # Set from HomeKit
self.hass.block_till_done() call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
service_data = self.events[-1].data[ATTR_SERVICE_DATA]
self.assertEqual(service_data[ATTR_TARGET_TEMP_HIGH], 73.4)
self.assertEqual(service_data[ATTR_TARGET_TEMP_LOW], 71.6)
acc.char_target_temp.client_update_value(24.0) await hass.async_add_job(
self.hass.block_till_done() acc.char_cooling_thresh_temp.client_update_value, 23)
service_data = self.events[-1].data[ATTR_SERVICE_DATA] await hass.async_block_till_done()
self.assertEqual(service_data[ATTR_TEMPERATURE], 75.2) assert call_set_temperature[0]
assert call_set_temperature[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[0].data[ATTR_TARGET_TEMP_HIGH] == 73.4
assert call_set_temperature[0].data[ATTR_TARGET_TEMP_LOW] == 68
await hass.async_add_job(
acc.char_heating_thresh_temp.client_update_value, 22)
await hass.async_block_till_done()
assert call_set_temperature[1]
assert call_set_temperature[1].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[1].data[ATTR_TARGET_TEMP_HIGH] == 73.4
assert call_set_temperature[1].data[ATTR_TARGET_TEMP_LOW] == 71.6
await hass.async_add_job(acc.char_target_temp.client_update_value, 24.0)
await hass.async_block_till_done()
assert call_set_temperature[2]
assert call_set_temperature[2].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[2].data[ATTR_TEMPERATURE] == 75.2

View File

@ -1,25 +1,20 @@
"""Test HomeKit util module.""" """Test HomeKit util module."""
import unittest
import voluptuous as vol
import pytest import pytest
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.components.homekit.accessories import HomeBridge from homeassistant.components.homekit.accessories import HomeBridge
from homeassistant.components.homekit.const import HOMEKIT_NOTIFY_ID from homeassistant.components.homekit.const import HOMEKIT_NOTIFY_ID
from homeassistant.components.homekit.util import ( from homeassistant.components.homekit.util import (
show_setup_message, dismiss_setup_message, convert_to_float, show_setup_message, dismiss_setup_message, convert_to_float,
temperature_to_homekit, temperature_to_states, ATTR_CODE, temperature_to_homekit, temperature_to_states, density_to_air_quality)
density_to_air_quality)
from homeassistant.components.homekit.util import validate_entity_config \ from homeassistant.components.homekit.util import validate_entity_config \
as vec as vec
from homeassistant.components.persistent_notification import ( from homeassistant.components.persistent_notification import (
SERVICE_CREATE, SERVICE_DISMISS, ATTR_NOTIFICATION_ID) DOMAIN, ATTR_NOTIFICATION_ID)
from homeassistant.const import ( from homeassistant.const import (
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_CODE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT)
TEMP_CELSIUS, TEMP_FAHRENHEIT, STATE_UNKNOWN)
from tests.common import get_test_home_assistant from tests.common import async_mock_service
def test_validate_entity_config(): def test_validate_entity_config():
@ -68,51 +63,27 @@ def test_density_to_air_quality():
assert density_to_air_quality(300) == 5 assert density_to_air_quality(300) == 5
class TestUtil(unittest.TestCase): async def test_show_setup_msg(hass):
"""Test all HomeKit util methods.""" """Test show setup message as persistence notification."""
bridge = HomeBridge(hass)
def setUp(self): call_create_notification = async_mock_service(hass, DOMAIN, 'create')
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.events = []
@callback await hass.async_add_job(show_setup_message, hass, bridge)
def record_event(event): await hass.async_block_till_done()
"""Track called event."""
self.events.append(event)
self.hass.bus.listen(EVENT_CALL_SERVICE, record_event) assert call_create_notification
assert call_create_notification[0].data[ATTR_NOTIFICATION_ID] == \
HOMEKIT_NOTIFY_ID
def tearDown(self):
"""Stop down everything that was started."""
self.hass.stop()
def test_show_setup_msg(self): async def test_dismiss_setup_msg(hass):
"""Test show setup message as persistence notification.""" """Test dismiss setup message."""
bridge = HomeBridge(self.hass) call_dismiss_notification = async_mock_service(hass, DOMAIN, 'dismiss')
show_setup_message(self.hass, bridge) await hass.async_add_job(dismiss_setup_message, hass)
self.hass.block_till_done() await hass.async_block_till_done()
data = self.events[0].data assert call_dismiss_notification
self.assertEqual( assert call_dismiss_notification[0].data[ATTR_NOTIFICATION_ID] == \
data.get(ATTR_DOMAIN, None), 'persistent_notification') HOMEKIT_NOTIFY_ID
self.assertEqual(data.get(ATTR_SERVICE, None), SERVICE_CREATE)
self.assertNotEqual(data.get(ATTR_SERVICE_DATA, None), None)
self.assertEqual(
data[ATTR_SERVICE_DATA].get(ATTR_NOTIFICATION_ID, None),
HOMEKIT_NOTIFY_ID)
def test_dismiss_setup_msg(self):
"""Test dismiss setup message."""
dismiss_setup_message(self.hass)
self.hass.block_till_done()
data = self.events[0].data
self.assertEqual(
data.get(ATTR_DOMAIN, None), 'persistent_notification')
self.assertEqual(data.get(ATTR_SERVICE, None), SERVICE_DISMISS)
self.assertNotEqual(data.get(ATTR_SERVICE_DATA, None), None)
self.assertEqual(
data[ATTR_SERVICE_DATA].get(ATTR_NOTIFICATION_ID, None),
HOMEKIT_NOTIFY_ID)