Rewrite Alexa Smart-Home skill to v3 (#9699)
* Rewrite Alexa Smart-Home skill to v3 * add discovery & fix brigness * Rewrite Tests * fix lint * fix lint p2 * fix version * fix tests * fix test message generator * Update smart_home.py * fix test * fix set bug * fix list * fix response name for discovery * fix flucky tests
This commit is contained in:
parent
4342d7aa17
commit
c1f156fd2b
2 changed files with 237 additions and 119 deletions
|
@ -1,5 +1,6 @@
|
|||
"""Test for smart home alexa support."""
|
||||
import asyncio
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -8,22 +9,86 @@ from homeassistant.components.alexa import smart_home
|
|||
from tests.common import async_mock_service
|
||||
|
||||
|
||||
def test_create_api_message():
|
||||
"""Create a API message."""
|
||||
msg = smart_home.api_message('testName', 'testNameSpace')
|
||||
def get_new_request(namespace, name, endpoint=None):
|
||||
"""Generate a new API message."""
|
||||
raw_msg = {
|
||||
'directive': {
|
||||
'header': {
|
||||
'namespace': namespace,
|
||||
'name': name,
|
||||
'messageId': str(uuid4()),
|
||||
'correlationToken': str(uuid4()),
|
||||
'payloadVersion': '3',
|
||||
},
|
||||
'endpoint': {
|
||||
'scope': {
|
||||
'type': 'BearerToken',
|
||||
'token': str(uuid4()),
|
||||
},
|
||||
'endpointId': endpoint,
|
||||
},
|
||||
'payload': {},
|
||||
}
|
||||
}
|
||||
|
||||
if not endpoint:
|
||||
raw_msg['directive'].pop('endpoint')
|
||||
|
||||
return raw_msg
|
||||
|
||||
|
||||
def test_create_api_message_defaults():
|
||||
"""Create a API message response of a request with defaults."""
|
||||
request = get_new_request('Alexa.PowerController', 'TurnOn', 'switch#xy')
|
||||
request = request['directive']
|
||||
|
||||
msg = smart_home.api_message(request, payload={'test': 3})
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert msg['header']['messageId'] is not None
|
||||
assert msg['header']['messageId'] != request['header']['messageId']
|
||||
assert msg['header']['correlationToken'] == \
|
||||
request['header']['correlationToken']
|
||||
assert msg['header']['name'] == 'Response'
|
||||
assert msg['header']['namespace'] == 'Alexa'
|
||||
assert msg['header']['payloadVersion'] == '3'
|
||||
|
||||
assert 'test' in msg['payload']
|
||||
assert msg['payload']['test'] == 3
|
||||
|
||||
assert msg['endpoint'] == request['endpoint']
|
||||
|
||||
|
||||
def test_create_api_message_special():
|
||||
"""Create a API message response of a request with non defaults."""
|
||||
request = get_new_request('Alexa.PowerController', 'TurnOn')
|
||||
request = request['directive']
|
||||
|
||||
request['header'].pop('correlationToken')
|
||||
|
||||
msg = smart_home.api_message(request, 'testName', 'testNameSpace')
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert msg['header']['messageId'] is not None
|
||||
assert msg['header']['messageId'] != request['header']['messageId']
|
||||
assert 'correlationToken' not in msg['header']
|
||||
assert msg['header']['name'] == 'testName'
|
||||
assert msg['header']['namespace'] == 'testNameSpace'
|
||||
assert msg['header']['payloadVersion'] == '2'
|
||||
assert msg['header']['payloadVersion'] == '3'
|
||||
|
||||
assert msg['payload'] == {}
|
||||
assert 'endpoint' not in msg
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_wrong_version(hass):
|
||||
"""Test with wrong version."""
|
||||
msg = smart_home.api_message('testName', 'testNameSpace')
|
||||
msg['header']['payloadVersion'] = '3'
|
||||
msg = get_new_request('Alexa.PowerController', 'TurnOn')
|
||||
msg['directive']['header']['payloadVersion'] = '2'
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
yield from smart_home.async_handle_message(hass, msg)
|
||||
|
@ -32,8 +97,7 @@ def test_wrong_version(hass):
|
|||
@asyncio.coroutine
|
||||
def test_discovery_request(hass):
|
||||
"""Test alexa discovery request."""
|
||||
msg = smart_home.api_message(
|
||||
'DiscoverAppliancesRequest', 'Alexa.ConnectedHome.Discovery')
|
||||
request = get_new_request('Alexa.Discovery', 'Discover')
|
||||
|
||||
# settup test devices
|
||||
hass.states.async_set(
|
||||
|
@ -46,30 +110,44 @@ def test_discovery_request(hass):
|
|||
'friendly_name': "Test light 2", 'supported_features': 1
|
||||
})
|
||||
|
||||
resp = yield from smart_home.async_api_discovery(hass, msg)
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert len(resp['payload']['discoveredAppliances']) == 3
|
||||
assert resp['header']['name'] == 'DiscoverAppliancesResponse'
|
||||
assert resp['header']['namespace'] == 'Alexa.ConnectedHome.Discovery'
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
for i, appliance in enumerate(resp['payload']['discoveredAppliances']):
|
||||
if appliance['applianceId'] == 'switch#test':
|
||||
assert appliance['applianceTypes'][0] == "SWITCH"
|
||||
assert len(msg['payload']['endpoints']) == 3
|
||||
assert msg['header']['name'] == 'Discover.Response'
|
||||
assert msg['header']['namespace'] == 'Alexa.Discovery'
|
||||
|
||||
for appliance in msg['payload']['endpoints']:
|
||||
if appliance['endpointId'] == 'switch#test':
|
||||
assert appliance['displayCategories'][0] == "SWITCH"
|
||||
assert appliance['friendlyName'] == "Test switch"
|
||||
assert appliance['actions'] == ['turnOff', 'turnOn']
|
||||
assert len(appliance['capabilities']) == 1
|
||||
assert appliance['capabilities'][-1]['interface'] == \
|
||||
'Alexa.PowerController'
|
||||
continue
|
||||
|
||||
if appliance['applianceId'] == 'light#test_1':
|
||||
assert appliance['applianceTypes'][0] == "LIGHT"
|
||||
if appliance['endpointId'] == 'light#test_1':
|
||||
assert appliance['displayCategories'][0] == "LIGHT"
|
||||
assert appliance['friendlyName'] == "Test light 1"
|
||||
assert appliance['actions'] == ['turnOff', 'turnOn']
|
||||
assert len(appliance['capabilities']) == 1
|
||||
assert appliance['capabilities'][-1]['interface'] == \
|
||||
'Alexa.PowerController'
|
||||
continue
|
||||
|
||||
if appliance['applianceId'] == 'light#test_2':
|
||||
assert appliance['applianceTypes'][0] == "LIGHT"
|
||||
if appliance['endpointId'] == 'light#test_2':
|
||||
assert appliance['displayCategories'][0] == "LIGHT"
|
||||
assert appliance['friendlyName'] == "Test light 2"
|
||||
assert appliance['actions'] == \
|
||||
['turnOff', 'turnOn', 'setPercentage']
|
||||
assert len(appliance['capabilities']) == 2
|
||||
|
||||
caps = set()
|
||||
for feature in appliance['capabilities']:
|
||||
caps.add(feature['interface'])
|
||||
|
||||
assert 'Alexa.BrightnessController' in caps
|
||||
assert 'Alexa.PowerController' in caps
|
||||
|
||||
continue
|
||||
|
||||
raise AssertionError("Unknown appliance!")
|
||||
|
@ -78,31 +156,41 @@ def test_discovery_request(hass):
|
|||
@asyncio.coroutine
|
||||
def test_api_entity_not_exists(hass):
|
||||
"""Test api turn on process without entity."""
|
||||
msg_switch = smart_home.api_message(
|
||||
'TurnOnRequest', 'Alexa.ConnectedHome.Control', {
|
||||
'appliance': {
|
||||
'applianceId': 'switch#test'
|
||||
}
|
||||
})
|
||||
request = get_new_request('Alexa.PowerController', 'TurnOn', 'switch#test')
|
||||
|
||||
call_switch = async_mock_service(hass, 'switch', 'turn_on')
|
||||
|
||||
resp = yield from smart_home.async_api_turn_on(hass, msg_switch)
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert len(call_switch) == 0
|
||||
assert resp['header']['name'] == 'DriverInternalError'
|
||||
assert resp['header']['namespace'] == 'Alexa.ConnectedHome.Control'
|
||||
assert msg['header']['name'] == 'ErrorResponse'
|
||||
assert msg['header']['namespace'] == 'Alexa'
|
||||
assert msg['payload']['type'] == 'NO_SUCH_ENDPOINT'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_api_function_not_implemented(hass):
|
||||
"""Test api call that is not implemented to us."""
|
||||
request = get_new_request('Alexa.HAHAAH', 'Sweet')
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert msg['header']['name'] == 'ErrorResponse'
|
||||
assert msg['header']['namespace'] == 'Alexa'
|
||||
assert msg['payload']['type'] == 'INTERNAL_ERROR'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
@pytest.mark.parametrize("domain", ['light', 'switch'])
|
||||
def test_api_turn_on(hass, domain):
|
||||
"""Test api turn on process."""
|
||||
msg = smart_home.api_message(
|
||||
'TurnOnRequest', 'Alexa.ConnectedHome.Control', {
|
||||
'appliance': {
|
||||
'applianceId': '{}#test'.format(domain)
|
||||
}
|
||||
})
|
||||
request = get_new_request(
|
||||
'Alexa.PowerController', 'TurnOn', '{}#test'.format(domain))
|
||||
|
||||
# settup test devices
|
||||
hass.states.async_set(
|
||||
|
@ -112,22 +200,22 @@ def test_api_turn_on(hass, domain):
|
|||
|
||||
call = async_mock_service(hass, domain, 'turn_on')
|
||||
|
||||
resp = yield from smart_home.async_api_turn_on(hass, msg)
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert len(call) == 1
|
||||
assert call[0].data['entity_id'] == '{}.test'.format(domain)
|
||||
assert resp['header']['name'] == 'TurnOnConfirmation'
|
||||
assert msg['header']['name'] == 'Response'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
@pytest.mark.parametrize("domain", ['light', 'switch'])
|
||||
def test_api_turn_off(hass, domain):
|
||||
"""Test api turn on process."""
|
||||
msg = smart_home.api_message(
|
||||
'TurnOffRequest', 'Alexa.ConnectedHome.Control', {
|
||||
'appliance': {
|
||||
'applianceId': '{}#test'.format(domain)
|
||||
}
|
||||
})
|
||||
request = get_new_request(
|
||||
'Alexa.PowerController', 'TurnOff', '{}#test'.format(domain))
|
||||
|
||||
# settup test devices
|
||||
hass.states.async_set(
|
||||
|
@ -137,24 +225,24 @@ def test_api_turn_off(hass, domain):
|
|||
|
||||
call = async_mock_service(hass, domain, 'turn_off')
|
||||
|
||||
resp = yield from smart_home.async_api_turn_off(hass, msg)
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert len(call) == 1
|
||||
assert call[0].data['entity_id'] == '{}.test'.format(domain)
|
||||
assert resp['header']['name'] == 'TurnOffConfirmation'
|
||||
assert msg['header']['name'] == 'Response'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_api_set_percentage_light(hass):
|
||||
def test_api_set_brightness(hass):
|
||||
"""Test api set brightness process."""
|
||||
msg_light = smart_home.api_message(
|
||||
'SetPercentageRequest', 'Alexa.ConnectedHome.Control', {
|
||||
'appliance': {
|
||||
'applianceId': 'light#test'
|
||||
},
|
||||
'percentageState': {
|
||||
'value': '50'
|
||||
}
|
||||
})
|
||||
request = get_new_request(
|
||||
'Alexa.BrightnessController', 'SetBrightness', 'light#test')
|
||||
|
||||
# add payload
|
||||
request['directive']['payload']['brightness'] = '50'
|
||||
|
||||
# settup test devices
|
||||
hass.states.async_set(
|
||||
|
@ -162,8 +250,12 @@ def test_api_set_percentage_light(hass):
|
|||
|
||||
call_light = async_mock_service(hass, 'light', 'turn_on')
|
||||
|
||||
resp = yield from smart_home.async_api_set_percentage(hass, msg_light)
|
||||
msg = yield from smart_home.async_handle_message(hass, request)
|
||||
|
||||
assert 'event' in msg
|
||||
msg = msg['event']
|
||||
|
||||
assert len(call_light) == 1
|
||||
assert call_light[0].data['entity_id'] == 'light.test'
|
||||
assert call_light[0].data['brightness'] == '50'
|
||||
assert resp['header']['name'] == 'SetPercentageConfirmation'
|
||||
assert msg['header']['name'] == 'Response'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue