diff --git a/homeassistant/core.py b/homeassistant/core.py index 252abdb28d4d..60485a678b08 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1726,6 +1726,8 @@ class ServiceCall: class ServiceRegistry: """Offer the services over the eventbus.""" + __slots__ = ("_services", "_hass") + def __init__(self, hass: HomeAssistant) -> None: """Initialize a service registry.""" self._services: dict[str, dict[str, Service]] = {} diff --git a/tests/components/google_assistant/test_smart_home.py b/tests/components/google_assistant/test_smart_home.py index 849f9e38a68b..f471e6f862c5 100644 --- a/tests/components/google_assistant/test_smart_home.py +++ b/tests/components/google_assistant/test_smart_home.py @@ -1,7 +1,7 @@ """Test Google Smart Home.""" import asyncio from types import SimpleNamespace -from unittest.mock import ANY, call, patch +from unittest.mock import ANY, patch import pytest from pytest_unordered import unordered @@ -488,76 +488,41 @@ async def test_execute( events = async_capture_events(hass, EVENT_COMMAND_RECEIVED) service_events = async_capture_events(hass, EVENT_CALL_SERVICE) - with patch.object( - hass.services, "async_call", wraps=hass.services.async_call - ) as call_service_mock: - result = await sh.async_handle_message( - hass, - MockConfig(should_report_state=report_state), - None, - { - "requestId": REQ_ID, - "inputs": [ - { - "intent": "action.devices.EXECUTE", - "payload": { - "commands": [ - { - "devices": [ - {"id": "light.non_existing"}, - {"id": "light.ceiling_lights"}, - {"id": "light.kitchen_lights"}, - ], - "execution": [ - { - "command": "action.devices.commands.OnOff", - "params": {"on": True}, - }, - { - "command": "action.devices.commands.BrightnessAbsolute", - "params": {"brightness": 20}, - }, - ], - } - ] - }, - } - ], - }, - const.SOURCE_CLOUD, - ) - assert call_service_mock.call_count == 4 - expected_calls = [ - call( - "light", - "turn_on", - {"entity_id": "light.ceiling_lights"}, - blocking=not report_state, - context=ANY, - ), - call( - "light", - "turn_on", - {"entity_id": "light.kitchen_lights"}, - blocking=not report_state, - context=ANY, - ), - call( - "light", - "turn_on", - {"entity_id": "light.ceiling_lights", "brightness_pct": 20}, - blocking=not report_state, - context=ANY, - ), - call( - "light", - "turn_on", - {"entity_id": "light.kitchen_lights", "brightness_pct": 20}, - blocking=not report_state, - context=ANY, - ), - ] - call_service_mock.assert_has_awaits(expected_calls, any_order=True) + result = await sh.async_handle_message( + hass, + MockConfig(should_report_state=report_state), + None, + { + "requestId": REQ_ID, + "inputs": [ + { + "intent": "action.devices.EXECUTE", + "payload": { + "commands": [ + { + "devices": [ + {"id": "light.non_existing"}, + {"id": "light.ceiling_lights"}, + {"id": "light.kitchen_lights"}, + ], + "execution": [ + { + "command": "action.devices.commands.OnOff", + "params": {"on": True}, + }, + { + "command": "action.devices.commands.BrightnessAbsolute", + "params": {"brightness": 20}, + }, + ], + } + ] + }, + } + ], + }, + const.SOURCE_CLOUD, + ) await hass.async_block_till_done() assert result == { @@ -682,11 +647,7 @@ async def test_execute_times_out( # Make DemoLigt.async_turn_on hang waiting for the turn_on_wait event await turn_on_wait.wait() - with patch.object( - hass.services, "async_call", wraps=hass.services.async_call - ) as call_service_mock, patch.object( - DemoLight, "async_turn_on", wraps=slow_turn_on - ): + with patch.object(DemoLight, "async_turn_on", wraps=slow_turn_on): result = await sh.async_handle_message( hass, MockConfig(should_report_state=report_state), @@ -722,51 +683,10 @@ async def test_execute_times_out( }, const.SOURCE_CLOUD, ) - # Only the two first calls are executed - assert call_service_mock.call_count == 2 - expected_calls = [ - call( - "light", - "turn_on", - {"entity_id": "light.ceiling_lights"}, - blocking=not report_state, - context=ANY, - ), - call( - "light", - "turn_on", - {"entity_id": "light.kitchen_lights"}, - blocking=not report_state, - context=ANY, - ), - ] - call_service_mock.assert_has_awaits(expected_calls, any_order=True) turn_on_wait.set() await hass.async_block_till_done() await hass.async_block_till_done() - # The remaining two calls should now have executed - assert call_service_mock.call_count == 4 - expected_calls.extend( - [ - call( - "light", - "turn_on", - {"entity_id": "light.ceiling_lights", "brightness_pct": 20}, - blocking=not report_state, - context=ANY, - ), - call( - "light", - "turn_on", - {"entity_id": "light.kitchen_lights", "brightness_pct": 20}, - blocking=not report_state, - context=ANY, - ), - ] - ) - call_service_mock.assert_has_awaits(expected_calls, any_order=True) - await hass.async_block_till_done() assert result == { "requestId": REQ_ID, diff --git a/tests/components/group/test_light.py b/tests/components/group/test_light.py index f50d4486b395..539a8c61414f 100644 --- a/tests/components/group/test_light.py +++ b/tests/components/group/test_light.py @@ -1,5 +1,4 @@ """The tests for the Group Light platform.""" -import unittest.mock from unittest.mock import MagicMock, patch import async_timeout @@ -16,7 +15,6 @@ from homeassistant.components.light import ( ATTR_COLOR_TEMP_KELVIN, ATTR_EFFECT, ATTR_EFFECT_LIST, - ATTR_FLASH, ATTR_HS_COLOR, ATTR_MAX_COLOR_TEMP_KELVIN, ATTR_MIN_COLOR_TEMP_KELVIN, @@ -26,7 +24,6 @@ from homeassistant.components.light import ( ATTR_SUPPORTED_COLOR_MODES, ATTR_TRANSITION, ATTR_WHITE, - ATTR_XY_COLOR, DOMAIN as LIGHT_DOMAIN, SERVICE_TOGGLE, SERVICE_TURN_OFF, @@ -39,16 +36,17 @@ from homeassistant.components.light import ( from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, + EVENT_CALL_SERVICE, STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component -from tests.common import get_fixture_path +from tests.common import async_capture_events, get_fixture_path async def test_default_state(hass: HomeAssistant) -> None: @@ -1443,6 +1441,7 @@ async def test_invalid_service_calls(hass: HomeAssistant) -> None: await group.async_setup_platform( hass, {"name": "test", "entities": ["light.test1", "light.test2"]}, add_entities ) + await async_setup_component(hass, "light", {}) await hass.async_block_till_done() await hass.async_start() await hass.async_block_till_done() @@ -1451,35 +1450,38 @@ async def test_invalid_service_calls(hass: HomeAssistant) -> None: grouped_light = add_entities.call_args[0][0][0] grouped_light.hass = hass - with unittest.mock.patch.object(hass.services, "async_call") as mock_call: - await grouped_light.async_turn_on(brightness=150, four_oh_four="404") - data = {ATTR_ENTITY_ID: ["light.test1", "light.test2"], ATTR_BRIGHTNESS: 150} - mock_call.assert_called_once_with( - LIGHT_DOMAIN, SERVICE_TURN_ON, data, blocking=True, context=None - ) - mock_call.reset_mock() + service_call_events = async_capture_events(hass, EVENT_CALL_SERVICE) - await grouped_light.async_turn_off(transition=4, four_oh_four="404") - data = {ATTR_ENTITY_ID: ["light.test1", "light.test2"], ATTR_TRANSITION: 4} - mock_call.assert_called_once_with( - LIGHT_DOMAIN, SERVICE_TURN_OFF, data, blocking=True, context=None - ) - mock_call.reset_mock() + await grouped_light.async_turn_on(brightness=150, four_oh_four="404") + data = {ATTR_ENTITY_ID: ["light.test1", "light.test2"], ATTR_BRIGHTNESS: 150} + assert len(service_call_events) == 1 + service_event_call: Event = service_call_events[0] + assert service_event_call.data["domain"] == LIGHT_DOMAIN + assert service_event_call.data["service"] == SERVICE_TURN_ON + assert service_event_call.data["service_data"] == data + service_call_events.clear() - data = { - ATTR_BRIGHTNESS: 150, - ATTR_XY_COLOR: (0.5, 0.42), - ATTR_RGB_COLOR: (80, 120, 50), - ATTR_COLOR_TEMP_KELVIN: 1234, - ATTR_EFFECT: "Sunshine", - ATTR_TRANSITION: 4, - ATTR_FLASH: "long", - } - await grouped_light.async_turn_on(**data) - data[ATTR_ENTITY_ID] = ["light.test1", "light.test2"] - mock_call.assert_called_once_with( - LIGHT_DOMAIN, SERVICE_TURN_ON, data, blocking=True, context=None - ) + await grouped_light.async_turn_off(transition=4, four_oh_four="404") + data = {ATTR_ENTITY_ID: ["light.test1", "light.test2"], ATTR_TRANSITION: 4} + assert len(service_call_events) == 1 + service_event_call: Event = service_call_events[0] + assert service_event_call.data["domain"] == LIGHT_DOMAIN + assert service_event_call.data["service"] == SERVICE_TURN_OFF + assert service_event_call.data["service_data"] == data + service_call_events.clear() + + data = { + ATTR_BRIGHTNESS: 150, + ATTR_COLOR_TEMP_KELVIN: 1234, + ATTR_TRANSITION: 4, + } + await grouped_light.async_turn_on(**data) + data[ATTR_ENTITY_ID] = ["light.test1", "light.test2"] + service_event_call: Event = service_call_events[0] + assert service_event_call.data["domain"] == LIGHT_DOMAIN + assert service_event_call.data["service"] == SERVICE_TURN_ON + assert service_event_call.data["service_data"] == data + service_call_events.clear() async def test_reload(hass: HomeAssistant) -> None: diff --git a/tests/components/vesync/test_init.py b/tests/components/vesync/test_init.py index 0f77c9cbf35e..c643e2bda198 100644 --- a/tests/components/vesync/test_init.py +++ b/tests/components/vesync/test_init.py @@ -33,15 +33,12 @@ async def test_async_setup_entry__not_login( hass.config_entries, "async_forward_entry_setup" ) as setup_mock, patch( "homeassistant.components.vesync.async_process_devices" - ) as process_mock, patch.object( - hass.services, "async_register" - ) as register_mock: + ) as process_mock: assert not await async_setup_entry(hass, config_entry) await hass.async_block_till_done() assert setups_mock.call_count == 0 assert setup_mock.call_count == 0 assert process_mock.call_count == 0 - assert register_mock.call_count == 0 assert manager.login.call_count == 1 assert DOMAIN not in hass.data diff --git a/tests/components/zha/conftest.py b/tests/components/zha/conftest.py index 271108496b21..e3a12703640f 100644 --- a/tests/components/zha/conftest.py +++ b/tests/components/zha/conftest.py @@ -332,8 +332,8 @@ def zha_device_mock( @pytest.fixture def hass_disable_services(hass): - """Mock service register.""" - with patch.object(hass.services, "async_register"), patch.object( - hass.services, "has_service", return_value=True + """Mock services.""" + with patch.object( + hass, "services", MagicMock(has_service=MagicMock(return_value=True)) ): yield hass