todo-backend / Chatbot /tests /unit /test_add_task_error_handling.py
Fizu123's picture
BACKEND FIX: Filter by credential provider during login
08af9fd
"""
Unit tests for error handling in add_task tool.
"""
import pytest
from backend.mcp_server.tools.add_task import add_task
from backend.mcp_server.schemas import ErrorCode
from unittest.mock import MagicMock, patch
def test_error_handling_empty_title():
"""Test error handling when title is empty."""
result = add_task(
user_id="user_abc123",
title=""
)
assert result["success"] is False
assert result["error"]["code"] == ErrorCode.INVALID_INPUT
assert "title" in result["error"]["message"].lower()
def test_error_handling_title_too_long():
"""Test error handling when title exceeds 200 characters."""
long_title = "A" * 201
result = add_task(
user_id="user_abc123",
title=long_title
)
assert result["success"] is False
assert result["error"]["code"] == ErrorCode.INVALID_INPUT
assert "200" in result["error"]["message"]
def test_error_handling_description_too_long():
"""Test error handling when description exceeds 1000 characters."""
long_desc = "A" * 1001
result = add_task(
user_id="user_abc123",
title="Valid title",
description=long_desc
)
assert result["success"] is False
assert result["error"]["code"] == ErrorCode.INVALID_INPUT
assert "1000" in result["error"]["message"]
@patch('backend.mcp_server.tools.add_task.Session')
def test_error_handling_database_error(mock_session_class):
"""Test error handling when database operation fails."""
from sqlmodel import Session
# Mock session that raises an exception
mock_session = MagicMock(spec=Session)
mock_session.add.side_effect = Exception("Database connection failed")
mock_session_class.return_value.__enter__ = MagicMock(return_value=mock_session)
mock_session_class.return_value.__exit__ = MagicMock(return_value=False)
# Create mock Task model that raises exception on instantiation
with patch('backend.mcp_server.tools.add_task.Task') as mock_task_class:
mock_task_class.return_value = MagicMock()
mock_task_class.return_value.id = 1
result = add_task(
user_id="user_abc123",
title="Test task"
)
# Should catch exception and return DATABASE_ERROR
# (This depends on actual implementation)
# For now, we test that it doesn't crash
assert "success" in result
def test_error_handling_missing_user_id():
"""Test error handling when user_id is missing."""
result = add_task(
user_id="",
title="Test task"
)
assert result["success"] is False
assert result["error"]["code"] == ErrorCode.INVALID_INPUT
def test_error_handling_whitespace_only_title():
"""Test error handling when title contains only whitespace."""
result = add_task(
user_id="user_abc123",
title=" "
)
assert result["success"] is False
assert result["error"]["code"] == ErrorCode.INVALID_INPUT
def test_error_response_format():
"""Test error response has consistent format."""
result = add_task(
user_id="user_abc123",
title=""
)
assert result["success"] is False
assert result["data"] is None
assert "error" in result
assert "code" in result["error"]
assert "message" in result["error"]
assert isinstance(result["error"]["code"], str)
assert isinstance(result["error"]["message"], str)
def test_no_raw_database_errors_exposed():
"""Test raw database errors are not exposed in response."""
# This test verifies that even if internal exceptions occur,
# the user sees a clean error message
result = add_task(
user_id="user_abc123",
title=""
)
# Error message should be user-friendly, not a stack trace
assert "traceback" not in result["error"]["message"].lower()
assert "exception" not in result["error"]["message"].lower()
assert len(result["error"]["message"]) < 200 # Reasonable length
def test_error_codes_are_constants():
"""Test error codes use defined constants."""
result = add_task(
user_id="user_abc123",
title=""
)
assert result["error"]["code"] in [
ErrorCode.INVALID_INPUT,
ErrorCode.NOT_FOUND,
ErrorCode.UNAUTHORIZED,
ErrorCode.DATABASE_ERROR
]
def test_multiple_validation_errors_first_one_returned():
"""Test that the first validation error is returned when multiple exist."""
# Title is both empty AND too long (conceptually)
result = add_task(
user_id="user_abc123",
title=""
)
# Should return INVALID_INPUT with a clear message
assert result["error"]["code"] == ErrorCode.INVALID_INPUT