2018-03-01 23:20:02 +00:00
|
|
|
"""Test all functions related to the basic accessory implementation.
|
|
|
|
|
|
|
|
This includes tests for all mock object types.
|
|
|
|
"""
|
2018-04-06 21:11:53 +00:00
|
|
|
from datetime import datetime, timedelta
|
2018-05-10 23:21:59 +00:00
|
|
|
from unittest.mock import patch, Mock
|
2018-03-01 23:20:02 +00:00
|
|
|
|
2018-05-21 02:25:53 +00:00
|
|
|
import pytest
|
|
|
|
|
2018-03-01 23:20:02 +00:00
|
|
|
from homeassistant.components.homekit.accessories import (
|
2018-04-06 21:11:53 +00:00
|
|
|
debounce, HomeAccessory, HomeBridge, HomeDriver)
|
2018-03-01 23:20:02 +00:00
|
|
|
from homeassistant.components.homekit.const import (
|
2018-05-21 02:25:53 +00:00
|
|
|
BRIDGE_MODEL, BRIDGE_NAME, BRIDGE_SERIAL_NUMBER, CHAR_FIRMWARE_REVISION,
|
|
|
|
CHAR_MANUFACTURER, CHAR_MODEL, CHAR_NAME, CHAR_SERIAL_NUMBER,
|
|
|
|
MANUFACTURER, SERV_ACCESSORY_INFO)
|
2018-05-04 14:46:00 +00:00
|
|
|
from homeassistant.const import __version__, ATTR_NOW, EVENT_TIME_CHANGED
|
2018-04-06 21:11:53 +00:00
|
|
|
import homeassistant.util.dt as dt_util
|
|
|
|
|
|
|
|
|
2018-05-10 23:21:59 +00:00
|
|
|
async def test_debounce(hass):
|
|
|
|
"""Test add_timeout decorator function."""
|
|
|
|
def demo_func(*args):
|
|
|
|
nonlocal arguments, counter
|
|
|
|
counter += 1
|
|
|
|
arguments = args
|
|
|
|
|
|
|
|
arguments = None
|
|
|
|
counter = 0
|
2018-05-30 10:39:27 +00:00
|
|
|
mock = Mock(hass=hass, debounce={})
|
2018-05-10 23:21:59 +00:00
|
|
|
|
|
|
|
debounce_demo = debounce(demo_func)
|
|
|
|
assert debounce_demo.__name__ == 'demo_func'
|
|
|
|
now = datetime(2018, 1, 1, 20, 0, 0, tzinfo=dt_util.UTC)
|
|
|
|
|
|
|
|
with patch('homeassistant.util.dt.utcnow', return_value=now):
|
|
|
|
await hass.async_add_job(debounce_demo, mock, 'value')
|
|
|
|
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):
|
|
|
|
await hass.async_add_job(debounce_demo, mock, 'value')
|
|
|
|
await hass.async_add_job(debounce_demo, mock, 'value')
|
|
|
|
|
|
|
|
hass.bus.async_fire(
|
|
|
|
EVENT_TIME_CHANGED, {ATTR_NOW: now + timedelta(seconds=3)})
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert counter == 2
|
|
|
|
|
|
|
|
|
2018-05-29 20:43:26 +00:00
|
|
|
async def test_home_accessory(hass, hk_driver):
|
2018-05-10 23:21:59 +00:00
|
|
|
"""Test HomeAccessory class."""
|
2018-05-12 15:10:19 +00:00
|
|
|
entity_id = 'homekit.accessory'
|
|
|
|
hass.states.async_set(entity_id, None)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
2018-05-29 20:43:26 +00:00
|
|
|
acc = HomeAccessory(hass, hk_driver, 'Home Accessory',
|
|
|
|
entity_id, 2, None)
|
2018-05-10 23:21:59 +00:00
|
|
|
assert acc.hass == hass
|
|
|
|
assert acc.display_name == 'Home Accessory'
|
2018-05-11 12:22:45 +00:00
|
|
|
assert acc.aid == 2
|
2018-05-10 23:21:59 +00:00
|
|
|
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'
|
|
|
|
|
2018-05-21 02:25:53 +00:00
|
|
|
hass.states.async_set(entity_id, 'on')
|
2018-05-10 23:21:59 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-05-21 02:25:53 +00:00
|
|
|
with patch('homeassistant.components.homekit.accessories.'
|
|
|
|
'HomeAccessory.update_state') as mock_update_state:
|
|
|
|
await hass.async_add_job(acc.run)
|
2018-05-30 10:39:27 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-05-21 02:25:53 +00:00
|
|
|
state = hass.states.get(entity_id)
|
|
|
|
mock_update_state.assert_called_with(state)
|
2018-05-10 23:21:59 +00:00
|
|
|
|
2018-05-21 02:25:53 +00:00
|
|
|
hass.states.async_remove(entity_id)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert mock_update_state.call_count == 1
|
2018-05-12 15:10:19 +00:00
|
|
|
|
2018-05-21 02:25:53 +00:00
|
|
|
with pytest.raises(NotImplementedError):
|
|
|
|
acc.update_state('new_state')
|
|
|
|
|
|
|
|
# Test model name from domain
|
2018-05-29 20:43:26 +00:00
|
|
|
entity_id = 'test_model.demo'
|
|
|
|
acc = HomeAccessory('hass', hk_driver, 'test_name', entity_id, 2, None)
|
2018-05-10 23:21:59 +00:00
|
|
|
serv = acc.services[0] # SERV_ACCESSORY_INFO
|
|
|
|
assert serv.get_characteristic(CHAR_MODEL).value == 'Test Model'
|
|
|
|
|
|
|
|
|
2018-05-29 20:43:26 +00:00
|
|
|
def test_home_bridge(hk_driver):
|
2018-05-10 23:21:59 +00:00
|
|
|
"""Test HomeBridge class."""
|
2018-05-29 20:43:26 +00:00
|
|
|
bridge = HomeBridge('hass', hk_driver)
|
2018-05-10 23:21:59 +00:00
|
|
|
assert bridge.hass == 'hass'
|
|
|
|
assert bridge.display_name == BRIDGE_NAME
|
|
|
|
assert bridge.category == 2 # Category.BRIDGE
|
|
|
|
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
|
|
|
|
|
2018-05-29 20:43:26 +00:00
|
|
|
bridge = HomeBridge('hass', hk_driver, 'test_name')
|
2018-05-10 23:21:59 +00:00
|
|
|
assert bridge.display_name == 'test_name'
|
|
|
|
assert len(bridge.services) == 1
|
|
|
|
serv = bridge.services[0] # SERV_ACCESSORY_INFO
|
|
|
|
|
|
|
|
# setup_message
|
|
|
|
bridge.setup_message()
|
|
|
|
|
|
|
|
|
|
|
|
def test_home_driver():
|
|
|
|
"""Test HomeDriver class."""
|
|
|
|
ip_address = '127.0.0.1'
|
|
|
|
port = 51826
|
|
|
|
path = '.homekit.state'
|
2018-05-18 14:32:57 +00:00
|
|
|
pin = b'123-45-678'
|
2018-05-10 23:21:59 +00:00
|
|
|
|
|
|
|
with patch('pyhap.accessory_driver.AccessoryDriver.__init__') \
|
|
|
|
as mock_driver:
|
2018-05-29 20:43:26 +00:00
|
|
|
driver = HomeDriver('hass', address=ip_address, port=port,
|
|
|
|
persist_file=path)
|
2018-05-10 23:21:59 +00:00
|
|
|
|
2018-05-29 20:43:26 +00:00
|
|
|
mock_driver.assert_called_with(address=ip_address, port=port,
|
|
|
|
persist_file=path)
|
2018-05-18 14:32:57 +00:00
|
|
|
driver.state = Mock(pincode=pin)
|
|
|
|
|
|
|
|
# pair
|
|
|
|
with patch('pyhap.accessory_driver.AccessoryDriver.pair') as mock_pair, \
|
|
|
|
patch('homeassistant.components.homekit.accessories.'
|
|
|
|
'dismiss_setup_message') as mock_dissmiss_msg:
|
|
|
|
driver.pair('client_uuid', 'client_public')
|
|
|
|
|
|
|
|
mock_pair.assert_called_with('client_uuid', 'client_public')
|
|
|
|
mock_dissmiss_msg.assert_called_with('hass')
|
|
|
|
|
|
|
|
# unpair
|
|
|
|
with patch('pyhap.accessory_driver.AccessoryDriver.unpair') \
|
|
|
|
as mock_unpair, \
|
|
|
|
patch('homeassistant.components.homekit.accessories.'
|
|
|
|
'show_setup_message') as mock_show_msg:
|
|
|
|
driver.unpair('client_uuid')
|
|
|
|
|
|
|
|
mock_unpair.assert_called_with('client_uuid')
|
|
|
|
mock_show_msg.assert_called_with('hass', pin)
|