@@ -537,6 +537,56 @@ def test_prepare_request_rejects_files_with_json(
537537 )
538538
539539
540+ def test_prepare_request_rejects_missing_leading_slash (
541+ monkeypatch : pytest .MonkeyPatch ,
542+ ) -> None :
543+ monkeypatch .setenv ("PDFREST_API_KEY" , VALID_API_KEY )
544+ with (
545+ PdfRestClient (api_key = VALID_API_KEY ) as client ,
546+ pytest .raises (PdfRestConfigurationError , match = "endpoint must start with '/'" ),
547+ ):
548+ client .prepare_request ("GET" , "up" )
549+
550+
551+ @pytest .mark .asyncio
552+ async def test_async_prepare_request_rejects_missing_leading_slash (
553+ monkeypatch : pytest .MonkeyPatch ,
554+ ) -> None :
555+ monkeypatch .setenv ("PDFREST_API_KEY" , ASYNC_API_KEY )
556+ async with AsyncPdfRestClient (api_key = ASYNC_API_KEY ) as client :
557+ with pytest .raises (
558+ PdfRestConfigurationError , match = "endpoint must start with '/'"
559+ ):
560+ client .prepare_request ("GET" , "up" )
561+
562+
563+ def test_prepare_request_accepts_iterator_and_marks_stream (
564+ monkeypatch : pytest .MonkeyPatch ,
565+ ) -> None :
566+ monkeypatch .setenv ("PDFREST_API_KEY" , VALID_API_KEY )
567+ file_iter = iter ([("file" , BytesIO (b"data" ))])
568+ with PdfRestClient (api_key = VALID_API_KEY ) as client :
569+ request = client .prepare_request ("POST" , "/upload" , files = file_iter )
570+
571+ assert isinstance (request .files , list )
572+ assert len (request .files ) == 1
573+ assert request .has_stream_uploads ()
574+
575+
576+ @pytest .mark .asyncio
577+ async def test_async_prepare_request_accepts_iterator_and_marks_stream (
578+ monkeypatch : pytest .MonkeyPatch ,
579+ ) -> None :
580+ monkeypatch .setenv ("PDFREST_API_KEY" , ASYNC_API_KEY )
581+ file_iter = iter ([("file" , BytesIO (b"data" ))])
582+ async with AsyncPdfRestClient (api_key = ASYNC_API_KEY ) as client :
583+ request = client .prepare_request ("POST" , "/upload" , files = file_iter )
584+
585+ assert isinstance (request .files , list )
586+ assert len (request .files ) == 1
587+ assert request .has_stream_uploads ()
588+
589+
540590def test_download_file_retries_on_error (monkeypatch : pytest .MonkeyPatch ) -> None :
541591 monkeypatch .setenv ("PDFREST_API_KEY" , VALID_API_KEY )
542592 monkeypatch .setattr (client_module .random , "uniform" , lambda * _ : 0.0 )
@@ -641,6 +691,76 @@ def handler(_: httpx.Request) -> httpx.Response:
641691 assert exc_info .value .response_content == "Unauthorized"
642692
643693
694+ def test_client_raises_for_non_json_success_response (
695+ monkeypatch : pytest .MonkeyPatch ,
696+ ) -> None :
697+ monkeypatch .setenv ("PDFREST_API_KEY" , VALID_API_KEY )
698+
699+ def handler (_ : httpx .Request ) -> httpx .Response :
700+ return httpx .Response (200 , text = "not-json" )
701+
702+ transport = httpx .MockTransport (handler )
703+ with (
704+ pytest .raises (PdfRestApiError , match = "Response body is not valid JSON" ) as exc ,
705+ PdfRestClient (transport = transport ) as client ,
706+ ):
707+ client .up ()
708+ assert exc .value .status_code == 200
709+ assert exc .value .response_content == "not-json"
710+
711+
712+ @pytest .mark .asyncio
713+ async def test_async_client_raises_for_non_json_success_response (
714+ monkeypatch : pytest .MonkeyPatch ,
715+ ) -> None :
716+ monkeypatch .setenv ("PDFREST_API_KEY" , ASYNC_API_KEY )
717+
718+ def handler (_ : httpx .Request ) -> httpx .Response :
719+ return httpx .Response (200 , text = "not-json" )
720+
721+ transport = httpx .MockTransport (handler )
722+ async with AsyncPdfRestClient (transport = transport ) as client :
723+ with pytest .raises (
724+ PdfRestApiError , match = "Response body is not valid JSON"
725+ ) as exc :
726+ await client .up ()
727+ assert exc .value .status_code == 200
728+ assert exc .value .response_content == "not-json"
729+
730+
731+ def test_client_uses_text_for_non_json_error_payload (
732+ monkeypatch : pytest .MonkeyPatch ,
733+ ) -> None :
734+ monkeypatch .setenv ("PDFREST_API_KEY" , VALID_API_KEY )
735+
736+ def handler (_ : httpx .Request ) -> httpx .Response :
737+ return httpx .Response (500 , text = "server blew up" )
738+
739+ transport = httpx .MockTransport (handler )
740+ with (
741+ pytest .raises (PdfRestApiError , match = "status code 500" ) as exc ,
742+ PdfRestClient (transport = transport ) as client ,
743+ ):
744+ client .up ()
745+ assert exc .value .response_content == "server blew up"
746+
747+
748+ @pytest .mark .asyncio
749+ async def test_async_client_uses_text_for_non_json_error_payload (
750+ monkeypatch : pytest .MonkeyPatch ,
751+ ) -> None :
752+ monkeypatch .setenv ("PDFREST_API_KEY" , ASYNC_API_KEY )
753+
754+ def handler (_ : httpx .Request ) -> httpx .Response :
755+ return httpx .Response (500 , text = "server blew up" )
756+
757+ transport = httpx .MockTransport (handler )
758+ async with AsyncPdfRestClient (transport = transport ) as client :
759+ with pytest .raises (PdfRestApiError , match = "status code 500" ) as exc :
760+ await client .up ()
761+ assert exc .value .response_content == "server blew up"
762+
763+
644764def test_client_raises_for_non_success_response (
645765 monkeypatch : pytest .MonkeyPatch ,
646766) -> None :
0 commit comments