@@ -57,7 +57,7 @@ async def test_search_entities(
5757 )
5858
5959 # Search for the entity
60- response = await client .post (f"{ v2_project_url } /search/" , json = {"search_text " : "Searchable" })
60+ response = await client .post (f"{ v2_project_url } /search/" , json = {"text " : "Searchable" })
6161
6262 assert response .status_code == 200
6363 data = response .json ()
@@ -243,7 +243,7 @@ async def test_search_with_type_filter(
243243
244244 # Search with type filter
245245 response = await client .post (
246- f"{ v2_project_url } /search/" , json = {"search_text " : "Type" , "note_types" : ["note" ]}
246+ f"{ v2_project_url } /search/" , json = {"text " : "Type" , "note_types" : ["note" ]}
247247 )
248248
249249 assert response .status_code == 200
@@ -276,7 +276,7 @@ async def test_search_with_date_filter(
276276 # Search with date filter
277277 response = await client .post (
278278 f"{ v2_project_url } /search/" ,
279- json = {"search_text " : "Date Filtered" , "after_date" : "2024-01-01T00:00:00Z" },
279+ json = {"text " : "Date Filtered" , "after_date" : "2024-01-01T00:00:00Z" },
280280 )
281281
282282 assert response .status_code == 200
@@ -297,12 +297,42 @@ async def test_search_empty_query(
297297 assert response .status_code in [200 , 422 ]
298298
299299
300+ @pytest .mark .asyncio
301+ async def test_search_whitespace_text_is_treated_as_empty (
302+ client : AsyncClient ,
303+ test_project : Project ,
304+ v2_project_url : str ,
305+ entity_repository ,
306+ search_service ,
307+ file_service ,
308+ ):
309+ """Whitespace-only text should not become an unfiltered project-wide search."""
310+ entity_data = {
311+ "title" : "Whitespace Regression Entity" ,
312+ "note_type" : "note" ,
313+ "content_type" : "text/markdown" ,
314+ "file_path" : "whitespace_regression.md" ,
315+ "checksum" : "whitespace123" ,
316+ }
317+ await create_test_entity (
318+ test_project , entity_data , entity_repository , search_service , file_service
319+ )
320+
321+ response = await client .post (f"{ v2_project_url } /search/" , json = {"text" : " " })
322+
323+ assert response .status_code == 200
324+ data = response .json ()
325+ assert data ["total" ] == 0
326+ assert data ["has_more" ] is False
327+ assert data ["results" ] == []
328+
329+
300330@pytest .mark .asyncio
301331async def test_search_invalid_project_id (
302332 client : AsyncClient ,
303333):
304334 """Test searching with invalid project ID returns 404."""
305- response = await client .post ("/v2/projects/999999/search/" , json = {"search_text " : "test" })
335+ response = await client .post ("/v2/projects/999999/search/" , json = {"text " : "test" })
306336
307337 assert response .status_code == 404
308338
@@ -342,7 +372,7 @@ async def test_v2_search_endpoints_use_project_id_not_name(
342372):
343373 """Test that v2 search endpoints reject string project names."""
344374 # Try to use project name instead of ID - should fail
345- response = await client .post (f"/v2/{ test_project .name } /search/" , json = {"search_text " : "test" })
375+ response = await client .post (f"/v2/{ test_project .name } /search/" , json = {"text " : "test" })
346376
347377 # FastAPI path validation should reject non-integer project_id
348378 assert response .status_code in [404 , 422 ]
@@ -358,11 +388,14 @@ class RaisingSearchService:
358388 async def search (self , * args , ** kwargs ):
359389 raise SemanticSearchDisabledError ("Semantic search is disabled for this project." )
360390
391+ async def count (self , * args , ** kwargs ):
392+ raise SemanticSearchDisabledError ("Semantic search is disabled for this project." )
393+
361394 app .dependency_overrides [get_search_service_v2_external ] = lambda : RaisingSearchService ()
362395 try :
363396 response = await client .post (
364397 f"{ v2_project_url } /search/" ,
365- json = {"search_text " : "semantic query" , "retrieval_mode" : "vector" },
398+ json = {"text " : "semantic query" , "retrieval_mode" : "vector" },
366399 )
367400 finally :
368401 app .dependency_overrides .pop (get_search_service_v2_external , None )
@@ -381,11 +414,14 @@ class RaisingSearchService:
381414 async def search (self , * args , ** kwargs ):
382415 raise SemanticDependenciesMissingError ("Semantic dependencies are missing." )
383416
417+ async def count (self , * args , ** kwargs ):
418+ raise SemanticDependenciesMissingError ("Semantic dependencies are missing." )
419+
384420 app .dependency_overrides [get_search_service_v2_external ] = lambda : RaisingSearchService ()
385421 try :
386422 response = await client .post (
387423 f"{ v2_project_url } /search/" ,
388- json = {"search_text " : "semantic query" , "retrieval_mode" : "hybrid" },
424+ json = {"text " : "semantic query" , "retrieval_mode" : "hybrid" },
389425 )
390426 finally :
391427 app .dependency_overrides .pop (get_search_service_v2_external , None )
@@ -404,6 +440,9 @@ class RaisingSearchService:
404440 async def search (self , * args , ** kwargs ):
405441 raise ValueError ("Vector retrieval requires a text query." )
406442
443+ async def count (self , * args , ** kwargs ):
444+ raise ValueError ("Vector retrieval requires a text query." )
445+
407446 app .dependency_overrides [get_search_service_v2_external ] = lambda : RaisingSearchService ()
408447 try :
409448 response = await client .post (
@@ -517,7 +556,7 @@ async def count(self, *args, **kwargs):
517556 try :
518557 response = await client .post (
519558 f"{ v2_project_url } /search/" ,
520- json = {"search_text " : "pricing" },
559+ json = {"text " : "pricing" },
521560 )
522561 finally :
523562 app .dependency_overrides .pop (get_search_service_v2_external , None )
@@ -561,7 +600,7 @@ async def count(self, *args, **kwargs):
561600 try :
562601 response = await client .post (
563602 f"{ v2_project_url } /search/" ,
564- json = {"search_text " : "general" },
603+ json = {"text " : "general" },
565604 )
566605 finally :
567606 app .dependency_overrides .pop (get_search_service_v2_external , None )
0 commit comments