11from __future__ import annotations
22
33import json
4+ from collections .abc import Callable
45
56import httpx
67import pytest
@@ -66,6 +67,32 @@ def make_signature_configuration(signature_type: str) -> dict[str, object]:
6667 return {"type" : "existing" , "name" : "esignature" }
6768
6869
70+ MULTI_FILE_CREDENTIAL_CASES = (
71+ pytest .param ("pfx" , "passphrase" , make_pfx_file , make_passphrase_file , id = "pfx" ),
72+ pytest .param (
73+ "passphrase" ,
74+ "pfx" ,
75+ make_passphrase_file ,
76+ make_pfx_file ,
77+ id = "passphrase" ,
78+ ),
79+ pytest .param (
80+ "certificate" ,
81+ "private_key" ,
82+ make_certificate_file ,
83+ make_private_key_file ,
84+ id = "certificate" ,
85+ ),
86+ pytest .param (
87+ "private_key" ,
88+ "certificate" ,
89+ make_private_key_file ,
90+ make_certificate_file ,
91+ id = "private-key" ,
92+ ),
93+ )
94+
95+
6996def test_sign_pdf_with_pfx_credentials (monkeypatch : pytest .MonkeyPatch ) -> None :
7097 monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
7198 input_file = make_pdf_file (PdfRestFileID .generate (1 ))
@@ -286,7 +313,10 @@ def test_sign_pdf_rejects_multiple_input_files(
286313
287314 with (
288315 PdfRestClient (api_key = VALID_API_KEY , transport = transport ) as client ,
289- pytest .raises (ValidationError , match = r"files|at most 1 item" ),
316+ pytest .raises (
317+ ValidationError ,
318+ match = r"files\n\s+List should have at most 1 item after validation" ,
319+ ),
290320 ):
291321 client .sign_pdf (
292322 [input_file_a , input_file_b ],
@@ -311,7 +341,10 @@ def test_sign_pdf_rejects_multiple_logo_files(
311341
312342 with (
313343 PdfRestClient (api_key = VALID_API_KEY , transport = transport ) as client ,
314- pytest .raises (ValidationError , match = r"logo|at most 1 item" ),
344+ pytest .raises (
345+ ValidationError ,
346+ match = r"logo\n\s+List should have at most 1 item after validation" ,
347+ ),
315348 ):
316349 client .sign_pdf (
317350 input_file ,
@@ -327,19 +360,30 @@ def test_sign_pdf_rejects_multiple_logo_files(
327360 )
328361
329362
330- def test_sign_pdf_rejects_multiple_pfx_credential_files (
363+ @pytest .mark .parametrize (
364+ ("multi_field" , "single_field" , "multi_factory" , "single_factory" ),
365+ MULTI_FILE_CREDENTIAL_CASES ,
366+ )
367+ def test_sign_pdf_rejects_multiple_credential_files (
331368 monkeypatch : pytest .MonkeyPatch ,
369+ multi_field : str ,
370+ single_field : str ,
371+ multi_factory : Callable [[str ], PdfRestFile ],
372+ single_factory : Callable [[str ], PdfRestFile ],
332373) -> None :
333374 monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
334375 input_file = make_pdf_file (PdfRestFileID .generate ())
335- pfx_file_a = make_pfx_file (str (PdfRestFileID .generate ()))
336- pfx_file_b = make_pfx_file (str (PdfRestFileID .generate ()))
337- passphrase_file = make_passphrase_file (str (PdfRestFileID .generate ()))
376+ multi_file_a = multi_factory (str (PdfRestFileID .generate ()))
377+ multi_file_b = multi_factory (str (PdfRestFileID .generate ()))
378+ single_file = single_factory (str (PdfRestFileID .generate ()))
338379 transport = httpx .MockTransport (lambda request : (_ for _ in ()).throw (RuntimeError ))
339380
381+ expected_match = (
382+ rf"{ multi_field } \n\s+List should have at most 1 item after validation"
383+ )
340384 with (
341385 PdfRestClient (api_key = VALID_API_KEY , transport = transport ) as client ,
342- pytest .raises (ValidationError , match = r"pfx|at most 1 item" ),
386+ pytest .raises (ValidationError , match = expected_match ),
343387 ):
344388 client .sign_pdf (
345389 input_file ,
@@ -348,8 +392,8 @@ def test_sign_pdf_rejects_multiple_pfx_credential_files(
348392 "location" : make_signature_location (),
349393 },
350394 credentials = {
351- "pfx" : [pfx_file_a , pfx_file_b ], # type: ignore[list -item]
352- "passphrase" : passphrase_file ,
395+ multi_field : [multi_file_a , multi_file_b ], # type: ignore[dict -item]
396+ single_field : single_file ,
353397 },
354398 )
355399
@@ -429,7 +473,10 @@ async def test_async_sign_pdf_rejects_multiple_input_files(
429473 transport = httpx .MockTransport (lambda request : (_ for _ in ()).throw (RuntimeError ))
430474
431475 async with AsyncPdfRestClient (api_key = ASYNC_API_KEY , transport = transport ) as client :
432- with pytest .raises (ValidationError , match = r"files|at most 1 item" ):
476+ with pytest .raises (
477+ ValidationError ,
478+ match = r"files\n\s+List should have at most 1 item after validation" ,
479+ ):
433480 await client .sign_pdf (
434481 [input_file_a , input_file_b ],
435482 signature_configuration = {
@@ -453,7 +500,10 @@ async def test_async_sign_pdf_rejects_multiple_logo_files(
453500 transport = httpx .MockTransport (lambda request : (_ for _ in ()).throw (RuntimeError ))
454501
455502 async with AsyncPdfRestClient (api_key = ASYNC_API_KEY , transport = transport ) as client :
456- with pytest .raises (ValidationError , match = r"logo|at most 1 item" ):
503+ with pytest .raises (
504+ ValidationError ,
505+ match = r"logo\n\s+List should have at most 1 item after validation" ,
506+ ):
457507 await client .sign_pdf (
458508 input_file ,
459509 signature_configuration = {
@@ -469,27 +519,38 @@ async def test_async_sign_pdf_rejects_multiple_logo_files(
469519
470520
471521@pytest .mark .asyncio
472- async def test_async_sign_pdf_rejects_multiple_pfx_credential_files (
522+ @pytest .mark .parametrize (
523+ ("multi_field" , "single_field" , "multi_factory" , "single_factory" ),
524+ MULTI_FILE_CREDENTIAL_CASES ,
525+ )
526+ async def test_async_sign_pdf_rejects_multiple_credential_files (
473527 monkeypatch : pytest .MonkeyPatch ,
528+ multi_field : str ,
529+ single_field : str ,
530+ multi_factory : Callable [[str ], PdfRestFile ],
531+ single_factory : Callable [[str ], PdfRestFile ],
474532) -> None :
475533 monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
476534 input_file = make_pdf_file (PdfRestFileID .generate ())
477- pfx_file_a = make_pfx_file (str (PdfRestFileID .generate ()))
478- pfx_file_b = make_pfx_file (str (PdfRestFileID .generate ()))
479- passphrase_file = make_passphrase_file (str (PdfRestFileID .generate ()))
535+ multi_file_a = multi_factory (str (PdfRestFileID .generate ()))
536+ multi_file_b = multi_factory (str (PdfRestFileID .generate ()))
537+ single_file = single_factory (str (PdfRestFileID .generate ()))
480538 transport = httpx .MockTransport (lambda request : (_ for _ in ()).throw (RuntimeError ))
481539
540+ expected_match = (
541+ rf"{ multi_field } \n\s+List should have at most 1 item after validation"
542+ )
482543 async with AsyncPdfRestClient (api_key = ASYNC_API_KEY , transport = transport ) as client :
483- with pytest .raises (ValidationError , match = r"pfx|at most 1 item" ):
544+ with pytest .raises (ValidationError , match = expected_match ):
484545 await client .sign_pdf (
485546 input_file ,
486547 signature_configuration = {
487548 "type" : "new" ,
488549 "location" : make_signature_location (),
489550 },
490551 credentials = {
491- "pfx" : [pfx_file_a , pfx_file_b ], # type: ignore[list -item]
492- "passphrase" : passphrase_file ,
552+ multi_field : [multi_file_a , multi_file_b ], # type: ignore[dict -item]
553+ single_field : single_file ,
493554 },
494555 )
495556
0 commit comments