Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion homeassistant/helpers/intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ def async_validate_slots(self, slots):
if self._slot_schema is None:
self._slot_schema = vol.Schema({
key: SLOT_SCHEMA.extend({'value': validator})
for key, validator in self.slot_schema.items()})
for key, validator in self.slot_schema.items()},
extra=vol.ALLOW_EXTRA)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit surprised this was the fix, as SLOT_SCHEMA already had vol.ALLOW_EXTRAS set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SLOT_SCHEMA is the schema for one specific slot (e.g. name). This sets vol.ALLOW_EXTRAS to the schema of the parent object containing all slots.


return self._slot_schema(slots)

Expand Down
44 changes: 44 additions & 0 deletions tests/components/test_snips.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from homeassistant.bootstrap import async_setup_component
from homeassistant.components.mqtt import MQTT_PUBLISH_SCHEMA
import homeassistant.components.snips as snips
from homeassistant.helpers.intent import (ServiceIntentHandler, async_register)
from tests.common import (async_fire_mqtt_message, async_mock_intent,
async_mock_service)

Expand Down Expand Up @@ -124,6 +125,49 @@ async def test_snips_intent(hass, mqtt_mock):
assert intent.text_input == 'turn the lights green'


async def test_snips_service_intent(hass, mqtt_mock):
"""Test ServiceIntentHandler via Snips."""
hass.states.async_set('light.kitchen', 'off')
calls = async_mock_service(hass, 'light', 'turn_on')
result = await async_setup_component(hass, "snips", {
"snips": {},
})
assert result
payload = """
{
"input": "turn the light on",
"intent": {
"intentName": "Lights",
"probability": 0.85
},
"siteId": "default",
"slots": [
{
"slotName": "name",
"value": {
"kind": "Custom",
"value": "kitchen"
}
}
]
}
"""

async_register(hass, ServiceIntentHandler(
"Lights", "light", 'turn_on', "Turned {} on"))

async_fire_mqtt_message(hass, 'hermes/intent/Lights',
payload)
await hass.async_block_till_done()

assert len(calls) == 1
assert calls[0].domain == 'light'
assert calls[0].service == 'turn_on'
assert calls[0].data['entity_id'] == 'light.kitchen'
assert 'probability' not in calls[0].data
assert 'site_id' not in calls[0].data


async def test_snips_intent_with_duration(hass, mqtt_mock):
"""Test intent with Snips duration."""
result = await async_setup_component(hass, "snips", {
Expand Down
36 changes: 35 additions & 1 deletion tests/helpers/test_intent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
"""Tests for the intent helpers."""

import unittest
import voluptuous as vol

from homeassistant.core import State
from homeassistant.helpers import intent
from homeassistant.helpers import (intent, config_validation as cv)


class MockIntentHandler(intent.IntentHandler):
"""Provide a mock intent handler."""

def __init__(self, slot_schema):
"""Initialize the mock handler."""
self.slot_schema = slot_schema


def test_async_match_state():
Expand All @@ -10,3 +22,25 @@ def test_async_match_state():

state = intent.async_match_state(None, 'kitch', [state1, state2])
assert state is state1


class TestIntentHandler(unittest.TestCase):
"""Test the Home Assistant event helpers."""

def test_async_validate_slots(self):
"""Test async_validate_slots of IntentHandler."""
handler1 = MockIntentHandler({
vol.Required('name'): cv.string,
})

self.assertRaises(vol.error.MultipleInvalid,
handler1.async_validate_slots, {})
self.assertRaises(vol.error.MultipleInvalid,
handler1.async_validate_slots, {'name': 1})
self.assertRaises(vol.error.MultipleInvalid,
handler1.async_validate_slots, {'name': 'kitchen'})
handler1.async_validate_slots({'name': {'value': 'kitchen'}})
handler1.async_validate_slots({
'name': {'value': 'kitchen'},
'probability': {'value': '0.5'}
})