Only show Google Tasks that are parents and fix ordering (#103820)
parent
4096687112
commit
378a708bf7
|
@ -2,7 +2,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import cast
|
||||
from typing import Any, cast
|
||||
|
||||
from homeassistant.components.todo import (
|
||||
TodoItem,
|
||||
|
@ -96,7 +96,7 @@ class GoogleTaskTodoListEntity(
|
|||
item.get("status"), TodoItemStatus.NEEDS_ACTION # type: ignore[arg-type]
|
||||
),
|
||||
)
|
||||
for item in self.coordinator.data
|
||||
for item in _order_tasks(self.coordinator.data)
|
||||
]
|
||||
|
||||
async def async_create_todo_item(self, item: TodoItem) -> None:
|
||||
|
@ -121,3 +121,16 @@ class GoogleTaskTodoListEntity(
|
|||
"""Delete To-do items."""
|
||||
await self.coordinator.api.delete(self._task_list_id, uids)
|
||||
await self.coordinator.async_refresh()
|
||||
|
||||
|
||||
def _order_tasks(tasks: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
"""Order the task items response.
|
||||
|
||||
All tasks have an order amongst their sibblings based on position.
|
||||
|
||||
Home Assistant To-do items do not support the Google Task parent/sibbling
|
||||
relationships and the desired behavior is for them to be filtered.
|
||||
"""
|
||||
parents = [task for task in tasks if task.get("parent") is None]
|
||||
parents.sort(key=lambda task: task["position"])
|
||||
return parents
|
||||
|
|
|
@ -14,6 +14,30 @@
|
|||
'POST',
|
||||
)
|
||||
# ---
|
||||
# name: test_parent_child_ordering[api_responses0]
|
||||
list([
|
||||
dict({
|
||||
'status': 'needs_action',
|
||||
'summary': 'Task 1',
|
||||
'uid': 'task-1',
|
||||
}),
|
||||
dict({
|
||||
'status': 'needs_action',
|
||||
'summary': 'Task 2',
|
||||
'uid': 'task-2',
|
||||
}),
|
||||
dict({
|
||||
'status': 'needs_action',
|
||||
'summary': 'Task 3 (Parent)',
|
||||
'uid': 'task-3',
|
||||
}),
|
||||
dict({
|
||||
'status': 'needs_action',
|
||||
'summary': 'Task 4',
|
||||
'uid': 'task-4',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_partial_update_status[api_responses0]
|
||||
tuple(
|
||||
'https://tasks.googleapis.com/tasks/v1/lists/task-list-id-1/tasks/some-task-id?alt=json',
|
||||
|
|
|
@ -45,14 +45,34 @@ BOUNDARY = "batch_00972cc8-75bd-11ee-9692-0242ac110002" # Arbitrary uuid
|
|||
|
||||
LIST_TASKS_RESPONSE_WATER = {
|
||||
"items": [
|
||||
{"id": "some-task-id", "title": "Water", "status": "needsAction"},
|
||||
{
|
||||
"id": "some-task-id",
|
||||
"title": "Water",
|
||||
"status": "needsAction",
|
||||
"position": "00000000000000000001",
|
||||
},
|
||||
],
|
||||
}
|
||||
LIST_TASKS_RESPONSE_MULTIPLE = {
|
||||
"items": [
|
||||
{"id": "some-task-id-1", "title": "Water", "status": "needsAction"},
|
||||
{"id": "some-task-id-2", "title": "Milk", "status": "needsAction"},
|
||||
{"id": "some-task-id-3", "title": "Cheese", "status": "needsAction"},
|
||||
{
|
||||
"id": "some-task-id-2",
|
||||
"title": "Milk",
|
||||
"status": "needsAction",
|
||||
"position": "00000000000000000002",
|
||||
},
|
||||
{
|
||||
"id": "some-task-id-1",
|
||||
"title": "Water",
|
||||
"status": "needsAction",
|
||||
"position": "00000000000000000001",
|
||||
},
|
||||
{
|
||||
"id": "some-task-id-3",
|
||||
"title": "Cheese",
|
||||
"status": "needsAction",
|
||||
"position": "00000000000000000003",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -182,8 +202,18 @@ def mock_http_response(response_handler: list | Callable) -> Mock:
|
|||
LIST_TASK_LIST_RESPONSE,
|
||||
{
|
||||
"items": [
|
||||
{"id": "task-1", "title": "Task 1", "status": "needsAction"},
|
||||
{"id": "task-2", "title": "Task 2", "status": "completed"},
|
||||
{
|
||||
"id": "task-1",
|
||||
"title": "Task 1",
|
||||
"status": "needsAction",
|
||||
"position": "0000000000000001",
|
||||
},
|
||||
{
|
||||
"id": "task-2",
|
||||
"title": "Task 2",
|
||||
"status": "completed",
|
||||
"position": "0000000000000002",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
@ -541,7 +571,7 @@ async def test_partial_update_status(
|
|||
LIST_TASK_LIST_RESPONSE,
|
||||
LIST_TASKS_RESPONSE_MULTIPLE,
|
||||
[EMPTY_RESPONSE, EMPTY_RESPONSE, EMPTY_RESPONSE], # Delete batch
|
||||
LIST_TASKS_RESPONSE, # refresh after create
|
||||
LIST_TASKS_RESPONSE, # refresh after delete
|
||||
]
|
||||
)
|
||||
)
|
||||
|
@ -697,3 +727,72 @@ async def test_delete_server_error(
|
|||
target={"entity_id": "todo.my_tasks"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"api_responses",
|
||||
[
|
||||
[
|
||||
LIST_TASK_LIST_RESPONSE,
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "task-3-2",
|
||||
"title": "Child 2",
|
||||
"status": "needsAction",
|
||||
"parent": "task-3",
|
||||
"position": "0000000000000002",
|
||||
},
|
||||
{
|
||||
"id": "task-3",
|
||||
"title": "Task 3 (Parent)",
|
||||
"status": "needsAction",
|
||||
"position": "0000000000000003",
|
||||
},
|
||||
{
|
||||
"id": "task-2",
|
||||
"title": "Task 2",
|
||||
"status": "needsAction",
|
||||
"position": "0000000000000002",
|
||||
},
|
||||
{
|
||||
"id": "task-1",
|
||||
"title": "Task 1",
|
||||
"status": "needsAction",
|
||||
"position": "0000000000000001",
|
||||
},
|
||||
{
|
||||
"id": "task-3-1",
|
||||
"title": "Child 1",
|
||||
"status": "needsAction",
|
||||
"parent": "task-3",
|
||||
"position": "0000000000000001",
|
||||
},
|
||||
{
|
||||
"id": "task-4",
|
||||
"title": "Task 4",
|
||||
"status": "needsAction",
|
||||
"position": "0000000000000004",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
],
|
||||
)
|
||||
async def test_parent_child_ordering(
|
||||
hass: HomeAssistant,
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
ws_get_items: Callable[[], Awaitable[dict[str, str]]],
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test getting todo list items."""
|
||||
|
||||
assert await integration_setup()
|
||||
|
||||
state = hass.states.get("todo.my_tasks")
|
||||
assert state
|
||||
assert state.state == "4"
|
||||
|
||||
items = await ws_get_items()
|
||||
assert items == snapshot
|
||||
|
|
Loading…
Reference in New Issue