Only show Google Tasks that are parents and fix ordering (#103820)

pull/103888/head
Allen Porter 2023-11-24 03:54:49 -08:00 committed by GitHub
parent 4096687112
commit 378a708bf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 145 additions and 9 deletions

View File

@ -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

View File

@ -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',

View File

@ -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