mirror of
https://github.com/home-assistant/core.git
synced 2025-08-30 09:51:37 +02:00
Improve test of WS command get_services (#150901)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
136
tests/components/websocket_api/snapshots/test_commands.ambr
Normal file
136
tests/components/websocket_api/snapshots/test_commands.ambr
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_get_services
|
||||||
|
dict({
|
||||||
|
'reload': dict({
|
||||||
|
'description': 'Reloads group configuration, entities, and notify services from YAML-configuration.',
|
||||||
|
'fields': dict({
|
||||||
|
}),
|
||||||
|
'name': 'Reload',
|
||||||
|
}),
|
||||||
|
'remove': dict({
|
||||||
|
'description': 'Removes a group.',
|
||||||
|
'fields': dict({
|
||||||
|
'object_id': dict({
|
||||||
|
'description': 'Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id].',
|
||||||
|
'example': 'test_group',
|
||||||
|
'name': 'Object ID',
|
||||||
|
'required': True,
|
||||||
|
'selector': dict({
|
||||||
|
'object': dict({
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'name': 'Remove',
|
||||||
|
}),
|
||||||
|
'set': dict({
|
||||||
|
'description': 'Creates/Updates a group.',
|
||||||
|
'fields': dict({
|
||||||
|
'add_entities': dict({
|
||||||
|
'description': 'List of members to be added to the group. Cannot be used in combination with `Entities` or `Remove entities`.',
|
||||||
|
'example': 'domain.entity_id1, domain.entity_id2',
|
||||||
|
'name': 'Add entities',
|
||||||
|
'selector': dict({
|
||||||
|
'entity': dict({
|
||||||
|
'multiple': True,
|
||||||
|
'reorder': False,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'all': dict({
|
||||||
|
'description': 'Enable this option if the group should only be used when all entities are in state `on`.',
|
||||||
|
'name': 'All',
|
||||||
|
'selector': dict({
|
||||||
|
'boolean': dict({
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'entities': dict({
|
||||||
|
'description': 'List of all members in the group. Cannot be used in combination with `Add entities` or `Remove entities`.',
|
||||||
|
'example': 'domain.entity_id1, domain.entity_id2',
|
||||||
|
'name': 'Entities',
|
||||||
|
'selector': dict({
|
||||||
|
'entity': dict({
|
||||||
|
'multiple': True,
|
||||||
|
'reorder': False,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'icon': dict({
|
||||||
|
'description': 'Name of the icon for the group.',
|
||||||
|
'example': 'mdi:camera',
|
||||||
|
'name': 'Icon',
|
||||||
|
'selector': dict({
|
||||||
|
'icon': dict({
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'name': dict({
|
||||||
|
'description': 'Name of the group.',
|
||||||
|
'example': 'My test group',
|
||||||
|
'name': 'Name',
|
||||||
|
'selector': dict({
|
||||||
|
'text': dict({
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'object_id': dict({
|
||||||
|
'description': 'Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id].',
|
||||||
|
'example': 'test_group',
|
||||||
|
'name': 'Object ID',
|
||||||
|
'required': True,
|
||||||
|
'selector': dict({
|
||||||
|
'text': dict({
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'remove_entities': dict({
|
||||||
|
'description': 'List of members to be removed from a group. Cannot be used in combination with `Entities` or `Add entities`.',
|
||||||
|
'example': 'domain.entity_id1, domain.entity_id2',
|
||||||
|
'name': 'Remove entities',
|
||||||
|
'selector': dict({
|
||||||
|
'entity': dict({
|
||||||
|
'multiple': True,
|
||||||
|
'reorder': False,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'name': 'Set',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_get_services.1
|
||||||
|
dict({
|
||||||
|
'set_default_level': dict({
|
||||||
|
'description': 'Translated description',
|
||||||
|
'fields': dict({
|
||||||
|
'level': dict({
|
||||||
|
'description': 'Field description',
|
||||||
|
'example': 'Field example',
|
||||||
|
'name': 'Field name',
|
||||||
|
'selector': dict({
|
||||||
|
'select': dict({
|
||||||
|
'options': list([
|
||||||
|
'debug',
|
||||||
|
'info',
|
||||||
|
'warning',
|
||||||
|
'error',
|
||||||
|
'fatal',
|
||||||
|
'critical',
|
||||||
|
]),
|
||||||
|
'translation_key': 'level',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'name': 'Translated name',
|
||||||
|
}),
|
||||||
|
'set_level': dict({
|
||||||
|
'description': '',
|
||||||
|
'fields': dict({
|
||||||
|
}),
|
||||||
|
'name': '',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
# ---
|
@@ -8,10 +8,13 @@ from typing import Any
|
|||||||
from unittest.mock import ANY, AsyncMock, Mock, patch
|
from unittest.mock import ANY, AsyncMock, Mock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import loader
|
from homeassistant import loader
|
||||||
from homeassistant.components.device_automation import toggle_entity
|
from homeassistant.components.device_automation import toggle_entity
|
||||||
|
from homeassistant.components.group import DOMAIN as DOMAIN_GROUP
|
||||||
|
from homeassistant.components.logger import DOMAIN as DOMAIN_LOGGER
|
||||||
from homeassistant.components.websocket_api import const
|
from homeassistant.components.websocket_api import const
|
||||||
from homeassistant.components.websocket_api.auth import (
|
from homeassistant.components.websocket_api.auth import (
|
||||||
TYPE_AUTH,
|
TYPE_AUTH,
|
||||||
@@ -34,7 +37,7 @@ from homeassistant.helpers.event import async_track_state_change_event
|
|||||||
from homeassistant.loader import Integration, async_get_integration
|
from homeassistant.loader import Integration, async_get_integration
|
||||||
from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component
|
from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component
|
||||||
from homeassistant.util.json import json_loads
|
from homeassistant.util.json import json_loads
|
||||||
from homeassistant.util.yaml.loader import parse_yaml
|
from homeassistant.util.yaml.loader import JSON_TYPE, parse_yaml
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
MockConfigEntry,
|
MockConfigEntry,
|
||||||
@@ -671,7 +674,9 @@ async def test_get_states(
|
|||||||
|
|
||||||
|
|
||||||
async def test_get_services(
|
async def test_get_services(
|
||||||
hass: HomeAssistant, websocket_client: MockHAClientWebSocket
|
hass: HomeAssistant,
|
||||||
|
websocket_client: MockHAClientWebSocket,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test get_services command."""
|
"""Test get_services command."""
|
||||||
assert ALL_SERVICE_DESCRIPTIONS_JSON_CACHE not in hass.data
|
assert ALL_SERVICE_DESCRIPTIONS_JSON_CACHE not in hass.data
|
||||||
@@ -686,16 +691,18 @@ async def test_get_services(
|
|||||||
assert msg == {"id": 2, "result": {}, "success": True, "type": "result"}
|
assert msg == {"id": 2, "result": {}, "success": True, "type": "result"}
|
||||||
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is old_cache
|
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is old_cache
|
||||||
|
|
||||||
# Load a service and check cache is updated
|
# Set up an integration that has services and check cache is updated
|
||||||
assert await async_setup_component(hass, "logger", {})
|
assert await async_setup_component(hass, DOMAIN_GROUP, {DOMAIN_GROUP: {}})
|
||||||
await websocket_client.send_json_auto_id({"type": "get_services"})
|
await websocket_client.send_json_auto_id({"type": "get_services"})
|
||||||
msg = await websocket_client.receive_json()
|
msg = await websocket_client.receive_json()
|
||||||
assert msg == {
|
assert msg == {
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"result": {"logger": {"set_default_level": ANY, "set_level": ANY}},
|
"result": {DOMAIN_GROUP: ANY},
|
||||||
"success": True,
|
"success": True,
|
||||||
"type": "result",
|
"type": "result",
|
||||||
}
|
}
|
||||||
|
group_services = msg["result"][DOMAIN_GROUP]
|
||||||
|
assert group_services == snapshot
|
||||||
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is not old_cache
|
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is not old_cache
|
||||||
|
|
||||||
# Check cache is reused
|
# Check cache is reused
|
||||||
@@ -704,12 +711,70 @@ async def test_get_services(
|
|||||||
msg = await websocket_client.receive_json()
|
msg = await websocket_client.receive_json()
|
||||||
assert msg == {
|
assert msg == {
|
||||||
"id": 4,
|
"id": 4,
|
||||||
"result": {"logger": {"set_default_level": ANY, "set_level": ANY}},
|
"result": {DOMAIN_GROUP: group_services},
|
||||||
"success": True,
|
"success": True,
|
||||||
"type": "result",
|
"type": "result",
|
||||||
}
|
}
|
||||||
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is old_cache
|
assert hass.data[ALL_SERVICE_DESCRIPTIONS_JSON_CACHE] is old_cache
|
||||||
|
|
||||||
|
# Set up an integration with legacy translations in services.yaml
|
||||||
|
def _load_services_file(hass: HomeAssistant, integration: Integration) -> JSON_TYPE:
|
||||||
|
return {
|
||||||
|
"set_default_level": {
|
||||||
|
"description": "Translated description",
|
||||||
|
"fields": {
|
||||||
|
"level": {
|
||||||
|
"description": "Field description",
|
||||||
|
"example": "Field example",
|
||||||
|
"name": "Field name",
|
||||||
|
"selector": {
|
||||||
|
"select": {
|
||||||
|
"options": [
|
||||||
|
"debug",
|
||||||
|
"info",
|
||||||
|
"warning",
|
||||||
|
"error",
|
||||||
|
"fatal",
|
||||||
|
"critical",
|
||||||
|
],
|
||||||
|
"translation_key": "level",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "Translated name",
|
||||||
|
},
|
||||||
|
"set_level": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
await async_setup_component(hass, DOMAIN_LOGGER, {DOMAIN_LOGGER: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.service._load_services_file",
|
||||||
|
side_effect=_load_services_file,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.service.translation.async_get_translations",
|
||||||
|
return_value={},
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await websocket_client.send_json_auto_id({"type": "get_services"})
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
|
||||||
|
assert msg == {
|
||||||
|
"id": 5,
|
||||||
|
"result": {
|
||||||
|
DOMAIN_LOGGER: ANY,
|
||||||
|
DOMAIN_GROUP: group_services,
|
||||||
|
},
|
||||||
|
"success": True,
|
||||||
|
"type": "result",
|
||||||
|
}
|
||||||
|
logger_services = msg["result"][DOMAIN_LOGGER]
|
||||||
|
assert logger_services == snapshot
|
||||||
|
|
||||||
|
|
||||||
@patch("annotatedyaml.loader.load_yaml")
|
@patch("annotatedyaml.loader.load_yaml")
|
||||||
@patch.object(Integration, "has_conditions", return_value=True)
|
@patch.object(Integration, "has_conditions", return_value=True)
|
||||||
|
Reference in New Issue
Block a user