@@ -62,6 +62,29 @@ def test_translate_payload_rejects_invalid_mime() -> None:
6262 )
6363
6464
65+ @pytest .mark .asyncio
66+ async def test_async_translate_payload_rejects_invalid_mime () -> None :
67+ file_id = str (PdfRestFileID .generate ())
68+ image_file = PdfRestFile .model_validate (
69+ {
70+ "id" : file_id ,
71+ "name" : "image.png" ,
72+ "url" : f"https://api.pdfrest.com/resource/{ file_id } " ,
73+ "type" : "image/png" ,
74+ "size" : 10 ,
75+ "modified" : "2024-01-01T00:00:00Z" ,
76+ "scheduledDeletionTimeUtc" : None ,
77+ }
78+ )
79+
80+ with pytest .raises (
81+ ValidationError , match = "Must be a PDF, Markdown, or plain text file"
82+ ):
83+ TranslatePdfTextPayload .model_validate (
84+ {"files" : [image_file ], "output_language" : "fr" }
85+ )
86+
87+
6588@pytest .mark .parametrize (
6689 "output_language" ,
6790 [
@@ -113,6 +136,38 @@ def test_translate_payload_requires_target_language() -> None:
113136 TranslatePdfTextPayload .model_validate ({"files" : [file_repr ]})
114137
115138
139+ @pytest .mark .asyncio
140+ @pytest .mark .parametrize (
141+ "output_language" ,
142+ [
143+ pytest .param ("" , id = "empty" ),
144+ pytest .param ("e" , id = "too-short" ),
145+ pytest .param ("english" , id = "not-a-code" ),
146+ pytest .param ("eng-USA" , id = "long-subtag" ),
147+ pytest .param ("en-1234" , id = "long-numeric-region" ),
148+ pytest .param ("en-US-extra" , id = "too-many-subtags" ),
149+ ],
150+ )
151+ async def test_async_translate_payload_rejects_invalid_output_language (
152+ output_language : str ,
153+ ) -> None :
154+ file_repr = make_pdf_file (PdfRestFileID .generate (1 ))
155+ with pytest .raises (
156+ ValidationError ,
157+ match = re .escape (OUTPUT_LANGUAGE_ERROR ),
158+ ):
159+ TranslatePdfTextPayload .model_validate (
160+ {"files" : [file_repr ], "output_language" : output_language }
161+ )
162+
163+
164+ @pytest .mark .asyncio
165+ async def test_async_translate_payload_requires_target_language () -> None :
166+ file_repr = make_pdf_file (PdfRestFileID .generate (1 ))
167+ with pytest .raises (ValidationError ):
168+ TranslatePdfTextPayload .model_validate ({"files" : [file_repr ]})
169+
170+
116171def test_translate_pdf_text_json_success (monkeypatch : pytest .MonkeyPatch ) -> None :
117172 monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
118173 input_file = _make_markdown_file (str (PdfRestFileID .generate (1 )))
@@ -237,6 +292,80 @@ def handler(request: httpx.Request) -> httpx.Response:
237292 assert timeout_value == pytest .approx (0.3 )
238293
239294
295+ @pytest .mark .asyncio
296+ async def test_async_translate_pdf_text_request_customization (
297+ monkeypatch : pytest .MonkeyPatch ,
298+ ) -> None :
299+ monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
300+ input_file = make_pdf_file (PdfRestFileID .generate (2 ))
301+ payload_dump = TranslatePdfTextPayload .model_validate (
302+ {
303+ "files" : [input_file ],
304+ "output_language" : "es" ,
305+ "output_type" : "file" ,
306+ }
307+ ).model_dump (mode = "json" , by_alias = True , exclude_none = True , exclude_unset = True )
308+ output_id = str (PdfRestFileID .generate ())
309+
310+ captured_timeout : dict [str , float | dict [str , float ] | None ] = {}
311+
312+ def handler (request : httpx .Request ) -> httpx .Response :
313+ if request .method == "POST" and request .url .path == "/translated-pdf-text" :
314+ assert request .url .params ["trace" ] == "true"
315+ assert request .headers ["X-Debug" ] == "async"
316+ captured_timeout ["value" ] = request .extensions .get ("timeout" )
317+ payload = json .loads (request .content .decode ("utf-8" ))
318+ for key , value in payload_dump .items ():
319+ assert payload [key ] == value
320+ assert payload ["debug" ] is True
321+ return httpx .Response (
322+ 200 ,
323+ json = {
324+ "outputUrl" : f"https://api.pdfrest.com/resource/{ output_id } ?format=file" ,
325+ "outputId" : output_id ,
326+ "inputId" : str (input_file .id ),
327+ "source_languages" : ["en" ],
328+ "output_language" : "es" ,
329+ },
330+ )
331+ if request .method == "GET" and request .url .path == f"/resource/{ output_id } " :
332+ assert request .url .params ["format" ] == "info"
333+ assert request .url .params ["trace" ] == "true"
334+ assert request .headers ["X-Debug" ] == "async"
335+ return httpx .Response (
336+ 200 ,
337+ json = _make_markdown_file (output_id ).model_dump (
338+ mode = "json" , by_alias = True
339+ ),
340+ )
341+ msg = f"Unexpected request { request .method } { request .url } "
342+ raise AssertionError (msg )
343+
344+ transport = httpx .MockTransport (handler )
345+ async with AsyncPdfRestClient (api_key = ASYNC_API_KEY , transport = transport ) as client :
346+ response = await client .translate_pdf_text_to_file (
347+ input_file ,
348+ output_language = "es" ,
349+ extra_query = {"trace" : "true" },
350+ extra_headers = {"X-Debug" : "async" },
351+ extra_body = {"debug" : True },
352+ timeout = 0.3 ,
353+ )
354+
355+ assert isinstance (response , TranslatePdfTextFileResponse )
356+ assert response .output_file .id == output_id
357+ assert response .output_language == "es"
358+ assert response .source_languages == ["en" ]
359+ timeout_value = captured_timeout ["value" ]
360+ assert timeout_value is not None
361+ if isinstance (timeout_value , dict ):
362+ assert all (
363+ component == pytest .approx (0.3 ) for component in timeout_value .values ()
364+ )
365+ else :
366+ assert timeout_value == pytest .approx (0.3 )
367+
368+
240369def test_translate_pdf_text_success (monkeypatch : pytest .MonkeyPatch ) -> None :
241370 monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
242371 input_file = make_pdf_file (PdfRestFileID .generate (2 ))
0 commit comments