When using fuzzy matching to match entity names for intents, whichever entity is first is preferred in the case of equal matches. This leads to situations where entities with similar names (such as entities named for their area and then specific area location) may be used when the whole area is wanted. I ran into this with the my Phillips Hue lights. I have each individual light named such that its room is the first part of the name, and its location within the room after. So my living room has: Living Room West Living Room Northwest Living Room North Living Room Northeast I then have a group for the whole room: Living Room Because the group is the last of the entities, trying to adjust the whole room only activates one light, because all of the lights match equally well. By preferring the shortest of equal matches, we prefer keys that have the least amount of extra information, causing "Living Room" to match the group instead of an individual light.
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Tests for the intent helpers."""
|
|
|
|
import pytest
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.core import State
|
|
from homeassistant.helpers import config_validation as cv, intent
|
|
|
|
|
|
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():
|
|
"""Test async_match_state helper."""
|
|
state1 = State("light.kitchen", "on")
|
|
state2 = State("switch.kitchen", "on")
|
|
|
|
state = intent.async_match_state(None, "kitch", [state1, state2])
|
|
assert state is state1
|
|
|
|
|
|
def test_async_validate_slots():
|
|
"""Test async_validate_slots of IntentHandler."""
|
|
handler1 = MockIntentHandler({vol.Required("name"): cv.string})
|
|
|
|
with pytest.raises(vol.error.MultipleInvalid):
|
|
handler1.async_validate_slots({})
|
|
with pytest.raises(vol.error.MultipleInvalid):
|
|
handler1.async_validate_slots({"name": 1})
|
|
with pytest.raises(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"}}
|
|
)
|
|
|
|
|
|
def test_fuzzy_match():
|
|
"""Test _fuzzymatch."""
|
|
state1 = State("light.living_room_northwest", "off")
|
|
state2 = State("light.living_room_north", "off")
|
|
state3 = State("light.living_room_northeast", "off")
|
|
state4 = State("light.living_room_west", "off")
|
|
state5 = State("light.living_room", "off")
|
|
states = [state1, state2, state3, state4, state5]
|
|
|
|
state = intent._fuzzymatch("Living Room", states, lambda state: state.name)
|
|
assert state == state5
|
|
|
|
state = intent._fuzzymatch(
|
|
"Living Room Northwest", states, lambda state: state.name
|
|
)
|
|
assert state == state1
|