diff --git a/homeassistant/components/conversation/default_agent.py b/homeassistant/components/conversation/default_agent.py index d5454883292..7bb2c2182b3 100644 --- a/homeassistant/components/conversation/default_agent.py +++ b/homeassistant/components/conversation/default_agent.py @@ -429,8 +429,15 @@ class DefaultAgent(ConversationEntity): intent_context=intent_context, language=language, ): - if ("name" in result.entities) and ( - not result.entities["name"].is_wildcard + # Prioritize results with a "name" slot, but still prefer ones with + # more literal text matched. + if ( + ("name" in result.entities) + and (not result.entities["name"].is_wildcard) + and ( + (name_result is None) + or (result.text_chunks_matched > name_result.text_chunks_matched) + ) ): name_result = result diff --git a/tests/components/conversation/test_default_agent_intents.py b/tests/components/conversation/test_default_agent_intents.py index f5050f4483e..b1c4a6d51af 100644 --- a/tests/components/conversation/test_default_agent_intents.py +++ b/tests/components/conversation/test_default_agent_intents.py @@ -1,5 +1,7 @@ """Test intents for the default agent.""" +from unittest.mock import patch + import pytest from homeassistant.components import ( @@ -7,6 +9,7 @@ from homeassistant.components import ( cover, light, media_player, + todo, vacuum, valve, ) @@ -35,6 +38,27 @@ from homeassistant.setup import async_setup_component from tests.common import async_mock_service +class MockTodoListEntity(todo.TodoListEntity): + """Test todo list entity.""" + + def __init__(self, items: list[todo.TodoItem] | None = None) -> None: + """Initialize entity.""" + self._attr_todo_items = items or [] + + @property + def items(self) -> list[todo.TodoItem]: + """Return the items in the To-do list.""" + return self._attr_todo_items + + async def async_create_todo_item(self, item: todo.TodoItem) -> None: + """Add an item to the To-do list.""" + self._attr_todo_items.append(item) + + async def async_delete_todo_items(self, uids: list[str]) -> None: + """Delete an item in the To-do list.""" + self._attr_todo_items = [item for item in self.items if item.uid not in uids] + + @pytest.fixture async def init_components(hass: HomeAssistant): """Initialize relevant components with empty configs.""" @@ -365,3 +389,27 @@ async def test_turn_floor_lights_on_off( assert {s.entity_id for s in result.response.matched_states} == { bedroom_light.entity_id } + + +async def test_todo_add_item_fr( + hass: HomeAssistant, + init_components, +) -> None: + """Test that wildcard matches prioritize results with more literal text matched.""" + assert await async_setup_component(hass, todo.DOMAIN, {}) + hass.states.async_set("todo.liste_des_courses", 0, {}) + + with ( + patch.object(hass.config, "language", "fr"), + patch( + "homeassistant.components.todo.intent.ListAddItemIntent.async_handle", + return_value=intent.IntentResponse(hass.config.language), + ) as mock_handle, + ): + await conversation.async_converse( + hass, "Ajoute de la farine a la liste des courses", None, Context(), None + ) + mock_handle.assert_called_once() + assert mock_handle.call_args.args + intent_obj = mock_handle.call_args.args[0] + assert intent_obj.slots.get("item", {}).get("value", "").strip() == "farine"