myrmidon / python /tests /mcp_server /features /tasks /test_task_tools.py
tek Atrust
chore(deploy): build monolithic server for Hugging Face
d5ef46f
Raw
History Blame Contribute Delete
5.85 kB
"""Unit tests for task management tools."""
import json
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from mcp.server.fastmcp import Context
from src.mcp_server.features.tasks.task_tools import register_task_tools
@pytest.fixture
def mock_mcp():
"""Create a mock MCP server for testing."""
mock = MagicMock()
# Store registered tools
mock._tools = {}
def tool_decorator():
def decorator(func):
mock._tools[func.__name__] = func
return func
return decorator
mock.tool = tool_decorator
return mock
@pytest.fixture
def mock_context():
"""Create a mock context for testing."""
return MagicMock(spec=Context)
@pytest.mark.asyncio
async def test_create_task_with_sources(mock_mcp, mock_context):
"""Test creating a task using manage_task."""
register_task_tools(mock_mcp)
# Get the manage_task function
manage_task = mock_mcp._tools.get("manage_task")
assert manage_task is not None, "manage_task tool not registered"
# Mock call_api response
mock_res = {
"success": True,
"task": {"id": "task-123", "title": "Test Task"},
"message": "Task created successfully",
}
with patch("src.mcp_server.features.tasks.task_tools.call_api", new_callable=AsyncMock) as mock_call:
mock_call.return_value = mock_res
result = await manage_task(
mock_context,
action="create",
project_id="project-123",
title="Implement OAuth2",
description="Add OAuth2 authentication",
assignee="AI IDE Agent",
)
result_data = json.loads(result)
assert result_data["success"] is True
assert result_data["task_id"] == "task-123"
# Verify the task was created properly via call_api
mock_call.assert_called_once()
args, kwargs = mock_call.call_args
assert args[0] == "POST"
assert args[1] == "/api/tasks"
assert kwargs["json"]["title"] == "Implement OAuth2"
@pytest.mark.asyncio
async def test_find_tasks_with_project_filter(mock_mcp, mock_context):
"""Test listing tasks with project-specific endpoint."""
register_task_tools(mock_mcp)
# Get the find_tasks function
find_tasks = mock_mcp._tools.get("find_tasks")
assert find_tasks is not None, "find_tasks tool not registered"
# Mock call_api response
mock_res = {
"success": True,
"tasks": [
{"id": "task-1", "title": "Task 1", "status": "todo"},
{"id": "task-2", "title": "Task 2", "status": "doing"},
],
}
with patch("src.mcp_server.features.tasks.task_tools.call_api", new_callable=AsyncMock) as mock_call:
mock_call.return_value = mock_res
result = await find_tasks(mock_context, filter_by="project", filter_value="project-123")
result_data = json.loads(result)
assert result_data["success"] is True
assert len(result_data["tasks"]) == 2
# Verify the correct project endpoint was called
args, kwargs = mock_call.call_args
assert args[1] == "/api/projects/project-123/tasks"
@pytest.mark.asyncio
async def test_find_tasks_with_status_filter(mock_mcp, mock_context):
"""Test listing tasks with status filter."""
register_task_tools(mock_mcp)
# Get the find_tasks function
find_tasks = mock_mcp._tools.get("find_tasks")
# Mock call_api response
mock_res = {
"success": True,
"tasks": [
{"id": "task-1", "title": "Task 1", "status": "todo"},
],
}
with patch("src.mcp_server.features.tasks.task_tools.call_api", new_callable=AsyncMock) as mock_call:
mock_call.return_value = mock_res
result = await find_tasks(mock_context, filter_by="status", filter_value="todo")
result_data = json.loads(result)
assert result_data["success"] is True
assert result_data["tasks"][0]["status"] == "todo"
# Verify status parameter was passed
args, kwargs = mock_call.call_args
assert kwargs["params"]["status"] == "todo"
@pytest.mark.asyncio
async def test_update_task_status(mock_mcp, mock_context):
"""Test updating task status."""
register_task_tools(mock_mcp)
manage_task = mock_mcp._tools.get("manage_task")
# Mock call_api response
mock_res = {
"success": True,
"task": {"id": "task-123", "status": "doing"},
"message": "Task updated successfully",
}
with patch("src.mcp_server.features.tasks.task_tools.call_api", new_callable=AsyncMock) as mock_call:
mock_call.return_value = mock_res
result = await manage_task(mock_context, action="update", task_id="task-123", status="doing")
result_data = json.loads(result)
assert result_data["success"] is True
assert result_data["task"]["status"] == "doing"
# Verify PUT call
args, kwargs = mock_call.call_args
assert args[0] == "PUT"
assert args[1] == "/api/tasks/task-123"
assert kwargs["json"]["status"] == "doing"
@pytest.mark.asyncio
async def test_delete_task_already_archived(mock_mcp, mock_context):
"""Test deleting an already archived/deleted task."""
register_task_tools(mock_mcp)
manage_task = mock_mcp._tools.get("manage_task")
# Mock call_api 404 response
mock_res = {"success": False, "error": "HTTP 404: Not Found"}
with patch("src.mcp_server.features.tasks.task_tools.call_api", new_callable=AsyncMock) as mock_call:
mock_call.return_value = mock_res
result = await manage_task(mock_context, action="delete", task_id="task-none")
result_data = json.loads(result)
assert result_data["success"] is False
assert "HTTP 404" in result_data["error"]