core/tests/components/test_snips.py

293 lines
8.3 KiB
Python

"""Test the Snips component."""
import asyncio
import json
import logging
from homeassistant.core import callback
from homeassistant.bootstrap import async_setup_component
from tests.common import (async_fire_mqtt_message, async_mock_intent,
async_mock_service)
from homeassistant.components.snips import (SERVICE_SCHEMA_SAY,
SERVICE_SCHEMA_SAY_ACTION)
@asyncio.coroutine
def test_snips_intent(hass, mqtt_mock):
"""Test intent via Snips."""
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "turn the lights green",
"intent": {
"intentName": "Lights",
"probability": 1
},
"slots": [
{
"slotName": "light_color",
"value": {
"kind": "Custom",
"value": "green"
}
}
]
}
"""
intents = async_mock_intent(hass, 'Lights')
async_fire_mqtt_message(hass, 'hermes/intent/Lights',
payload)
yield from hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == 'snips'
assert intent.intent_type == 'Lights'
assert intent.slots == {'light_color': {'value': 'green'}}
assert intent.text_input == 'turn the lights green'
@asyncio.coroutine
def test_snips_intent_with_duration(hass, mqtt_mock):
"""Test intent with Snips duration."""
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "set a timer of five minutes",
"intent": {
"intentName": "SetTimer"
},
"slots": [
{
"rawValue": "five minutes",
"value": {
"kind": "Duration",
"years": 0,
"quarters": 0,
"months": 0,
"weeks": 0,
"days": 0,
"hours": 0,
"minutes": 5,
"seconds": 0,
"precision": "Exact"
},
"range": {
"start": 15,
"end": 27
},
"entity": "snips/duration",
"slotName": "timer_duration"
}
]
}
"""
intents = async_mock_intent(hass, 'SetTimer')
async_fire_mqtt_message(hass, 'hermes/intent/SetTimer',
payload)
yield from hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == 'snips'
assert intent.intent_type == 'SetTimer'
assert intent.slots == {'timer_duration': {'value': 300}}
@asyncio.coroutine
def test_intent_speech_response(hass, mqtt_mock):
"""Test intent speech response via Snips."""
event = 'call_service'
events = []
@callback
def record_event(event):
"""Add recorded event to set."""
events.append(event)
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
result = yield from async_setup_component(hass, "intent_script", {
"intent_script": {
"spokenIntent": {
"speech": {
"type": "plain",
"text": "I am speaking to you"
}
}
}
})
assert result
payload = """
{
"input": "speak to me",
"sessionId": "abcdef0123456789",
"intent": {
"intentName": "spokenIntent"
},
"slots": []
}
"""
hass.bus.async_listen(event, record_event)
async_fire_mqtt_message(hass, 'hermes/intent/spokenIntent',
payload)
yield from hass.async_block_till_done()
assert len(events) == 1
assert events[0].data['domain'] == 'mqtt'
assert events[0].data['service'] == 'publish'
payload = json.loads(events[0].data['service_data']['payload'])
topic = events[0].data['service_data']['topic']
assert payload['sessionId'] == 'abcdef0123456789'
assert payload['text'] == 'I am speaking to you'
assert topic == 'hermes/dialogueManager/endSession'
@asyncio.coroutine
def test_unknown_intent(hass, mqtt_mock, caplog):
"""Test unknown intent."""
caplog.set_level(logging.WARNING)
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "I don't know what I am supposed to do",
"sessionId": "abcdef1234567890",
"intent": {
"intentName": "unknownIntent"
},
"slots": []
}
"""
async_fire_mqtt_message(hass,
'hermes/intent/unknownIntent', payload)
yield from hass.async_block_till_done()
assert 'Received unknown intent unknownIntent' in caplog.text
@asyncio.coroutine
def test_snips_intent_user(hass, mqtt_mock):
"""Test intentName format user_XXX__intentName."""
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "what to do",
"intent": {
"intentName": "user_ABCDEF123__Lights"
},
"slots": []
}
"""
intents = async_mock_intent(hass, 'Lights')
async_fire_mqtt_message(hass, 'hermes/intent/user_ABCDEF123__Lights',
payload)
yield from hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == 'snips'
assert intent.intent_type == 'Lights'
@asyncio.coroutine
def test_snips_intent_username(hass, mqtt_mock):
"""Test intentName format username:intentName."""
result = yield from async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "what to do",
"intent": {
"intentName": "username:Lights"
},
"slots": []
}
"""
intents = async_mock_intent(hass, 'Lights')
async_fire_mqtt_message(hass, 'hermes/intent/username:Lights',
payload)
yield from hass.async_block_till_done()
assert len(intents) == 1
intent = intents[0]
assert intent.platform == 'snips'
assert intent.intent_type == 'Lights'
@asyncio.coroutine
def test_snips_say(hass, caplog):
"""Test snips say with invalid config."""
calls = async_mock_service(hass, 'snips', 'say',
SERVICE_SCHEMA_SAY)
data = {'text': 'Hello'}
yield from hass.services.async_call('snips', 'say', data)
yield from hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == 'snips'
assert calls[0].service == 'say'
assert calls[0].data['text'] == 'Hello'
@asyncio.coroutine
def test_snips_say_action(hass, caplog):
"""Test snips say_action with invalid config."""
calls = async_mock_service(hass, 'snips', 'say_action',
SERVICE_SCHEMA_SAY_ACTION)
data = {'text': 'Hello', 'intent_filter': ['myIntent']}
yield from hass.services.async_call('snips', 'say_action', data)
yield from hass.async_block_till_done()
assert len(calls) == 1
assert calls[0].domain == 'snips'
assert calls[0].service == 'say_action'
assert calls[0].data['text'] == 'Hello'
assert calls[0].data['intent_filter'] == ['myIntent']
@asyncio.coroutine
def test_snips_say_invalid_config(hass, caplog):
"""Test snips say with invalid config."""
calls = async_mock_service(hass, 'snips', 'say',
SERVICE_SCHEMA_SAY)
data = {'text': 'Hello', 'badKey': 'boo'}
yield from hass.services.async_call('snips', 'say', data)
yield from hass.async_block_till_done()
assert len(calls) == 0
assert 'ERROR' in caplog.text
assert 'Invalid service data' in caplog.text
@asyncio.coroutine
def test_snips_say_action_invalid_config(hass, caplog):
"""Test snips say_action with invalid config."""
calls = async_mock_service(hass, 'snips', 'say_action',
SERVICE_SCHEMA_SAY_ACTION)
data = {'text': 'Hello', 'can_be_enqueued': 'notabool'}
yield from hass.services.async_call('snips', 'say_action', data)
yield from hass.async_block_till_done()
assert len(calls) == 0
assert 'ERROR' in caplog.text
assert 'Invalid service data' in caplog.text