From 2e5f56b70d144b2d19a2e757dbb39cce25eb9216 Mon Sep 17 00:00:00 2001 From: Manu <4445816+tr4nt0r@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:36:20 +0100 Subject: [PATCH] Refactor to-do list order and reordering in Habitica (#138566) --- homeassistant/components/habitica/todo.py | 54 +++++++++++-------- .../fixtures/reorder_dailies_response.json | 15 ++++++ .../fixtures/reorder_todos_response.json | 12 +++++ tests/components/habitica/test_todo.py | 31 +++++++++-- 4 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 tests/components/habitica/fixtures/reorder_dailies_response.json create mode 100644 tests/components/habitica/fixtures/reorder_todos_response.json diff --git a/homeassistant/components/habitica/todo.py b/homeassistant/components/habitica/todo.py index 29b98e90b04..71ba8e60e06 100644 --- a/homeassistant/components/habitica/todo.py +++ b/homeassistant/components/habitica/todo.py @@ -117,20 +117,24 @@ class BaseHabiticaListEntity(HabiticaBase, TodoListEntity): """Move an item in the To-do list.""" if TYPE_CHECKING: assert self.todo_items + tasks_order = ( + self.coordinator.data.user.tasksOrder.todos + if self.entity_description.key is HabiticaTodoList.TODOS + else self.coordinator.data.user.tasksOrder.dailys + ) if previous_uid: - pos = self.todo_items.index( - next(item for item in self.todo_items if item.uid == previous_uid) - ) - if pos < self.todo_items.index( - next(item for item in self.todo_items if item.uid == uid) - ): + pos = tasks_order.index(UUID(previous_uid)) + if pos < tasks_order.index(UUID(uid)): pos += 1 + else: pos = 0 try: - await self.coordinator.habitica.reorder_task(UUID(uid), pos) + tasks_order[:] = ( + await self.coordinator.habitica.reorder_task(UUID(uid), pos) + ).data except TooManyRequestsError as e: raise HomeAssistantError( translation_domain=DOMAIN, @@ -144,20 +148,6 @@ class BaseHabiticaListEntity(HabiticaBase, TodoListEntity): translation_key=f"move_{self.entity_description.key}_item_failed", translation_placeholders={"pos": str(pos)}, ) from e - else: - # move tasks in the coordinator until we have fresh data - tasks = self.coordinator.data.tasks - new_pos = ( - tasks.index( - next(task for task in tasks if task.id == UUID(previous_uid)) - ) - + 1 - if previous_uid - else 0 - ) - old_pos = tasks.index(next(task for task in tasks if task.id == UUID(uid))) - tasks.insert(new_pos, tasks.pop(old_pos)) - await self.coordinator.async_request_refresh() async def async_update_todo_item(self, item: TodoItem) -> None: """Update a Habitica todo.""" @@ -271,7 +261,7 @@ class HabiticaTodosListEntity(BaseHabiticaListEntity): def todo_items(self) -> list[TodoItem]: """Return the todo items.""" - return [ + tasks = [ *( TodoItem( uid=str(task.id), @@ -288,6 +278,15 @@ class HabiticaTodosListEntity(BaseHabiticaListEntity): if task.Type is TaskType.TODO ), ] + return sorted( + tasks, + key=lambda task: ( + float("inf") + if (uid := UUID(task.uid)) + not in (tasks_order := self.coordinator.data.user.tasksOrder.todos) + else tasks_order.index(uid) + ), + ) async def async_create_todo_item(self, item: TodoItem) -> None: """Create a Habitica todo.""" @@ -348,7 +347,7 @@ class HabiticaDailiesListEntity(BaseHabiticaListEntity): if TYPE_CHECKING: assert self.coordinator.data.user.lastCron - return [ + tasks = [ *( TodoItem( uid=str(task.id), @@ -365,3 +364,12 @@ class HabiticaDailiesListEntity(BaseHabiticaListEntity): if task.Type is TaskType.DAILY ) ] + return sorted( + tasks, + key=lambda task: ( + float("inf") + if (uid := UUID(task.uid)) + not in (tasks_order := self.coordinator.data.user.tasksOrder.dailys) + else tasks_order.index(uid) + ), + ) diff --git a/tests/components/habitica/fixtures/reorder_dailies_response.json b/tests/components/habitica/fixtures/reorder_dailies_response.json new file mode 100644 index 00000000000..3ad38ae9c2f --- /dev/null +++ b/tests/components/habitica/fixtures/reorder_dailies_response.json @@ -0,0 +1,15 @@ +{ + "success": true, + "data": [ + "f21fa608-cfc6-4413-9fc7-0eb1b48ca43a", + "2c6d136c-a1c3-4bef-b7c4-fa980784b1e1", + "bc1d1855-b2b8-4663-98ff-62e7b763dfc4", + "e97659e0-2c42-4599-a7bb-00282adc410d", + "564b9ac9-c53d-4638-9e7f-1cd96fe19baa", + "f2c85972-1a19-4426-bc6d-ce3337b9d99f", + "6e53f1f5-a315-4edd-984d-8d762e4a08ef" + ], + "notifications": [], + "userV": 589, + "appVersion": "5.28.6" +} diff --git a/tests/components/habitica/fixtures/reorder_todos_response.json b/tests/components/habitica/fixtures/reorder_todos_response.json new file mode 100644 index 00000000000..ba8118aa1da --- /dev/null +++ b/tests/components/habitica/fixtures/reorder_todos_response.json @@ -0,0 +1,12 @@ +{ + "success": true, + "data": [ + "88de7cd9-af2b-49ce-9afd-bf941d87336b", + "1aa3137e-ef72-4d1f-91ee-41933602f438", + "2f6fcabc-f670-4ec3-ba65-817e8deea490", + "86ea2475-d1b5-4020-bdcc-c188c7996afa" + ], + "notifications": [], + "userV": 589, + "appVersion": "5.28.6" +} diff --git a/tests/components/habitica/test_todo.py b/tests/components/habitica/test_todo.py index 01c033fcf95..3457af78403 100644 --- a/tests/components/habitica/test_todo.py +++ b/tests/components/habitica/test_todo.py @@ -6,7 +6,13 @@ from typing import Any from unittest.mock import AsyncMock, patch from uuid import UUID -from habiticalib import Direction, HabiticaTasksResponse, Task, TaskType +from habiticalib import ( + Direction, + HabiticaTaskOrderResponse, + HabiticaTasksResponse, + Task, + TaskType, +) import pytest from syrupy.assertion import SnapshotAssertion @@ -601,19 +607,23 @@ async def test_delete_completed_todo_items_exception( @pytest.mark.parametrize( - ("entity_id", "uid", "second_pos", "third_pos"), + ("entity_id", "uid", "second_pos", "third_pos", "fixture", "task_type"), [ ( "todo.test_user_to_do_s", "1aa3137e-ef72-4d1f-91ee-41933602f438", "88de7cd9-af2b-49ce-9afd-bf941d87336b", "2f6fcabc-f670-4ec3-ba65-817e8deea490", + "reorder_todos_response.json", + "todos", ), ( "todo.test_user_dailies", "2c6d136c-a1c3-4bef-b7c4-fa980784b1e1", - "564b9ac9-c53d-4638-9e7f-1cd96fe19baa", - "f2c85972-1a19-4426-bc6d-ce3337b9d99f", + "f21fa608-cfc6-4413-9fc7-0eb1b48ca43a", + "bc1d1855-b2b8-4663-98ff-62e7b763dfc4", + "reorder_dailies_response.json", + "dailys", ), ], ids=["todo", "daily"], @@ -627,9 +637,14 @@ async def test_move_todo_item( uid: str, second_pos: str, third_pos: str, + fixture: str, + task_type: str, ) -> None: """Test move todo items.""" - + reorder_response = HabiticaTaskOrderResponse.from_json( + load_fixture(fixture, DOMAIN) + ) + habitica.reorder_task.return_value = reorder_response config_entry.add_to_hass(hass) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() @@ -650,6 +665,7 @@ async def test_move_todo_item( assert resp.get("success") habitica.reorder_task.assert_awaited_once_with(UUID(uid), 1) + habitica.reorder_task.reset_mock() # move down to third position @@ -665,6 +681,7 @@ async def test_move_todo_item( assert resp.get("success") habitica.reorder_task.assert_awaited_once_with(UUID(uid), 2) + habitica.reorder_task.reset_mock() # move to top position @@ -679,6 +696,10 @@ async def test_move_todo_item( assert resp.get("success") habitica.reorder_task.assert_awaited_once_with(UUID(uid), 0) + assert ( + getattr(config_entry.runtime_data.data.user.tasksOrder, task_type) + == reorder_response.data + ) @pytest.mark.parametrize(