Skip to content

Commit 7487414

Browse files
watermark-pdf: Fix incomplete unit test coverage
Assisted-by: Codex
1 parent 6436ee2 commit 7487414

1 file changed

Lines changed: 233 additions & 0 deletions

File tree

tests/test_watermark_pdf.py

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,81 @@ def handler(request: httpx.Request) -> httpx.Response:
226226
assert timeout_value == pytest.approx(0.31)
227227

228228

229+
def test_watermark_pdf_with_image_request_customization(
230+
monkeypatch: pytest.MonkeyPatch,
231+
) -> None:
232+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
233+
input_file = make_pdf_file(PdfRestFileID.generate(1))
234+
watermark_file = make_pdf_file(PdfRestFileID.generate(1), name="sync-stamp.pdf")
235+
output_id = str(PdfRestFileID.generate())
236+
captured_timeout: dict[str, float | dict[str, float] | None] = {}
237+
238+
def handler(request: httpx.Request) -> httpx.Response:
239+
if request.method == "POST" and request.url.path == "/watermarked-pdf":
240+
assert request.url.params["trace"] == "img-sync"
241+
assert request.headers["X-Debug"] == "img-sync"
242+
captured_timeout["value"] = request.extensions.get("timeout")
243+
payload = json.loads(request.content.decode("utf-8"))
244+
assert payload["watermark_file_id"] == str(watermark_file.id)
245+
assert payload["watermark_file_scale"] == pytest.approx(0.65)
246+
assert payload["horizontal_alignment"] == "left"
247+
assert payload["vertical_alignment"] == "top"
248+
assert payload["x"] == -24
249+
assert payload["y"] == 48
250+
assert payload["rotation"] == 15
251+
assert payload["debug"] == "img-sync"
252+
assert payload["id"] == str(input_file.id)
253+
return httpx.Response(
254+
200,
255+
json={
256+
"inputId": [input_file.id, watermark_file.id],
257+
"outputId": [output_id],
258+
},
259+
)
260+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
261+
assert request.url.params["format"] == "info"
262+
assert request.url.params["trace"] == "img-sync"
263+
assert request.headers["X-Debug"] == "img-sync"
264+
return httpx.Response(
265+
200,
266+
json=build_file_info_payload(
267+
output_id,
268+
"img-sync.pdf",
269+
"application/pdf",
270+
),
271+
)
272+
msg = f"Unexpected request {request.method} {request.url}"
273+
raise AssertionError(msg)
274+
275+
transport = httpx.MockTransport(handler)
276+
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
277+
response = client.watermark_pdf_with_image(
278+
input_file,
279+
watermark_file=watermark_file,
280+
watermark_file_scale=0.65,
281+
horizontal_alignment="left",
282+
vertical_alignment="top",
283+
x=-24,
284+
y=48,
285+
rotation=15,
286+
extra_query={"trace": "img-sync"},
287+
extra_headers={"X-Debug": "img-sync"},
288+
extra_body={"debug": "img-sync"},
289+
timeout=0.57,
290+
)
291+
292+
assert isinstance(response, PdfRestFileBasedResponse)
293+
assert response.output_file.name == "img-sync.pdf"
294+
timeout_value = captured_timeout["value"]
295+
assert timeout_value is not None
296+
if isinstance(timeout_value, dict):
297+
assert all(
298+
component == pytest.approx(0.57) for component in timeout_value.values()
299+
)
300+
else:
301+
assert timeout_value == pytest.approx(0.57)
302+
303+
229304
def test_watermark_pdf_with_text_validation_rejects_invalid_text_color(
230305
monkeypatch: pytest.MonkeyPatch,
231306
) -> None:
@@ -303,6 +378,49 @@ def test_watermark_pdf_with_image_validation_rejects_non_pdf_watermark(
303378
client.watermark_pdf_with_image(input_file, watermark_file=bad_watermark)
304379

305380

381+
def test_watermark_pdf_with_text_validation_rejects_multiple_input_files(
382+
monkeypatch: pytest.MonkeyPatch,
383+
) -> None:
384+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
385+
input_file_one = make_pdf_file(PdfRestFileID.generate(1))
386+
input_file_two = make_pdf_file(PdfRestFileID.generate(1), name="second.pdf")
387+
with (
388+
PdfRestClient(
389+
api_key=VALID_API_KEY,
390+
transport=httpx.MockTransport(
391+
lambda _: (_ for _ in ()).throw(RuntimeError("Should not be called"))
392+
),
393+
) as client,
394+
pytest.raises(ValidationError, match="at most 1 item"),
395+
):
396+
client.watermark_pdf_with_text(
397+
[input_file_one, input_file_two],
398+
watermark_text="TooManyInputs",
399+
)
400+
401+
402+
def test_watermark_pdf_with_image_validation_rejects_multiple_watermark_files(
403+
monkeypatch: pytest.MonkeyPatch,
404+
) -> None:
405+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
406+
input_file = make_pdf_file(PdfRestFileID.generate(1))
407+
watermark_file_one = make_pdf_file(PdfRestFileID.generate(1), name="first.pdf")
408+
watermark_file_two = make_pdf_file(PdfRestFileID.generate(1), name="second.pdf")
409+
with (
410+
PdfRestClient(
411+
api_key=VALID_API_KEY,
412+
transport=httpx.MockTransport(
413+
lambda _: (_ for _ in ()).throw(RuntimeError("Should not be called"))
414+
),
415+
) as client,
416+
pytest.raises(ValidationError, match="at most 1 item"),
417+
):
418+
client.watermark_pdf_with_image(
419+
input_file,
420+
watermark_file=[watermark_file_one, watermark_file_two],
421+
)
422+
423+
306424
def test_watermark_pdf_with_text_validation_rejects_short_text_size(
307425
monkeypatch: pytest.MonkeyPatch,
308426
) -> None:
@@ -526,3 +644,118 @@ def handler(request: httpx.Request) -> httpx.Response:
526644
)
527645
else:
528646
assert timeout_value == pytest.approx(0.42)
647+
648+
649+
@pytest.mark.asyncio
650+
async def test_async_watermark_pdf_with_image_request_customization(
651+
monkeypatch: pytest.MonkeyPatch,
652+
) -> None:
653+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
654+
input_file = make_pdf_file(PdfRestFileID.generate(2))
655+
watermark_file = make_pdf_file(PdfRestFileID.generate(2), name="async-stamp.pdf")
656+
output_id = str(PdfRestFileID.generate())
657+
captured_timeout: dict[str, float | dict[str, float] | None] = {}
658+
659+
def handler(request: httpx.Request) -> httpx.Response:
660+
if request.method == "POST" and request.url.path == "/watermarked-pdf":
661+
assert request.url.params["trace"] == "img-async"
662+
assert request.headers["X-Debug"] == "img-async"
663+
captured_timeout["value"] = request.extensions.get("timeout")
664+
payload = json.loads(request.content.decode("utf-8"))
665+
assert payload["watermark_file_id"] == str(watermark_file.id)
666+
assert payload["watermark_file_scale"] == pytest.approx(0.25)
667+
assert payload["opacity"] == pytest.approx(0.85)
668+
assert payload["horizontal_alignment"] == "right"
669+
assert payload["vertical_alignment"] == "bottom"
670+
assert payload["x"] == 12
671+
assert payload["y"] == -18
672+
assert payload["rotation"] == 330
673+
assert payload["debug"] == "img-async"
674+
assert payload["id"] == str(input_file.id)
675+
return httpx.Response(
676+
200,
677+
json={
678+
"inputId": [input_file.id, watermark_file.id],
679+
"outputId": [output_id],
680+
},
681+
)
682+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
683+
assert request.url.params["format"] == "info"
684+
assert request.url.params["trace"] == "img-async"
685+
assert request.headers["X-Debug"] == "img-async"
686+
return httpx.Response(
687+
200,
688+
json=build_file_info_payload(
689+
output_id,
690+
"img-async.pdf",
691+
"application/pdf",
692+
),
693+
)
694+
msg = f"Unexpected request {request.method} {request.url}"
695+
raise AssertionError(msg)
696+
697+
transport = httpx.MockTransport(handler)
698+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
699+
response = await client.watermark_pdf_with_image(
700+
input_file,
701+
watermark_file=watermark_file,
702+
watermark_file_scale=0.25,
703+
opacity=0.85,
704+
horizontal_alignment="right",
705+
vertical_alignment="bottom",
706+
x=12,
707+
y=-18,
708+
rotation=330,
709+
extra_query={"trace": "img-async"},
710+
extra_headers={"X-Debug": "img-async"},
711+
extra_body={"debug": "img-async"},
712+
timeout=0.29,
713+
)
714+
715+
assert isinstance(response, PdfRestFileBasedResponse)
716+
assert response.output_file.name == "img-async.pdf"
717+
timeout_value = captured_timeout["value"]
718+
assert timeout_value is not None
719+
if isinstance(timeout_value, dict):
720+
assert all(
721+
component == pytest.approx(0.29) for component in timeout_value.values()
722+
)
723+
else:
724+
assert timeout_value == pytest.approx(0.29)
725+
726+
727+
@pytest.mark.asyncio
728+
async def test_async_watermark_pdf_with_text_validation_rejects_multiple_input_files(
729+
monkeypatch: pytest.MonkeyPatch,
730+
) -> None:
731+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
732+
input_file_one = make_pdf_file(PdfRestFileID.generate(2))
733+
input_file_two = make_pdf_file(PdfRestFileID.generate(2), name="second.pdf")
734+
transport = httpx.MockTransport(
735+
lambda _: (_ for _ in ()).throw(RuntimeError("Should not be called"))
736+
)
737+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
738+
with pytest.raises(ValidationError, match="at most 1 item"):
739+
await client.watermark_pdf_with_text(
740+
[input_file_one, input_file_two],
741+
watermark_text="TooManyInputs",
742+
)
743+
744+
745+
@pytest.mark.asyncio
746+
async def test_async_watermark_pdf_with_image_validation_rejects_multiple_watermark_files(
747+
monkeypatch: pytest.MonkeyPatch,
748+
) -> None:
749+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
750+
input_file = make_pdf_file(PdfRestFileID.generate(2))
751+
watermark_file_one = make_pdf_file(PdfRestFileID.generate(2), name="first.pdf")
752+
watermark_file_two = make_pdf_file(PdfRestFileID.generate(2), name="second.pdf")
753+
transport = httpx.MockTransport(
754+
lambda _: (_ for _ in ()).throw(RuntimeError("Should not be called"))
755+
)
756+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
757+
with pytest.raises(ValidationError, match="at most 1 item"):
758+
await client.watermark_pdf_with_image(
759+
input_file,
760+
watermark_file=[watermark_file_one, watermark_file_two],
761+
)

0 commit comments

Comments
 (0)