File size: 7,318 Bytes
310260a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | """
Unit Tests for create_task MCP Tool
Tests the create_task tool functionality including:
- Valid task creation with title only
- Task creation with title and description
- Validation errors for empty title
- Validation errors for title exceeding 200 chars
- Validation errors for description exceeding 2000 chars
- User_id scoping from MCPContext
"""
import pytest
from datetime import datetime
from src.tools.create_task import create_task_internal
from tests.utils.task_helpers import get_task_by_id, count_tasks
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_valid_title(mock_mcp_context, test_session):
"""
Test: create_task with valid title
Verifies that create_task successfully creates a task with just a title.
"""
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title="Buy groceries"
)
# Assert
assert result["status"] == "success"
assert "task" in result
assert result["task"]["title"] == "Buy groceries"
assert result["task"]["description"] is None
assert result["task"]["completed"] is False
assert "id" in result["task"]
assert "created_at" in result["task"]
assert "updated_at" in result["task"]
# Verify task persisted in database
task_id = result["task"]["id"]
task = get_task_by_id(test_session, task_id)
assert task is not None
assert task.title == "Buy groceries"
assert task.user_id == mock_mcp_context.user_id
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_title_and_description(mock_mcp_context, test_session):
"""
Test: create_task with title and description
Verifies that create_task successfully creates a task with both title and description.
"""
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title="Review PR",
description="Check code quality and test coverage"
)
# Assert
assert result["status"] == "success"
assert result["task"]["title"] == "Review PR"
assert result["task"]["description"] == "Check code quality and test coverage"
assert result["task"]["completed"] is False
# Verify task persisted in database
task_id = result["task"]["id"]
task = get_task_by_id(test_session, task_id)
assert task is not None
assert task.title == "Review PR"
assert task.description == "Check code quality and test coverage"
assert task.user_id == mock_mcp_context.user_id
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_empty_title_returns_error(mock_mcp_context):
"""
Test: create_task with empty title returns error
Verifies that create_task returns validation error for empty title.
"""
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title=""
)
# Assert
assert result["status"] == "error"
assert "error" in result
assert "Title is required" in result["error"]
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_whitespace_only_title_returns_error(mock_mcp_context):
"""
Test: create_task with whitespace-only title returns error
Verifies that create_task returns validation error for whitespace-only title.
"""
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title=" "
)
# Assert
assert result["status"] == "error"
assert "error" in result
assert "Title is required" in result["error"]
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_title_exceeding_200_chars_returns_error(mock_mcp_context):
"""
Test: create_task with title exceeding 200 chars returns error
Verifies that create_task returns validation error for title exceeding 200 characters.
"""
# Create a title with 201 characters
long_title = "A" * 201
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title=long_title
)
# Assert
assert result["status"] == "error"
assert "error" in result
assert "Title exceeds 200 characters" in result["error"]
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_description_exceeding_2000_chars_returns_error(mock_mcp_context):
"""
Test: create_task with description exceeding 2000 chars returns error
Verifies that create_task returns validation error for description exceeding 2000 characters.
"""
# Create a description with 2001 characters
long_description = "B" * 2001
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title="Valid title",
description=long_description
)
# Assert
assert result["status"] == "error"
assert "error" in result
assert "Description exceeds 2000 characters" in result["error"]
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_persists_user_id_from_mcp_context(mock_mcp_context, test_session):
"""
Test: create_task persists user_id from MCPContext
Verifies that create_task correctly uses user_id from MCPContext for data scoping.
"""
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title="Test task for user scoping"
)
# Assert
assert result["status"] == "success"
# Verify task has correct user_id from context
task_id = result["task"]["id"]
task = get_task_by_id(test_session, task_id)
assert task is not None
assert task.user_id == mock_mcp_context.user_id
# Verify task count for user
task_count = count_tasks(test_session, mock_mcp_context.user_id)
assert task_count == 1
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_max_valid_title_length(mock_mcp_context, test_session):
"""
Test: create_task with maximum valid title length (200 chars)
Verifies that create_task accepts title with exactly 200 characters.
"""
# Create a title with exactly 200 characters
max_title = "A" * 200
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title=max_title
)
# Assert
assert result["status"] == "success"
assert result["task"]["title"] == max_title
# Verify task persisted
task_id = result["task"]["id"]
task = get_task_by_id(test_session, task_id)
assert task is not None
assert len(task.title) == 200
@pytest.mark.unit
@pytest.mark.asyncio
async def test_create_task_with_max_valid_description_length(mock_mcp_context, test_session):
"""
Test: create_task with maximum valid description length (2000 chars)
Verifies that create_task accepts description with exactly 2000 characters.
"""
# Create a description with exactly 2000 characters
max_description = "B" * 2000
# Execute
result = await create_task_internal(
ctx=mock_mcp_context,
title="Valid title",
description=max_description
)
# Assert
assert result["status"] == "success"
assert result["task"]["description"] == max_description
# Verify task persisted
task_id = result["task"]["id"]
task = get_task_by_id(test_session, task_id)
assert task is not None
assert len(task.description) == 2000
|