@@ -226,6 +226,28 @@ async def test_create_or_update_arc_with_dict(client_config: Config) -> None:
226226 assert isinstance (response , ArcResult )
227227
228228
229+ @pytest .mark .asyncio
230+ @respx .mock
231+ async def test_create_or_update_arc_with_json_string (client_config : Config ) -> None :
232+ """Test create_or_update_arc with a JSON string."""
233+ route = respx .post (f"{ client_config .api_url } v3/arcs" ).mock (
234+ return_value = httpx .Response (http .HTTPStatus .OK , json = _ARC_RESPONSE )
235+ )
236+ async with ApiClient (client_config ) as client :
237+ response = await client .create_or_update_arc (rdi = "test-rdi" , arc = '{"id": "mock-arc"}' )
238+ assert route .called
239+ assert isinstance (response , ArcResult )
240+ assert response .arc_id == "arc-123"
241+
242+
243+ @pytest .mark .asyncio
244+ async def test_create_or_update_arc_with_invalid_json_string (client_config : Config ) -> None :
245+ """Test create_or_update_arc with an invalid JSON string."""
246+ async with ApiClient (client_config ) as client :
247+ with pytest .raises (ApiClientError , match = "Invalid JSON string provided for ARC" ):
248+ await client .create_or_update_arc (rdi = "test-rdi" , arc = '{"id": "mock-arc"' )
249+
250+
229251@pytest .mark .asyncio
230252@respx .mock
231253async def test_create_or_update_arc_http_error (client_config : Config ) -> None :
@@ -495,13 +517,35 @@ async def test_submit_arc_in_harvest_invalid_response(client_config: Config) ->
495517 await client .submit_arc_in_harvest ("harvest-456" , arc = {"id" : "mock" })
496518
497519
520+ @pytest .mark .asyncio
521+ @respx .mock
522+ async def test_submit_arc_in_harvest_with_json_string (client_config : Config ) -> None :
523+ """Test submit_arc_in_harvest with a JSON string."""
524+ route = respx .post (f"{ client_config .api_url } v3/harvests/harvest-456/arcs" ).mock (
525+ return_value = httpx .Response (http .HTTPStatus .OK , json = _ARC_RESPONSE )
526+ )
527+ async with ApiClient (client_config ) as client :
528+ response = await client .submit_arc_in_harvest ("harvest-456" , arc = '{"id": "mock-arc"}' )
529+ assert route .called
530+ assert isinstance (response , ArcResult )
531+ assert response .arc_id == "arc-123"
532+
533+
534+ @pytest .mark .asyncio
535+ async def test_submit_arc_in_harvest_with_invalid_json_string (client_config : Config ) -> None :
536+ """Test submit_arc_in_harvest with an invalid JSON string."""
537+ async with ApiClient (client_config ) as client :
538+ with pytest .raises (ApiClientError , match = "Invalid JSON string provided for ARC" ):
539+ await client .submit_arc_in_harvest ("harvest-456" , arc = '{"id": "mock-arc"' )
540+
541+
498542# ---------------------------------------------------------------------------
499543# harvest_arcs
500544# ---------------------------------------------------------------------------
501545
502546
503- async def _arc_gen (* arcs : "dict[str, Any]" ) -> AsyncGenerator ["dict[str, Any]" , None ]:
504- """Yield the provided arc dicts as an async generator."""
547+ async def _arc_gen (* arcs : "dict[str, Any] | str | ARC " ) -> AsyncGenerator ["dict[str, Any] | str | ARC " , None ]:
548+ """Yield the provided arc dicts, JSON strings, or ARC objects as an async generator."""
505549 for arc in arcs :
506550 yield arc
507551
@@ -650,6 +694,52 @@ async def test_harvest_arcs_cancels_on_catastrophic_error(client_config: Config)
650694 assert cancel_route .called
651695
652696
697+ @pytest .mark .asyncio
698+ @respx .mock
699+ async def test_harvest_arcs_with_json_string (client_config : Config ) -> None :
700+ """harvest_arcs supports JSON strings in async generator."""
701+ completed_response = {** _HARVEST_RESPONSE , "status" : "COMPLETED" , "completed_at" : "2024-01-01T01:00:00Z" }
702+ respx .post (f"{ client_config .api_url } v3/harvests" ).mock (
703+ return_value = httpx .Response (http .HTTPStatus .OK , json = _HARVEST_RESPONSE )
704+ )
705+ respx .post (f"{ client_config .api_url } v3/harvests/harvest-456/arcs" ).mock (
706+ return_value = httpx .Response (http .HTTPStatus .OK , json = _ARC_RESPONSE )
707+ )
708+ respx .post (f"{ client_config .api_url } v3/harvests/harvest-456/complete" ).mock (
709+ return_value = httpx .Response (http .HTTPStatus .OK , json = completed_response )
710+ )
711+
712+ arcs = _arc_gen (
713+ '{"id": "arc-1-string"}' ,
714+ {"id" : "arc-2-dict" },
715+ ARC .from_arc_investigation (ArcInvestigation .create (identifier = "test" , title = "Test" )),
716+ )
717+ async with ApiClient (client_config ) as client :
718+ result = await client .harvest_arcs ("test-rdi" , arcs , expected_datasets = 3 )
719+
720+ assert isinstance (result , HarvestResult )
721+ assert result .status == "COMPLETED"
722+
723+
724+ @pytest .mark .asyncio
725+ @respx .mock
726+ async def test_harvest_arcs_with_invalid_json_string (client_config : Config ) -> None :
727+ """harvest_arcs raises ApiClientError when JSON string is invalid."""
728+ # Mock the harvest creation endpoint to prevent actual HTTP requests
729+ respx .post (f"{ client_config .api_url } v3/harvests" ).mock (
730+ return_value = httpx .Response (http .HTTPStatus .OK , json = _HARVEST_RESPONSE )
731+ )
732+ # Mock the harvest cancellation endpoint
733+ respx .delete (f"{ client_config .api_url } v3/harvests/harvest-456" ).mock (
734+ return_value = httpx .Response (http .HTTPStatus .NO_CONTENT )
735+ )
736+
737+ async with ApiClient (client_config ) as client :
738+ arcs = _arc_gen ('{"id": "arc-1"' ) # Single invalid JSON string
739+ with pytest .raises (ApiClientError , match = "Invalid JSON string provided for ARC" ):
740+ await client .harvest_arcs ("test-rdi" , arcs )
741+
742+
653743@pytest .mark .asyncio
654744@respx .mock
655745async def test_harvest_arcs_cancel_failure_does_not_mask_original_error (client_config : Config ) -> None :
0 commit comments