Skip to content

Commit ec26190

Browse files
tests: Add sync/async coverage for request validation and error handling
- Add tests to ensure `prepare_request` rejects endpoints without a leading `/`. - Validate iterator-based file uploads for stream detection in both sync and async methods. - Cover cases where the client raises errors for non-JSON success or error responses, verifying payload content. Assisted-by: Codex
1 parent c743f65 commit ec26190

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

tests/test_client.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
540590
def 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+
644764
def test_client_raises_for_non_success_response(
645765
monkeypatch: pytest.MonkeyPatch,
646766
) -> None:

0 commit comments

Comments
 (0)