Added HassOpenCover and HassCloseCover intents (#13372)

* Added intents to cover

* Added test for cover intents

* Style fixes

* Reverted reversions

* Async fixes

* Woof

* Added conditional loading

* Added conditional loading

* Added conditional loading

* Moved tests, fixed logic

* Moved tests, fixed logic

* Pylint

* Pylint

* Refactored componenet registration

* Refactored componenet registration

* Lint
This commit is contained in:
Tod Schmidt 2018-03-30 20:22:48 -04:00 committed by Paulus Schoutsen
parent bf58945680
commit bf44dc422c
5 changed files with 185 additions and 83 deletions

View file

@ -13,10 +13,14 @@ from homeassistant import core
from homeassistant.components import http from homeassistant.components import http
from homeassistant.components.http.data_validator import ( from homeassistant.components.http.data_validator import (
RequestDataValidator) RequestDataValidator)
from homeassistant.components.cover import (INTENT_OPEN_COVER,
INTENT_CLOSE_COVER)
from homeassistant.const import EVENT_COMPONENT_LOADED
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import intent from homeassistant.helpers import intent
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.setup import (ATTR_COMPONENT)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -28,6 +32,13 @@ DOMAIN = 'conversation'
REGEX_TURN_COMMAND = re.compile(r'turn (?P<name>(?: |\w)+) (?P<command>\w+)') REGEX_TURN_COMMAND = re.compile(r'turn (?P<name>(?: |\w)+) (?P<command>\w+)')
REGEX_TYPE = type(re.compile('')) REGEX_TYPE = type(re.compile(''))
UTTERANCES = {
'cover': {
INTENT_OPEN_COVER: ['Open [the] [a] [an] {name}[s]'],
INTENT_CLOSE_COVER: ['Close [the] [a] [an] {name}[s]']
}
}
SERVICE_PROCESS = 'process' SERVICE_PROCESS = 'process'
SERVICE_PROCESS_SCHEMA = vol.Schema({ SERVICE_PROCESS_SCHEMA = vol.Schema({
@ -112,6 +123,25 @@ async def async_setup(hass, config):
'[the] [a] [an] {name}[s] toggle', '[the] [a] [an] {name}[s] toggle',
]) ])
@callback
def register_utterances(component):
"""Register utterances for a component."""
if component not in UTTERANCES:
return
for intent_type, sentences in UTTERANCES[component].items():
async_register(hass, intent_type, sentences)
@callback
def component_loaded(event):
"""Handle a new component loaded."""
register_utterances(event.data[ATTR_COMPONENT])
hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded)
# Check already loaded components.
for component in hass.config.components:
register_utterances(component)
return True return True

View file

@ -17,6 +17,7 @@ from homeassistant.helpers.entity import Entity
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components import group from homeassistant.components import group
from homeassistant.helpers import intent
from homeassistant.const import ( from homeassistant.const import (
SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION, SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION,
SERVICE_STOP_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_CLOSE_COVER_TILT, SERVICE_STOP_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_CLOSE_COVER_TILT,
@ -55,6 +56,9 @@ ATTR_CURRENT_TILT_POSITION = 'current_tilt_position'
ATTR_POSITION = 'position' ATTR_POSITION = 'position'
ATTR_TILT_POSITION = 'tilt_position' ATTR_TILT_POSITION = 'tilt_position'
INTENT_OPEN_COVER = 'HassOpenCover'
INTENT_CLOSE_COVER = 'HassCloseCover'
COVER_SERVICE_SCHEMA = vol.Schema({ COVER_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
}) })
@ -181,6 +185,12 @@ async def async_setup(hass, config):
hass.services.async_register( hass.services.async_register(
DOMAIN, service_name, async_handle_cover_service, DOMAIN, service_name, async_handle_cover_service,
schema=schema) schema=schema)
hass.helpers.intent.async_register(intent.ServiceIntentHandler(
INTENT_OPEN_COVER, DOMAIN, SERVICE_OPEN_COVER,
"Opened {}"))
hass.helpers.intent.async_register(intent.ServiceIntentHandler(
INTENT_CLOSE_COVER, DOMAIN, SERVICE_CLOSE_COVER,
"Closed {}"))
return True return True

View file

@ -0,0 +1,49 @@
"""The tests for the cover platform."""
from homeassistant.components.cover import (SERVICE_OPEN_COVER,
SERVICE_CLOSE_COVER)
from homeassistant.components import intent
import homeassistant.components as comps
from tests.common import async_mock_service
async def test_open_cover_intent(hass):
"""Test HassOpenCover intent."""
result = await comps.cover.async_setup(hass, {})
assert result
hass.states.async_set('cover.garage_door', 'closed')
calls = async_mock_service(hass, 'cover', SERVICE_OPEN_COVER)
response = await intent.async_handle(
hass, 'test', 'HassOpenCover', {'name': {'value': 'garage door'}}
)
await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Opened garage door'
assert len(calls) == 1
call = calls[0]
assert call.domain == 'cover'
assert call.service == 'open_cover'
assert call.data == {'entity_id': 'cover.garage_door'}
async def test_close_cover_intent(hass):
"""Test HassCloseCover intent."""
result = await comps.cover.async_setup(hass, {})
assert result
hass.states.async_set('cover.garage_door', 'open')
calls = async_mock_service(hass, 'cover', SERVICE_CLOSE_COVER)
response = await intent.async_handle(
hass, 'test', 'HassCloseCover', {'name': {'value': 'garage door'}}
)
await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Closed garage door'
assert len(calls) == 1
call = calls[0]
assert call.domain == 'cover'
assert call.service == 'close_cover'
assert call.data == {'entity_id': 'cover.garage_door'}

View file

@ -1,26 +1,24 @@
"""The tests for the Conversation component.""" """The tests for the Conversation component."""
# pylint: disable=protected-access # pylint: disable=protected-access
import asyncio
import pytest import pytest
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.components import conversation from homeassistant.components import conversation
import homeassistant.components as component import homeassistant.components as component
from homeassistant.components.cover import (SERVICE_OPEN_COVER)
from homeassistant.helpers import intent from homeassistant.helpers import intent
from tests.common import async_mock_intent, async_mock_service from tests.common import async_mock_intent, async_mock_service
@asyncio.coroutine async def test_calling_intent(hass):
def test_calling_intent(hass):
"""Test calling an intent from a conversation.""" """Test calling an intent from a conversation."""
intents = async_mock_intent(hass, 'OrderBeer') intents = async_mock_intent(hass, 'OrderBeer')
result = yield from component.async_setup(hass, {}) result = await component.async_setup(hass, {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', { result = await async_setup_component(hass, 'conversation', {
'conversation': { 'conversation': {
'intents': { 'intents': {
'OrderBeer': [ 'OrderBeer': [
@ -31,11 +29,11 @@ def test_calling_intent(hass):
}) })
assert result assert result
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: 'I would like the Grolsch beer' conversation.ATTR_TEXT: 'I would like the Grolsch beer'
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(intents) == 1 assert len(intents) == 1
intent = intents[0] intent = intents[0]
@ -45,8 +43,7 @@ def test_calling_intent(hass):
assert intent.text_input == 'I would like the Grolsch beer' assert intent.text_input == 'I would like the Grolsch beer'
@asyncio.coroutine async def test_register_before_setup(hass):
def test_register_before_setup(hass):
"""Test calling an intent from a conversation.""" """Test calling an intent from a conversation."""
intents = async_mock_intent(hass, 'OrderBeer') intents = async_mock_intent(hass, 'OrderBeer')
@ -54,7 +51,7 @@ def test_register_before_setup(hass):
'A {type} beer, please' 'A {type} beer, please'
]) ])
result = yield from async_setup_component(hass, 'conversation', { result = await async_setup_component(hass, 'conversation', {
'conversation': { 'conversation': {
'intents': { 'intents': {
'OrderBeer': [ 'OrderBeer': [
@ -65,11 +62,11 @@ def test_register_before_setup(hass):
}) })
assert result assert result
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: 'A Grolsch beer, please' conversation.ATTR_TEXT: 'A Grolsch beer, please'
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(intents) == 1 assert len(intents) == 1
intent = intents[0] intent = intents[0]
@ -78,11 +75,11 @@ def test_register_before_setup(hass):
assert intent.slots == {'type': {'value': 'Grolsch'}} assert intent.slots == {'type': {'value': 'Grolsch'}}
assert intent.text_input == 'A Grolsch beer, please' assert intent.text_input == 'A Grolsch beer, please'
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: 'I would like the Grolsch beer' conversation.ATTR_TEXT: 'I would like the Grolsch beer'
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(intents) == 2 assert len(intents) == 2
intent = intents[1] intent = intents[1]
@ -92,14 +89,14 @@ def test_register_before_setup(hass):
assert intent.text_input == 'I would like the Grolsch beer' assert intent.text_input == 'I would like the Grolsch beer'
@asyncio.coroutine async def test_http_processing_intent(hass, test_client):
def test_http_processing_intent(hass, aiohttp_client):
"""Test processing intent via HTTP API.""" """Test processing intent via HTTP API."""
class TestIntentHandler(intent.IntentHandler): class TestIntentHandler(intent.IntentHandler):
"""Test Intent Handler."""
intent_type = 'OrderBeer' intent_type = 'OrderBeer'
@asyncio.coroutine async def async_handle(self, intent):
def async_handle(self, intent):
"""Handle the intent.""" """Handle the intent."""
response = intent.create_response() response = intent.create_response()
response.async_set_speech( response.async_set_speech(
@ -111,7 +108,7 @@ def test_http_processing_intent(hass, aiohttp_client):
intent.async_register(hass, TestIntentHandler()) intent.async_register(hass, TestIntentHandler())
result = yield from async_setup_component(hass, 'conversation', { result = await async_setup_component(hass, 'conversation', {
'conversation': { 'conversation': {
'intents': { 'intents': {
'OrderBeer': [ 'OrderBeer': [
@ -122,13 +119,13 @@ def test_http_processing_intent(hass, aiohttp_client):
}) })
assert result assert result
client = yield from aiohttp_client(hass.http.app) client = await test_client(hass.http.app)
resp = yield from client.post('/api/conversation/process', json={ resp = await client.post('/api/conversation/process', json={
'text': 'I would like the Grolsch beer' 'text': 'I would like the Grolsch beer'
}) })
assert resp.status == 200 assert resp.status == 200
data = yield from resp.json() data = await resp.json()
assert data == { assert data == {
'card': { 'card': {
@ -145,24 +142,23 @@ def test_http_processing_intent(hass, aiohttp_client):
} }
@asyncio.coroutine
@pytest.mark.parametrize('sentence', ('turn on kitchen', 'turn kitchen on')) @pytest.mark.parametrize('sentence', ('turn on kitchen', 'turn kitchen on'))
def test_turn_on_intent(hass, sentence): async def test_turn_on_intent(hass, sentence):
"""Test calling the turn on intent.""" """Test calling the turn on intent."""
result = yield from component.async_setup(hass, {}) result = await component.async_setup(hass, {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', {}) result = await async_setup_component(hass, 'conversation', {})
assert result assert result
hass.states.async_set('light.kitchen', 'off') hass.states.async_set('light.kitchen', 'off')
calls = async_mock_service(hass, 'homeassistant', 'turn_on') calls = async_mock_service(hass, 'homeassistant', 'turn_on')
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: sentence conversation.ATTR_TEXT: sentence
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
call = calls[0] call = calls[0]
@ -171,24 +167,49 @@ def test_turn_on_intent(hass, sentence):
assert call.data == {'entity_id': 'light.kitchen'} assert call.data == {'entity_id': 'light.kitchen'}
@asyncio.coroutine async def test_cover_intents_loading(hass):
@pytest.mark.parametrize('sentence', ('turn off kitchen', 'turn kitchen off')) """Test Cover Intents Loading."""
def test_turn_off_intent(hass, sentence): with pytest.raises(intent.UnknownIntent):
"""Test calling the turn on intent.""" await intent.async_handle(
result = yield from component.async_setup(hass, {}) hass, 'test', 'HassOpenCover', {'name': {'value': 'garage door'}}
)
result = await async_setup_component(hass, 'cover', {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', {}) hass.states.async_set('cover.garage_door', 'closed')
calls = async_mock_service(hass, 'cover', SERVICE_OPEN_COVER)
response = await intent.async_handle(
hass, 'test', 'HassOpenCover', {'name': {'value': 'garage door'}}
)
await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Opened garage door'
assert len(calls) == 1
call = calls[0]
assert call.domain == 'cover'
assert call.service == 'open_cover'
assert call.data == {'entity_id': 'cover.garage_door'}
@pytest.mark.parametrize('sentence', ('turn off kitchen', 'turn kitchen off'))
async def test_turn_off_intent(hass, sentence):
"""Test calling the turn on intent."""
result = await component.async_setup(hass, {})
assert result
result = await async_setup_component(hass, 'conversation', {})
assert result assert result
hass.states.async_set('light.kitchen', 'on') hass.states.async_set('light.kitchen', 'on')
calls = async_mock_service(hass, 'homeassistant', 'turn_off') calls = async_mock_service(hass, 'homeassistant', 'turn_off')
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: sentence conversation.ATTR_TEXT: sentence
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
call = calls[0] call = calls[0]
@ -197,24 +218,23 @@ def test_turn_off_intent(hass, sentence):
assert call.data == {'entity_id': 'light.kitchen'} assert call.data == {'entity_id': 'light.kitchen'}
@asyncio.coroutine
@pytest.mark.parametrize('sentence', ('toggle kitchen', 'kitchen toggle')) @pytest.mark.parametrize('sentence', ('toggle kitchen', 'kitchen toggle'))
def test_toggle_intent(hass, sentence): async def test_toggle_intent(hass, sentence):
"""Test calling the turn on intent.""" """Test calling the turn on intent."""
result = yield from component.async_setup(hass, {}) result = await component.async_setup(hass, {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', {}) result = await async_setup_component(hass, 'conversation', {})
assert result assert result
hass.states.async_set('light.kitchen', 'on') hass.states.async_set('light.kitchen', 'on')
calls = async_mock_service(hass, 'homeassistant', 'toggle') calls = async_mock_service(hass, 'homeassistant', 'toggle')
yield from hass.services.async_call( await hass.services.async_call(
'conversation', 'process', { 'conversation', 'process', {
conversation.ATTR_TEXT: sentence conversation.ATTR_TEXT: sentence
}) })
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
call = calls[0] call = calls[0]
@ -223,20 +243,19 @@ def test_toggle_intent(hass, sentence):
assert call.data == {'entity_id': 'light.kitchen'} assert call.data == {'entity_id': 'light.kitchen'}
@asyncio.coroutine async def test_http_api(hass, test_client):
def test_http_api(hass, aiohttp_client):
"""Test the HTTP conversation API.""" """Test the HTTP conversation API."""
result = yield from component.async_setup(hass, {}) result = await component.async_setup(hass, {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', {}) result = await async_setup_component(hass, 'conversation', {})
assert result assert result
client = yield from aiohttp_client(hass.http.app) client = await test_client(hass.http.app)
hass.states.async_set('light.kitchen', 'off') hass.states.async_set('light.kitchen', 'off')
calls = async_mock_service(hass, 'homeassistant', 'turn_on') calls = async_mock_service(hass, 'homeassistant', 'turn_on')
resp = yield from client.post('/api/conversation/process', json={ resp = await client.post('/api/conversation/process', json={
'text': 'Turn the kitchen on' 'text': 'Turn the kitchen on'
}) })
assert resp.status == 200 assert resp.status == 200
@ -248,23 +267,22 @@ def test_http_api(hass, aiohttp_client):
assert call.data == {'entity_id': 'light.kitchen'} assert call.data == {'entity_id': 'light.kitchen'}
@asyncio.coroutine async def test_http_api_wrong_data(hass, test_client):
def test_http_api_wrong_data(hass, aiohttp_client):
"""Test the HTTP conversation API.""" """Test the HTTP conversation API."""
result = yield from component.async_setup(hass, {}) result = await component.async_setup(hass, {})
assert result assert result
result = yield from async_setup_component(hass, 'conversation', {}) result = await async_setup_component(hass, 'conversation', {})
assert result assert result
client = yield from aiohttp_client(hass.http.app) client = await test_client(hass.http.app)
resp = yield from client.post('/api/conversation/process', json={ resp = await client.post('/api/conversation/process', json={
'text': 123 'text': 123
}) })
assert resp.status == 400 assert resp.status == 400
resp = yield from client.post('/api/conversation/process', json={ resp = await client.post('/api/conversation/process', json={
}) })
assert resp.status == 400 assert resp.status == 400

View file

@ -1,6 +1,5 @@
"""The tests for Core components.""" """The tests for Core components."""
# pylint: disable=protected-access # pylint: disable=protected-access
import asyncio
import unittest import unittest
from unittest.mock import patch, Mock from unittest.mock import patch, Mock
@ -75,9 +74,9 @@ class TestComponentsCore(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
self.assertEqual(1, len(calls)) self.assertEqual(1, len(calls))
@asyncio.coroutine
@patch('homeassistant.core.ServiceRegistry.call') @patch('homeassistant.core.ServiceRegistry.call')
def test_turn_on_to_not_block_for_domains_without_service(self, mock_call): async def test_turn_on_to_not_block_for_domains_without_service(self,
mock_call):
"""Test if turn_on is blocking domain with no service.""" """Test if turn_on is blocking domain with no service."""
async_mock_service(self.hass, 'light', SERVICE_TURN_ON) async_mock_service(self.hass, 'light', SERVICE_TURN_ON)
@ -88,7 +87,7 @@ class TestComponentsCore(unittest.TestCase):
'entity_id': ['light.test', 'sensor.bla', 'light.bla'] 'entity_id': ['light.test', 'sensor.bla', 'light.bla']
}) })
service = self.hass.services._services['homeassistant']['turn_on'] service = self.hass.services._services['homeassistant']['turn_on']
yield from service.func(service_call) await service.func(service_call)
self.assertEqual(2, mock_call.call_count) self.assertEqual(2, mock_call.call_count)
self.assertEqual( self.assertEqual(
@ -130,8 +129,8 @@ class TestComponentsCore(unittest.TestCase):
comps.reload_core_config(self.hass) comps.reload_core_config(self.hass)
self.hass.block_till_done() self.hass.block_till_done()
assert 10 == self.hass.config.latitude assert self.hass.config.latitude == 10
assert 20 == self.hass.config.longitude assert self.hass.config.longitude == 20
ent.schedule_update_ha_state() ent.schedule_update_ha_state()
self.hass.block_till_done() self.hass.block_till_done()
@ -198,19 +197,18 @@ class TestComponentsCore(unittest.TestCase):
assert not mock_stop.called assert not mock_stop.called
@asyncio.coroutine async def test_turn_on_intent(hass):
def test_turn_on_intent(hass):
"""Test HassTurnOn intent.""" """Test HassTurnOn intent."""
result = yield from comps.async_setup(hass, {}) result = await comps.async_setup(hass, {})
assert result assert result
hass.states.async_set('light.test_light', 'off') hass.states.async_set('light.test_light', 'off')
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
response = yield from intent.async_handle( response = await intent.async_handle(
hass, 'test', 'HassTurnOn', {'name': {'value': 'test light'}} hass, 'test', 'HassTurnOn', {'name': {'value': 'test light'}}
) )
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Turned test light on' assert response.speech['plain']['speech'] == 'Turned test light on'
assert len(calls) == 1 assert len(calls) == 1
@ -220,19 +218,18 @@ def test_turn_on_intent(hass):
assert call.data == {'entity_id': ['light.test_light']} assert call.data == {'entity_id': ['light.test_light']}
@asyncio.coroutine async def test_turn_off_intent(hass):
def test_turn_off_intent(hass):
"""Test HassTurnOff intent.""" """Test HassTurnOff intent."""
result = yield from comps.async_setup(hass, {}) result = await comps.async_setup(hass, {})
assert result assert result
hass.states.async_set('light.test_light', 'on') hass.states.async_set('light.test_light', 'on')
calls = async_mock_service(hass, 'light', SERVICE_TURN_OFF) calls = async_mock_service(hass, 'light', SERVICE_TURN_OFF)
response = yield from intent.async_handle( response = await intent.async_handle(
hass, 'test', 'HassTurnOff', {'name': {'value': 'test light'}} hass, 'test', 'HassTurnOff', {'name': {'value': 'test light'}}
) )
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Turned test light off' assert response.speech['plain']['speech'] == 'Turned test light off'
assert len(calls) == 1 assert len(calls) == 1
@ -242,19 +239,18 @@ def test_turn_off_intent(hass):
assert call.data == {'entity_id': ['light.test_light']} assert call.data == {'entity_id': ['light.test_light']}
@asyncio.coroutine async def test_toggle_intent(hass):
def test_toggle_intent(hass):
"""Test HassToggle intent.""" """Test HassToggle intent."""
result = yield from comps.async_setup(hass, {}) result = await comps.async_setup(hass, {})
assert result assert result
hass.states.async_set('light.test_light', 'off') hass.states.async_set('light.test_light', 'off')
calls = async_mock_service(hass, 'light', SERVICE_TOGGLE) calls = async_mock_service(hass, 'light', SERVICE_TOGGLE)
response = yield from intent.async_handle( response = await intent.async_handle(
hass, 'test', 'HassToggle', {'name': {'value': 'test light'}} hass, 'test', 'HassToggle', {'name': {'value': 'test light'}}
) )
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Toggled test light' assert response.speech['plain']['speech'] == 'Toggled test light'
assert len(calls) == 1 assert len(calls) == 1
@ -264,13 +260,12 @@ def test_toggle_intent(hass):
assert call.data == {'entity_id': ['light.test_light']} assert call.data == {'entity_id': ['light.test_light']}
@asyncio.coroutine async def test_turn_on_multiple_intent(hass):
def test_turn_on_multiple_intent(hass):
"""Test HassTurnOn intent with multiple similar entities. """Test HassTurnOn intent with multiple similar entities.
This tests that matching finds the proper entity among similar names. This tests that matching finds the proper entity among similar names.
""" """
result = yield from comps.async_setup(hass, {}) result = await comps.async_setup(hass, {})
assert result assert result
hass.states.async_set('light.test_light', 'off') hass.states.async_set('light.test_light', 'off')
@ -278,10 +273,10 @@ def test_turn_on_multiple_intent(hass):
hass.states.async_set('light.test_lighter', 'off') hass.states.async_set('light.test_lighter', 'off')
calls = async_mock_service(hass, 'light', SERVICE_TURN_ON) calls = async_mock_service(hass, 'light', SERVICE_TURN_ON)
response = yield from intent.async_handle( response = await intent.async_handle(
hass, 'test', 'HassTurnOn', {'name': {'value': 'test lights'}} hass, 'test', 'HassTurnOn', {'name': {'value': 'test lights'}}
) )
yield from hass.async_block_till_done() await hass.async_block_till_done()
assert response.speech['plain']['speech'] == 'Turned test lights 2 on' assert response.speech['plain']['speech'] == 'Turned test lights 2 on'
assert len(calls) == 1 assert len(calls) == 1