| """ |
| Unit Tests for list_tasks MCP Tool |
| |
| Tests the list_tasks tool functionality including: |
| - Returns all tasks for user |
| - Returns empty array for user with no tasks |
| - Filters by user_id correctly |
| - Returns correct counts (total, completed, pending) |
| - Handles database errors gracefully |
| """ |
|
|
| import pytest |
|
|
| from src.tools.list_tasks import list_tasks_internal |
| from tests.utils.task_helpers import create_test_task, create_multiple_tasks, delete_all_tasks |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_returns_all_tasks_for_user(mock_mcp_context, test_session): |
| """ |
| Test: list_tasks returns all tasks for user |
| |
| Verifies that list_tasks returns all tasks belonging to the authenticated user. |
| """ |
| |
| create_multiple_tasks(test_session, mock_mcp_context.user_id, count=3, title_prefix="Task") |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert "tasks" in result |
| assert len(result["tasks"]) == 3 |
| assert result["total"] == 3 |
| assert result["pending_count"] == 3 |
| assert result["completed_count"] == 0 |
|
|
| |
| for task in result["tasks"]: |
| assert "id" in task |
| assert "title" in task |
| assert "completed" in task |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_returns_empty_array_for_user_with_no_tasks(mock_mcp_context, test_session): |
| """ |
| Test: list_tasks returns empty array for user with no tasks |
| |
| Verifies that list_tasks returns empty array when user has no tasks. |
| """ |
| |
| delete_all_tasks(test_session, mock_mcp_context.user_id) |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert "tasks" in result |
| assert len(result["tasks"]) == 0 |
| assert result["total"] == 0 |
| assert result["pending_count"] == 0 |
| assert result["completed_count"] == 0 |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_filters_by_user_id_correctly(mock_mcp_context, mock_mcp_context_user2, test_session): |
| """ |
| Test: list_tasks filters by user_id correctly |
| |
| Verifies that list_tasks only returns tasks for the authenticated user. |
| """ |
| |
| create_multiple_tasks(test_session, mock_mcp_context.user_id, count=3, title_prefix="User1 Task") |
| create_multiple_tasks(test_session, mock_mcp_context_user2.user_id, count=2, title_prefix="User2 Task") |
|
|
| |
| result1 = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert len(result1["tasks"]) == 3 |
| assert result1["total"] == 3 |
| for task in result1["tasks"]: |
| assert "User1 Task" in task["title"] |
|
|
| |
| result2 = await list_tasks_internal(ctx=mock_mcp_context_user2) |
|
|
| |
| assert len(result2["tasks"]) == 2 |
| assert result2["total"] == 2 |
| for task in result2["tasks"]: |
| assert "User2 Task" in task["title"] |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_returns_correct_counts(mock_mcp_context, test_session): |
| """ |
| Test: list_tasks returns correct counts (total, completed, pending) |
| |
| Verifies that list_tasks returns accurate counts for total, completed, and pending tasks. |
| """ |
| |
| create_multiple_tasks(test_session, mock_mcp_context.user_id, count=2, title_prefix="Completed", completed=True) |
| create_multiple_tasks(test_session, mock_mcp_context.user_id, count=3, title_prefix="Pending", completed=False) |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert result["total"] == 5 |
| assert result["completed_count"] == 2 |
| assert result["pending_count"] == 3 |
|
|
| |
| assert len(result["tasks"]) == 5 |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_handles_database_errors_gracefully(mock_mcp_context): |
| """ |
| Test: list_tasks handles database errors gracefully |
| |
| Verifies that list_tasks returns error response for database failures. |
| """ |
| |
| |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert "tasks" in result |
| assert "total" in result |
| assert "completed_count" in result |
| assert "pending_count" in result |
|
|
| |
| if "status" in result and result["status"] == "error": |
| assert "error" in result |
| assert isinstance(result["error"], str) |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_includes_all_required_fields(mock_mcp_context, test_session): |
| """ |
| Test: list_tasks includes all required fields in task objects |
| |
| Verifies that each task in the response contains all required fields. |
| """ |
| |
| create_test_task( |
| test_session, |
| mock_mcp_context.user_id, |
| title="Complete Task", |
| description="Task description", |
| completed=False |
| ) |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert len(result["tasks"]) == 1 |
| task = result["tasks"][0] |
|
|
| |
| assert "id" in task |
| assert "title" in task |
| assert "description" in task |
| assert "completed" in task |
| assert "created_at" in task |
| assert "updated_at" in task |
|
|
| |
| assert isinstance(task["id"], int) |
| assert isinstance(task["title"], str) |
| assert isinstance(task["completed"], bool) |
| assert isinstance(task["created_at"], str) |
| assert isinstance(task["updated_at"], str) |
|
|
|
|
| @pytest.mark.unit |
| @pytest.mark.asyncio |
| async def test_list_tasks_with_mixed_completion_status(mock_mcp_context, test_session): |
| """ |
| Test: list_tasks with mixed completion status |
| |
| Verifies that list_tasks correctly returns tasks with different completion statuses. |
| """ |
| |
| create_test_task(test_session, mock_mcp_context.user_id, title="Task 1", completed=True) |
| create_test_task(test_session, mock_mcp_context.user_id, title="Task 2", completed=False) |
| create_test_task(test_session, mock_mcp_context.user_id, title="Task 3", completed=True) |
| create_test_task(test_session, mock_mcp_context.user_id, title="Task 4", completed=False) |
|
|
| |
| result = await list_tasks_internal(ctx=mock_mcp_context) |
|
|
| |
| assert result["total"] == 4 |
| assert result["completed_count"] == 2 |
| assert result["pending_count"] == 2 |
|
|
| |
| completed_tasks = [t for t in result["tasks"] if t["completed"]] |
| pending_tasks = [t for t in result["tasks"] if not t["completed"]] |
|
|
| assert len(completed_tasks) == 2 |
| assert len(pending_tasks) == 2 |
|
|