|
2 | 2 |
|
3 | 3 | import pytest |
4 | 4 | from datetime import datetime, timedelta |
| 5 | +from unittest.mock import patch |
5 | 6 |
|
6 | 7 | from basic_memory.mcp.tools import write_note |
7 | | -from basic_memory.mcp.tools.search import search_notes |
| 8 | +from basic_memory.mcp.tools.search import search_notes, _format_search_error_response |
8 | 9 |
|
9 | 10 |
|
10 | 11 | @pytest.mark.asyncio |
@@ -157,3 +158,91 @@ async def test_search_with_date_filter(client): |
157 | 158 |
|
158 | 159 | # Verify we get results within timeframe |
159 | 160 | assert len(response.results) > 0 |
| 161 | + |
| 162 | + |
| 163 | +class TestSearchErrorFormatting: |
| 164 | + """Test search error formatting for better user experience.""" |
| 165 | + |
| 166 | + def test_format_search_error_fts5_syntax(self): |
| 167 | + """Test formatting for FTS5 syntax errors.""" |
| 168 | + result = _format_search_error_response("syntax error in FTS5", "test query(") |
| 169 | + |
| 170 | + assert "# Search Failed - Invalid Syntax" in result |
| 171 | + assert "The search query 'test query(' contains invalid syntax" in result |
| 172 | + assert "Special characters" in result |
| 173 | + assert "test query" in result # Clean query without special chars |
| 174 | + |
| 175 | + def test_format_search_error_no_results(self): |
| 176 | + """Test formatting for no results found.""" |
| 177 | + result = _format_search_error_response("no results found", "very specific query") |
| 178 | + |
| 179 | + assert "# Search Complete - No Results Found" in result |
| 180 | + assert "No content found matching 'very specific query'" in result |
| 181 | + assert "Broaden your search" in result |
| 182 | + assert "very" in result # Simplified query |
| 183 | + |
| 184 | + def test_format_search_error_server_error(self): |
| 185 | + """Test formatting for server errors.""" |
| 186 | + result = _format_search_error_response("internal server error", "test query") |
| 187 | + |
| 188 | + assert "# Search Failed - Server Error" in result |
| 189 | + assert "The search service encountered an error while processing 'test query'" in result |
| 190 | + assert "Try again" in result |
| 191 | + assert "Check project status" in result |
| 192 | + |
| 193 | + def test_format_search_error_permission_denied(self): |
| 194 | + """Test formatting for permission errors.""" |
| 195 | + result = _format_search_error_response("permission denied", "test query") |
| 196 | + |
| 197 | + assert "# Search Failed - Access Error" in result |
| 198 | + assert "You don't have permission to search" in result |
| 199 | + assert "Check your project access" in result |
| 200 | + |
| 201 | + def test_format_search_error_project_not_found(self): |
| 202 | + """Test formatting for project not found errors.""" |
| 203 | + result = _format_search_error_response("current project not found", "test query") |
| 204 | + |
| 205 | + assert "# Search Failed - Project Not Found" in result |
| 206 | + assert "The current project is not accessible" in result |
| 207 | + assert "Check available projects" in result |
| 208 | + |
| 209 | + def test_format_search_error_generic(self): |
| 210 | + """Test formatting for generic errors.""" |
| 211 | + result = _format_search_error_response("unknown error", "test query") |
| 212 | + |
| 213 | + assert "# Search Failed" in result |
| 214 | + assert "Error searching for 'test query': unknown error" in result |
| 215 | + assert "General troubleshooting" in result |
| 216 | + |
| 217 | + |
| 218 | +class TestSearchToolErrorHandling: |
| 219 | + """Test search tool exception handling.""" |
| 220 | + |
| 221 | + @pytest.mark.asyncio |
| 222 | + async def test_search_notes_exception_handling(self): |
| 223 | + """Test exception handling in search_notes.""" |
| 224 | + with patch("basic_memory.mcp.tools.search.get_active_project") as mock_get_project: |
| 225 | + mock_get_project.return_value.project_url = "http://test" |
| 226 | + |
| 227 | + with patch( |
| 228 | + "basic_memory.mcp.tools.search.call_post", side_effect=Exception("syntax error") |
| 229 | + ): |
| 230 | + result = await search_notes("test query") |
| 231 | + |
| 232 | + assert isinstance(result, str) |
| 233 | + assert "# Search Failed - Invalid Syntax" in result |
| 234 | + |
| 235 | + @pytest.mark.asyncio |
| 236 | + async def test_search_notes_permission_error(self): |
| 237 | + """Test search_notes with permission error.""" |
| 238 | + with patch("basic_memory.mcp.tools.search.get_active_project") as mock_get_project: |
| 239 | + mock_get_project.return_value.project_url = "http://test" |
| 240 | + |
| 241 | + with patch( |
| 242 | + "basic_memory.mcp.tools.search.call_post", |
| 243 | + side_effect=Exception("permission denied"), |
| 244 | + ): |
| 245 | + result = await search_notes("test query") |
| 246 | + |
| 247 | + assert isinstance(result, str) |
| 248 | + assert "# Search Failed - Access Error" in result |
0 commit comments