@@ -773,6 +773,54 @@ def handler(request: httpx.Request) -> httpx.Response:
773773 assert seen == {"post" : 1 , "get" : 1 }
774774
775775
776+ def test_sign_pdf_allows_zero_logo_opacity_via_public_argument (
777+ monkeypatch : pytest .MonkeyPatch ,
778+ ) -> None :
779+ monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
780+ input_file = make_pdf_file (PdfRestFileID .generate ())
781+ pfx_file = make_pfx_file (str (PdfRestFileID .generate ()))
782+ passphrase_file = make_passphrase_file (str (PdfRestFileID .generate ()))
783+ output_id = str (PdfRestFileID .generate ())
784+
785+ def handler (request : httpx .Request ) -> httpx .Response :
786+ if request .method == "POST" and request .url .path == "/signed-pdf" :
787+ payload = json .loads (request .content .decode ("utf-8" ))
788+ signature_payload = json .loads (payload ["signature_configuration" ])
789+ assert signature_payload ["logo_opacity" ] == pytest .approx (0.0 )
790+ assert signature_payload ["type" ] == "new"
791+ return httpx .Response (
792+ 200 ,
793+ json = {"inputId" : [input_file .id ], "outputId" : [output_id ]},
794+ )
795+ if request .method == "GET" and request .url .path == f"/resource/{ output_id } " :
796+ return httpx .Response (
797+ 200 ,
798+ json = build_file_info_payload (
799+ output_id ,
800+ "logo-opacity-zero.pdf" ,
801+ "application/pdf" ,
802+ ),
803+ )
804+ msg = f"Unexpected request { request .method } { request .url } "
805+ raise AssertionError (msg )
806+
807+ transport = httpx .MockTransport (handler )
808+ with PdfRestClient (api_key = VALID_API_KEY , transport = transport ) as client :
809+ response = client .sign_pdf (
810+ input_file ,
811+ signature_configuration = {
812+ "type" : "new" ,
813+ "name" : "visible-zero" ,
814+ "location" : make_signature_location (),
815+ "logo_opacity" : 0.0 ,
816+ },
817+ credentials = {"pfx" : pfx_file , "passphrase" : passphrase_file },
818+ )
819+
820+ assert isinstance (response , PdfRestFileBasedResponse )
821+ assert response .output_file .name == "logo-opacity-zero.pdf"
822+
823+
776824@pytest .mark .asyncio
777825async def test_async_sign_pdf_request_customization (
778826 monkeypatch : pytest .MonkeyPatch ,
@@ -849,6 +897,55 @@ def handler(request: httpx.Request) -> httpx.Response:
849897 assert seen == {"post" : 1 , "get" : 1 }
850898
851899
900+ @pytest .mark .asyncio
901+ async def test_async_sign_pdf_allows_zero_logo_opacity_via_public_argument (
902+ monkeypatch : pytest .MonkeyPatch ,
903+ ) -> None :
904+ monkeypatch .delenv ("PDFREST_API_KEY" , raising = False )
905+ input_file = make_pdf_file (PdfRestFileID .generate ())
906+ pfx_file = make_pfx_file (str (PdfRestFileID .generate ()))
907+ passphrase_file = make_passphrase_file (str (PdfRestFileID .generate ()))
908+ output_id = str (PdfRestFileID .generate ())
909+
910+ def handler (request : httpx .Request ) -> httpx .Response :
911+ if request .method == "POST" and request .url .path == "/signed-pdf" :
912+ payload = json .loads (request .content .decode ("utf-8" ))
913+ signature_payload = json .loads (payload ["signature_configuration" ])
914+ assert signature_payload ["logo_opacity" ] == pytest .approx (0.0 )
915+ assert signature_payload ["type" ] == "new"
916+ return httpx .Response (
917+ 200 ,
918+ json = {"inputId" : [input_file .id ], "outputId" : [output_id ]},
919+ )
920+ if request .method == "GET" and request .url .path == f"/resource/{ output_id } " :
921+ return httpx .Response (
922+ 200 ,
923+ json = build_file_info_payload (
924+ output_id ,
925+ "async-logo-opacity-zero.pdf" ,
926+ "application/pdf" ,
927+ ),
928+ )
929+ msg = f"Unexpected request { request .method } { request .url } "
930+ raise AssertionError (msg )
931+
932+ transport = httpx .MockTransport (handler )
933+ async with AsyncPdfRestClient (api_key = ASYNC_API_KEY , transport = transport ) as client :
934+ response = await client .sign_pdf (
935+ input_file ,
936+ signature_configuration = {
937+ "type" : "new" ,
938+ "name" : "async-visible-zero" ,
939+ "location" : make_signature_location (),
940+ "logo_opacity" : 0.0 ,
941+ },
942+ credentials = {"pfx" : pfx_file , "passphrase" : passphrase_file },
943+ )
944+
945+ assert isinstance (response , PdfRestFileBasedResponse )
946+ assert response .output_file .name == "async-logo-opacity-zero.pdf"
947+
948+
852949def test_sign_payload_requires_location_when_type_new () -> None :
853950 input_file = make_pdf_file (PdfRestFileID .generate ())
854951 pfx_file = make_pfx_file (str (PdfRestFileID .generate ()))
@@ -988,6 +1085,7 @@ def test_sign_payload_accepts_logo_tuple_sequence() -> None:
9881085@pytest .mark .parametrize (
9891086 "logo_opacity" ,
9901087 [
1088+ pytest .param (0.0 , id = "zero" ),
9911089 pytest .param (0.01 , id = "min" ),
9921090 pytest .param (1.0 , id = "max" ),
9931091 ],
@@ -1016,7 +1114,6 @@ def test_sign_payload_accepts_logo_opacity_bounds(logo_opacity: float) -> None:
10161114@pytest .mark .parametrize (
10171115 "invalid_logo_opacity" ,
10181116 [
1019- pytest .param (0.0 , id = "zero" ),
10201117 pytest .param (- 0.01 , id = "below-min" ),
10211118 pytest .param (1.01 , id = "above-max" ),
10221119 ],
@@ -1030,7 +1127,7 @@ def test_sign_payload_rejects_logo_opacity_out_of_bounds(
10301127
10311128 with pytest .raises (
10321129 ValidationError ,
1033- match = r"greater than 0|less than or equal to 1" ,
1130+ match = r"greater than or equal to 0|less than or equal to 1" ,
10341131 ):
10351132 PdfSignPayload .model_validate (
10361133 {
0 commit comments