From b4d0de9c0ff37a979a487b246935df210c4c3477 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:41:55 +0200 Subject: [PATCH] Improve type hints in conversation tests (#120306) --- .../conversation/test_default_agent.py | 104 ++++++++++-------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/tests/components/conversation/test_default_agent.py b/tests/components/conversation/test_default_agent.py index 511967e3a9c..dee7b4ca0ff 100644 --- a/tests/components/conversation/test_default_agent.py +++ b/tests/components/conversation/test_default_agent.py @@ -1,6 +1,7 @@ """Test for the default agent.""" from collections import defaultdict +from typing import Any from unittest.mock import AsyncMock, patch from hassil.recognize import Intent, IntentData, MatchEntity, RecognizeResult @@ -34,7 +35,7 @@ from tests.common import MockConfigEntry, async_mock_service @pytest.fixture -async def init_components(hass): +async def init_components(hass: HomeAssistant) -> None: """Initialize relevant components with empty configs.""" assert await async_setup_component(hass, "homeassistant", {}) assert await async_setup_component(hass, "conversation", {}) @@ -50,8 +51,9 @@ async def init_components(hass): {"entity_category": entity.EntityCategory.DIAGNOSTIC}, ], ) +@pytest.mark.usefixtures("init_components") async def test_hidden_entities_skipped( - hass: HomeAssistant, init_components, er_kwargs, entity_registry: er.EntityRegistry + hass: HomeAssistant, er_kwargs: dict[str, Any], entity_registry: er.EntityRegistry ) -> None: """Test we skip hidden entities.""" @@ -69,7 +71,8 @@ async def test_hidden_entities_skipped( assert result.response.error_code == intent.IntentResponseErrorCode.NO_VALID_TARGETS -async def test_exposed_domains(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_exposed_domains(hass: HomeAssistant) -> None: """Test that we can't interact with entities that aren't exposed.""" hass.states.async_set( "lock.front_door", "off", attributes={ATTR_FRIENDLY_NAME: "Front Door"} @@ -93,9 +96,9 @@ async def test_exposed_domains(hass: HomeAssistant, init_components) -> None: assert result.response.error_code == intent.IntentResponseErrorCode.NO_VALID_TARGETS +@pytest.mark.usefixtures("init_components") async def test_exposed_areas( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, @@ -160,10 +163,8 @@ async def test_exposed_areas( assert result.response.response_type == intent.IntentResponseType.QUERY_ANSWER -async def test_conversation_agent( - hass: HomeAssistant, - init_components, -) -> None: +@pytest.mark.usefixtures("init_components") +async def test_conversation_agent(hass: HomeAssistant) -> None: """Test DefaultAgent.""" agent = default_agent.async_get_default_agent(hass) with patch( @@ -209,9 +210,9 @@ async def test_expose_flag_automatically_set( } +@pytest.mark.usefixtures("init_components") async def test_unexposed_entities_skipped( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, entity_registry: er.EntityRegistry, ) -> None: @@ -262,7 +263,8 @@ async def test_unexposed_entities_skipped( assert result.response.matched_states[0].entity_id == exposed_light.entity_id -async def test_trigger_sentences(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_trigger_sentences(hass: HomeAssistant) -> None: """Test registering/unregistering/matching a few trigger sentences.""" trigger_sentences = ["It's party time", "It is time to party"] trigger_response = "Cowabunga!" @@ -303,9 +305,8 @@ async def test_trigger_sentences(hass: HomeAssistant, init_components) -> None: assert len(callback.mock_calls) == 0 -async def test_shopping_list_add_item( - hass: HomeAssistant, init_components, sl_setup -) -> None: +@pytest.mark.usefixtures("init_components", "sl_setup") +async def test_shopping_list_add_item(hass: HomeAssistant) -> None: """Test adding an item to the shopping list through the default agent.""" result = await conversation.async_converse( hass, "add apples to my shopping list", None, Context() @@ -316,7 +317,8 @@ async def test_shopping_list_add_item( } -async def test_nevermind_item(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_nevermind_item(hass: HomeAssistant) -> None: """Test HassNevermind intent through the default agent.""" result = await conversation.async_converse(hass, "nevermind", None, Context()) assert result.response.intent is not None @@ -326,9 +328,9 @@ async def test_nevermind_item(hass: HomeAssistant, init_components) -> None: assert not result.response.speech +@pytest.mark.usefixtures("init_components") async def test_device_area_context( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, @@ -465,7 +467,8 @@ async def test_device_area_context( } -async def test_error_no_device(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_device(hass: HomeAssistant) -> None: """Test error message when device/entity is missing.""" result = await conversation.async_converse( hass, "turn on missing entity", None, Context(), None @@ -479,7 +482,8 @@ async def test_error_no_device(hass: HomeAssistant, init_components) -> None: ) -async def test_error_no_area(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_area(hass: HomeAssistant) -> None: """Test error message when area is missing.""" result = await conversation.async_converse( hass, "turn on the lights in missing area", None, Context(), None @@ -493,7 +497,8 @@ async def test_error_no_area(hass: HomeAssistant, init_components) -> None: ) -async def test_error_no_floor(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_floor(hass: HomeAssistant) -> None: """Test error message when floor is missing.""" result = await conversation.async_converse( hass, "turn on all the lights on missing floor", None, Context(), None @@ -507,8 +512,9 @@ async def test_error_no_floor(hass: HomeAssistant, init_components) -> None: ) +@pytest.mark.usefixtures("init_components") async def test_error_no_device_in_area( - hass: HomeAssistant, init_components, area_registry: ar.AreaRegistry + hass: HomeAssistant, area_registry: ar.AreaRegistry ) -> None: """Test error message when area is missing a device/entity.""" area_kitchen = area_registry.async_get_or_create("kitchen_id") @@ -525,9 +531,8 @@ async def test_error_no_device_in_area( ) -async def test_error_no_domain( - hass: HomeAssistant, init_components, area_registry: ar.AreaRegistry -) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_domain(hass: HomeAssistant) -> None: """Test error message when no devices/entities exist for a domain.""" # We don't have a sentence for turning on all fans @@ -558,8 +563,9 @@ async def test_error_no_domain( ) +@pytest.mark.usefixtures("init_components") async def test_error_no_domain_in_area( - hass: HomeAssistant, init_components, area_registry: ar.AreaRegistry + hass: HomeAssistant, area_registry: ar.AreaRegistry ) -> None: """Test error message when no devices/entities for a domain exist in an area.""" area_kitchen = area_registry.async_get_or_create("kitchen_id") @@ -576,9 +582,9 @@ async def test_error_no_domain_in_area( ) +@pytest.mark.usefixtures("init_components") async def test_error_no_domain_in_floor( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, floor_registry: fr.FloorRegistry, ) -> None: @@ -618,7 +624,8 @@ async def test_error_no_domain_in_floor( ) -async def test_error_no_device_class(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_device_class(hass: HomeAssistant) -> None: """Test error message when no entities of a device class exist.""" # Create a cover entity that is not a window. # This ensures that the filtering below won't exit early because there are @@ -658,8 +665,9 @@ async def test_error_no_device_class(hass: HomeAssistant, init_components) -> No ) +@pytest.mark.usefixtures("init_components") async def test_error_no_device_class_in_area( - hass: HomeAssistant, init_components, area_registry: ar.AreaRegistry + hass: HomeAssistant, area_registry: ar.AreaRegistry ) -> None: """Test error message when no entities of a device class exist in an area.""" area_bedroom = area_registry.async_get_or_create("bedroom_id") @@ -676,7 +684,8 @@ async def test_error_no_device_class_in_area( ) -async def test_error_no_intent(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_intent(hass: HomeAssistant) -> None: """Test response with an intent match failure.""" with patch( "homeassistant.components.conversation.default_agent.recognize_all", @@ -696,8 +705,9 @@ async def test_error_no_intent(hass: HomeAssistant, init_components) -> None: ) +@pytest.mark.usefixtures("init_components") async def test_error_duplicate_names( - hass: HomeAssistant, init_components, entity_registry: er.EntityRegistry + hass: HomeAssistant, entity_registry: er.EntityRegistry ) -> None: """Test error message when multiple devices have the same name (or alias).""" kitchen_light_1 = entity_registry.async_get_or_create("light", "demo", "1234") @@ -747,9 +757,9 @@ async def test_error_duplicate_names( ) +@pytest.mark.usefixtures("init_components") async def test_error_duplicate_names_in_area( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, entity_registry: er.EntityRegistry, ) -> None: @@ -805,7 +815,8 @@ async def test_error_duplicate_names_in_area( ) -async def test_error_wrong_state(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_wrong_state(hass: HomeAssistant) -> None: """Test error message when no entities are in the correct state.""" assert await async_setup_component(hass, media_player.DOMAIN, {}) @@ -824,9 +835,8 @@ async def test_error_wrong_state(hass: HomeAssistant, init_components) -> None: assert result.response.speech["plain"]["speech"] == "Sorry, no device is playing" -async def test_error_feature_not_supported( - hass: HomeAssistant, init_components -) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_feature_not_supported(hass: HomeAssistant) -> None: """Test error message when no devices support a required feature.""" assert await async_setup_component(hass, media_player.DOMAIN, {}) @@ -849,7 +859,8 @@ async def test_error_feature_not_supported( ) -async def test_error_no_timer_support(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_no_timer_support(hass: HomeAssistant) -> None: """Test error message when a device does not support timers (no handler is registered).""" device_id = "test_device" @@ -866,7 +877,8 @@ async def test_error_no_timer_support(hass: HomeAssistant, init_components) -> N ) -async def test_error_timer_not_found(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_error_timer_not_found(hass: HomeAssistant) -> None: """Test error message when a timer cannot be matched.""" device_id = "test_device" @@ -888,9 +900,9 @@ async def test_error_timer_not_found(hass: HomeAssistant, init_components) -> No ) +@pytest.mark.usefixtures("init_components") async def test_error_multiple_timers_matched( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, device_registry: dr.DeviceRegistry, ) -> None: @@ -938,8 +950,9 @@ async def test_error_multiple_timers_matched( ) +@pytest.mark.usefixtures("init_components") async def test_no_states_matched_default_error( - hass: HomeAssistant, init_components, area_registry: ar.AreaRegistry + hass: HomeAssistant, area_registry: ar.AreaRegistry ) -> None: """Test default response when no states match and slots are missing.""" area_kitchen = area_registry.async_get_or_create("kitchen_id") @@ -966,9 +979,9 @@ async def test_no_states_matched_default_error( ) +@pytest.mark.usefixtures("init_components") async def test_empty_aliases( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, @@ -1031,7 +1044,8 @@ async def test_empty_aliases( assert floors.values[0].text_in.text == floor_1.name -async def test_all_domains_loaded(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_all_domains_loaded(hass: HomeAssistant) -> None: """Test that sentences for all domains are always loaded.""" # light domain is not loaded @@ -1050,9 +1064,9 @@ async def test_all_domains_loaded(hass: HomeAssistant, init_components) -> None: ) +@pytest.mark.usefixtures("init_components") async def test_same_named_entities_in_different_areas( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, entity_registry: er.EntityRegistry, ) -> None: @@ -1147,9 +1161,9 @@ async def test_same_named_entities_in_different_areas( assert result.response.response_type == intent.IntentResponseType.QUERY_ANSWER +@pytest.mark.usefixtures("init_components") async def test_same_aliased_entities_in_different_areas( hass: HomeAssistant, - init_components, area_registry: ar.AreaRegistry, entity_registry: er.EntityRegistry, ) -> None: @@ -1238,7 +1252,8 @@ async def test_same_aliased_entities_in_different_areas( assert result.response.response_type == intent.IntentResponseType.QUERY_ANSWER -async def test_device_id_in_handler(hass: HomeAssistant, init_components) -> None: +@pytest.mark.usefixtures("init_components") +async def test_device_id_in_handler(hass: HomeAssistant) -> None: """Test that the default agent passes device_id to intent handler.""" device_id = "test_device" @@ -1270,9 +1285,8 @@ async def test_device_id_in_handler(hass: HomeAssistant, init_components) -> Non assert handler.device_id == device_id -async def test_name_wildcard_lower_priority( - hass: HomeAssistant, init_components -) -> None: +@pytest.mark.usefixtures("init_components") +async def test_name_wildcard_lower_priority(hass: HomeAssistant) -> None: """Test that the default agent does not prioritize a {name} slot when it's a wildcard.""" class OrderBeerIntentHandler(intent.IntentHandler):