mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add the todo.get_items service (#103285)
This commit is contained in:
parent
bba2734a5c
commit
5f13faac76
@ -11,7 +11,7 @@ from homeassistant.components import frontend, websocket_api
|
||||
from homeassistant.components.websocket_api import ERR_NOT_FOUND, ERR_NOT_SUPPORTED
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, SupportsResponse
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
@ -58,7 +58,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
vol.Required("item"): vol.All(cv.string, vol.Length(min=1)),
|
||||
vol.Optional("rename"): vol.All(cv.string, vol.Length(min=1)),
|
||||
vol.Optional("status"): vol.In(
|
||||
{TodoItemStatus.NEEDS_ACTION, TodoItemStatus.COMPLETED}
|
||||
{TodoItemStatus.NEEDS_ACTION, TodoItemStatus.COMPLETED},
|
||||
),
|
||||
}
|
||||
),
|
||||
@ -77,6 +77,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
_async_remove_todo_items,
|
||||
required_features=[TodoListEntityFeature.DELETE_TODO_ITEM],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
"get_items",
|
||||
cv.make_entity_service_schema(
|
||||
{
|
||||
vol.Optional("status"): vol.All(
|
||||
cv.ensure_list,
|
||||
[vol.In({TodoItemStatus.NEEDS_ACTION, TodoItemStatus.COMPLETED})],
|
||||
),
|
||||
}
|
||||
),
|
||||
_async_get_todo_items,
|
||||
supports_response=SupportsResponse.ONLY,
|
||||
)
|
||||
|
||||
await component.async_setup(config)
|
||||
return True
|
||||
@ -258,3 +271,16 @@ async def _async_remove_todo_items(entity: TodoListEntity, call: ServiceCall) ->
|
||||
raise ValueError(f"Unable to find To-do item '{item}")
|
||||
uids.append(found.uid)
|
||||
await entity.async_delete_todo_items(uids=uids)
|
||||
|
||||
|
||||
async def _async_get_todo_items(
|
||||
entity: TodoListEntity, call: ServiceCall
|
||||
) -> dict[str, Any]:
|
||||
"""Return items in the To-do list."""
|
||||
return {
|
||||
"items": [
|
||||
dataclasses.asdict(item)
|
||||
for item in entity.todo_items or ()
|
||||
if not (statuses := call.data.get("status")) or item.status in statuses
|
||||
]
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
get_items:
|
||||
target:
|
||||
entity:
|
||||
domain: todo
|
||||
fields:
|
||||
status:
|
||||
example: "needs_action"
|
||||
default: needs_action
|
||||
selector:
|
||||
select:
|
||||
translation_key: status
|
||||
options:
|
||||
- needs_action
|
||||
- completed
|
||||
multiple: true
|
||||
add_item:
|
||||
target:
|
||||
entity:
|
||||
|
@ -6,6 +6,16 @@
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"get_items": {
|
||||
"name": "Get to-do list items",
|
||||
"description": "Get items on a to-do list.",
|
||||
"fields": {
|
||||
"status": {
|
||||
"name": "Status",
|
||||
"description": "Only return to-do items with the specified statuses. Returns not completed actions by default."
|
||||
}
|
||||
}
|
||||
},
|
||||
"add_item": {
|
||||
"name": "Add to-do list item",
|
||||
"description": "Add a new to-do list item.",
|
||||
|
@ -33,6 +33,16 @@ from tests.common import (
|
||||
from tests.typing import WebSocketGenerator
|
||||
|
||||
TEST_DOMAIN = "test"
|
||||
ITEM_1 = {
|
||||
"uid": "1",
|
||||
"summary": "Item #1",
|
||||
"status": "needs_action",
|
||||
}
|
||||
ITEM_2 = {
|
||||
"uid": "2",
|
||||
"summary": "Item #2",
|
||||
"status": "completed",
|
||||
}
|
||||
|
||||
|
||||
class MockFlow(ConfigFlow):
|
||||
@ -182,12 +192,63 @@ async def test_list_todo_items(
|
||||
assert resp.get("success")
|
||||
assert resp.get("result") == {
|
||||
"items": [
|
||||
{"summary": "Item #1", "uid": "1", "status": "needs_action"},
|
||||
{"summary": "Item #2", "uid": "2", "status": "completed"},
|
||||
ITEM_1,
|
||||
ITEM_2,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("service_data", "expected_items"),
|
||||
[
|
||||
({}, [ITEM_1, ITEM_2]),
|
||||
(
|
||||
[
|
||||
{"status": [TodoItemStatus.COMPLETED, TodoItemStatus.NEEDS_ACTION]},
|
||||
[ITEM_1, ITEM_2],
|
||||
]
|
||||
),
|
||||
(
|
||||
[
|
||||
{"status": [TodoItemStatus.NEEDS_ACTION]},
|
||||
[ITEM_1],
|
||||
]
|
||||
),
|
||||
(
|
||||
[
|
||||
{"status": [TodoItemStatus.COMPLETED]},
|
||||
[ITEM_2],
|
||||
]
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_get_items_service(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
test_entity: TodoListEntity,
|
||||
service_data: dict[str, Any],
|
||||
expected_items: list[dict[str, Any]],
|
||||
) -> None:
|
||||
"""Test listing items in a To-do list from a service call."""
|
||||
|
||||
await create_mock_platform(hass, [test_entity])
|
||||
|
||||
state = hass.states.get("todo.entity1")
|
||||
assert state
|
||||
assert state.state == "1"
|
||||
assert state.attributes == {"supported_features": 15}
|
||||
|
||||
result = await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"get_items",
|
||||
service_data,
|
||||
target={"entity_id": "todo.entity1"},
|
||||
blocking=True,
|
||||
return_response=True,
|
||||
)
|
||||
assert result == {"todo.entity1": {"items": expected_items}}
|
||||
|
||||
|
||||
async def test_unsupported_websocket(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
|
Loading…
x
Reference in New Issue
Block a user