Only show Google Tasks that are parents and fix ordering (#103820)
parent
4096687112
commit
378a708bf7
|
@ -2,7 +2,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from homeassistant.components.todo import (
|
from homeassistant.components.todo import (
|
||||||
TodoItem,
|
TodoItem,
|
||||||
|
@ -96,7 +96,7 @@ class GoogleTaskTodoListEntity(
|
||||||
item.get("status"), TodoItemStatus.NEEDS_ACTION # type: ignore[arg-type]
|
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:
|
async def async_create_todo_item(self, item: TodoItem) -> None:
|
||||||
|
@ -121,3 +121,16 @@ class GoogleTaskTodoListEntity(
|
||||||
"""Delete To-do items."""
|
"""Delete To-do items."""
|
||||||
await self.coordinator.api.delete(self._task_list_id, uids)
|
await self.coordinator.api.delete(self._task_list_id, uids)
|
||||||
await self.coordinator.async_refresh()
|
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',
|
'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]
|
# name: test_partial_update_status[api_responses0]
|
||||||
tuple(
|
tuple(
|
||||||
'https://tasks.googleapis.com/tasks/v1/lists/task-list-id-1/tasks/some-task-id?alt=json',
|
'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 = {
|
LIST_TASKS_RESPONSE_WATER = {
|
||||||
"items": [
|
"items": [
|
||||||
{"id": "some-task-id", "title": "Water", "status": "needsAction"},
|
{
|
||||||
|
"id": "some-task-id",
|
||||||
|
"title": "Water",
|
||||||
|
"status": "needsAction",
|
||||||
|
"position": "00000000000000000001",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
LIST_TASKS_RESPONSE_MULTIPLE = {
|
LIST_TASKS_RESPONSE_MULTIPLE = {
|
||||||
"items": [
|
"items": [
|
||||||
{"id": "some-task-id-1", "title": "Water", "status": "needsAction"},
|
{
|
||||||
{"id": "some-task-id-2", "title": "Milk", "status": "needsAction"},
|
"id": "some-task-id-2",
|
||||||
{"id": "some-task-id-3", "title": "Cheese", "status": "needsAction"},
|
"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,
|
LIST_TASK_LIST_RESPONSE,
|
||||||
{
|
{
|
||||||
"items": [
|
"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_TASK_LIST_RESPONSE,
|
||||||
LIST_TASKS_RESPONSE_MULTIPLE,
|
LIST_TASKS_RESPONSE_MULTIPLE,
|
||||||
[EMPTY_RESPONSE, EMPTY_RESPONSE, EMPTY_RESPONSE], # Delete batch
|
[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"},
|
target={"entity_id": "todo.my_tasks"},
|
||||||
blocking=True,
|
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