Spaces:
Sleeping
Sleeping
| """ | |
| 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"] | |
| 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 | |