From 6557fef6a2cabc3c5ebf2aa96a70896f5bcd4406 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 27 Mar 2026 23:01:24 -0400 Subject: [PATCH] feat: support multi-value status and priority filters in list_notes --- src/fabledassistant/routes/notes.py | 5 ++++- src/fabledassistant/services/notes.py | 14 ++++++++------ tests/test_recurrence.py | 11 ++++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/fabledassistant/routes/notes.py b/src/fabledassistant/routes/notes.py index 0a237ea..320ee62 100644 --- a/src/fabledassistant/routes/notes.py +++ b/src/fabledassistant/routes/notes.py @@ -70,11 +70,14 @@ async def list_notes_route(): elif type_param == "note": is_task = False + status = request.args.getlist("status") or None + priority = request.args.getlist("priority") or None + notes, total = await list_notes( uid, q=q, tags=tag or None, is_task=is_task, sort=sort, order=order, limit=limit, offset=offset, project_id=project_id, milestone_id=milestone_id, parent_id=parent_id, - no_project=no_project, + no_project=no_project, status=status, priority=priority, ) return jsonify({"notes": [n.to_dict() for n in notes], "total": total}) diff --git a/src/fabledassistant/services/notes.py b/src/fabledassistant/services/notes.py index be9e0ea..0af7a30 100644 --- a/src/fabledassistant/services/notes.py +++ b/src/fabledassistant/services/notes.py @@ -106,8 +106,8 @@ async def list_notes( q: str | None = None, tags: list[str] | None = None, is_task: bool | None = None, - status: str | None = None, - priority: str | None = None, + status: str | list[str] | None = None, + priority: str | list[str] | None = None, due_before: date | None = None, due_after: date | None = None, project_id: int | None = None, @@ -153,12 +153,14 @@ async def list_notes( count_query = count_query.where(tag_filter) if status: - query = query.where(Note.status == status) - count_query = count_query.where(Note.status == status) + statuses = [status] if isinstance(status, str) else status + query = query.where(Note.status.in_(statuses)) + count_query = count_query.where(Note.status.in_(statuses)) if priority: - query = query.where(Note.priority == priority) - count_query = count_query.where(Note.priority == priority) + priorities = [priority] if isinstance(priority, str) else priority + query = query.where(Note.priority.in_(priorities)) + count_query = count_query.where(Note.priority.in_(priorities)) if due_before is not None: query = query.where(Note.due_date < due_before) diff --git a/tests/test_recurrence.py b/tests/test_recurrence.py index 41ca059..071e15e 100644 --- a/tests/test_recurrence.py +++ b/tests/test_recurrence.py @@ -271,15 +271,14 @@ async def test_spawn_recurring_tasks_creates_child(): # ── Multi-status filtering ──────────────────────────────────────────────────── async def test_list_notes_multi_status_builds_in_clause(): - """list_notes with a list of statuses uses IN rather than equality.""" + """list_notes with a list of statuses executes without error.""" from unittest.mock import AsyncMock, MagicMock, patch mock_session = AsyncMock() mock_result = MagicMock() mock_result.scalars.return_value.all.return_value = [] - mock_count_result = MagicMock() - mock_count_result.scalar.return_value = 0 - mock_session.execute = AsyncMock(side_effect=[mock_result, mock_count_result]) + mock_session.execute = AsyncMock(return_value=mock_result) + mock_session.scalar = AsyncMock(return_value=0) mock_session.__aenter__ = AsyncMock(return_value=mock_session) mock_session.__aexit__ = AsyncMock(return_value=False) @@ -288,4 +287,6 @@ async def test_list_notes_multi_status_builds_in_clause(): notes, total = await list_notes(1, status=["todo", "in_progress"], is_task=True) assert total == 0 - assert mock_session.execute.call_count == 2 + assert notes == [] + mock_session.scalar.assert_called_once() + mock_session.execute.assert_called_once()