Skip to content

Commit 4ba6eba

Browse files
Add tests of ZIP tool
Assisted-by: Codex
1 parent dd4f818 commit 4ba6eba

2 files changed

Lines changed: 284 additions & 0 deletions

File tree

tests/live/test_live_zip.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from pdfrest import AsyncPdfRestClient, PdfRestApiError, PdfRestClient
6+
from pdfrest.models import PdfRestFile
7+
8+
from ..resources import get_test_resource_path
9+
10+
11+
@pytest.fixture(scope="module")
12+
def uploaded_zip_inputs(
13+
pdfrest_api_key: str,
14+
pdfrest_live_base_url: str,
15+
) -> list[PdfRestFile]:
16+
paths = [
17+
get_test_resource_path("report.pdf"),
18+
get_test_resource_path("report.docx"),
19+
]
20+
with PdfRestClient(
21+
api_key=pdfrest_api_key,
22+
base_url=pdfrest_live_base_url,
23+
) as client:
24+
return client.files.create_from_paths(paths)
25+
26+
27+
def test_live_zip_files(
28+
pdfrest_api_key: str,
29+
pdfrest_live_base_url: str,
30+
uploaded_zip_inputs: list[PdfRestFile],
31+
) -> None:
32+
with PdfRestClient(
33+
api_key=pdfrest_api_key,
34+
base_url=pdfrest_live_base_url,
35+
) as client:
36+
response = client.zip_files(
37+
uploaded_zip_inputs,
38+
output="live-zip",
39+
)
40+
41+
assert response.output_file.name.startswith("live-zip")
42+
assert response.output_file.name.endswith(".zip")
43+
assert response.output_file.type == "application/zip"
44+
assert response.output_file.size > 0
45+
assert {str(file.id) for file in uploaded_zip_inputs} == {
46+
str(file_id) for file_id in response.input_ids
47+
}
48+
49+
50+
def test_live_zip_files_invalid_id_override(
51+
pdfrest_api_key: str,
52+
pdfrest_live_base_url: str,
53+
uploaded_zip_inputs: list[PdfRestFile],
54+
) -> None:
55+
with (
56+
PdfRestClient(
57+
api_key=pdfrest_api_key,
58+
base_url=pdfrest_live_base_url,
59+
) as client,
60+
pytest.raises(PdfRestApiError, match="id"),
61+
):
62+
client.zip_files(
63+
uploaded_zip_inputs,
64+
extra_body={"id": "not-a-uuid"},
65+
)
66+
67+
68+
@pytest.mark.asyncio
69+
async def test_live_zip_files_async(
70+
pdfrest_api_key: str,
71+
pdfrest_live_base_url: str,
72+
uploaded_zip_inputs: list[PdfRestFile],
73+
) -> None:
74+
async with AsyncPdfRestClient(
75+
api_key=pdfrest_api_key,
76+
base_url=pdfrest_live_base_url,
77+
) as client:
78+
response = await client.zip_files(
79+
uploaded_zip_inputs,
80+
output="live-zip-async",
81+
extra_query={"trace": "async"},
82+
)
83+
84+
assert response.output_file.name.startswith("live-zip-async")
85+
assert response.output_file.name.endswith(".zip")
86+
assert response.output_file.type == "application/zip"
87+
assert response.output_file.size > 0
88+
assert {str(file.id) for file in uploaded_zip_inputs} == {
89+
str(file_id) for file_id in response.input_ids
90+
}

tests/test_zip_files.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
from __future__ import annotations
2+
3+
import json
4+
5+
import httpx
6+
import pytest
7+
from pydantic import ValidationError
8+
9+
from pdfrest import AsyncPdfRestClient, PdfRestClient
10+
from pdfrest.models import PdfRestFileBasedResponse, PdfRestFileID
11+
from pdfrest.models._internal import ZipPayload
12+
13+
from .graphics_test_helpers import (
14+
ASYNC_API_KEY,
15+
VALID_API_KEY,
16+
build_file_info_payload,
17+
make_pdf_file,
18+
)
19+
20+
21+
def test_zip_files_success(monkeypatch: pytest.MonkeyPatch) -> None:
22+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
23+
first = make_pdf_file(PdfRestFileID.generate(1), name="first.pdf")
24+
second = make_pdf_file(PdfRestFileID.generate(1), name="second.pdf")
25+
output_id = str(PdfRestFileID.generate())
26+
27+
payload_dump = ZipPayload.model_validate(
28+
{"files": [first, second], "output": "bundle"}
29+
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
30+
31+
seen: dict[str, int] = {"post": 0, "get": 0}
32+
33+
def handler(request: httpx.Request) -> httpx.Response:
34+
if request.method == "POST" and request.url.path == "/zip":
35+
seen["post"] += 1
36+
payload = json.loads(request.content.decode("utf-8"))
37+
assert payload == payload_dump
38+
return httpx.Response(
39+
200,
40+
json={
41+
"inputId": [first.id, second.id],
42+
"outputId": [output_id],
43+
},
44+
)
45+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
46+
seen["get"] += 1
47+
assert request.url.params["format"] == "info"
48+
return httpx.Response(
49+
200,
50+
json=build_file_info_payload(
51+
output_id,
52+
"bundle.zip",
53+
"application/zip",
54+
),
55+
)
56+
msg = f"Unexpected request {request.method} {request.url}"
57+
raise AssertionError(msg)
58+
59+
transport = httpx.MockTransport(handler)
60+
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
61+
response = client.zip_files([first, second], output="bundle")
62+
63+
assert seen == {"post": 1, "get": 1}
64+
assert isinstance(response, PdfRestFileBasedResponse)
65+
assert response.output_file.name == "bundle.zip"
66+
assert response.output_file.type == "application/zip"
67+
assert {str(file_id) for file_id in response.input_ids} == {
68+
str(first.id),
69+
str(second.id),
70+
}
71+
assert response.warning is None
72+
73+
74+
def test_zip_files_request_customization(monkeypatch: pytest.MonkeyPatch) -> None:
75+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
76+
source = make_pdf_file(PdfRestFileID.generate(1))
77+
output_id = str(PdfRestFileID.generate())
78+
captured_timeout: dict[str, float | dict[str, float] | None] = {}
79+
80+
def handler(request: httpx.Request) -> httpx.Response:
81+
if request.method == "POST" and request.url.path == "/zip":
82+
assert request.url.params["trace"] == "sync"
83+
assert request.headers["X-Debug"] == "sync"
84+
captured_timeout["value"] = request.extensions.get("timeout")
85+
payload = json.loads(request.content.decode("utf-8"))
86+
assert payload["id"] == [str(source.id)]
87+
assert payload["output"] == "custom-zip"
88+
assert payload["diagnostics"] == "on"
89+
return httpx.Response(
90+
200,
91+
json={
92+
"inputId": [source.id],
93+
"outputId": [output_id],
94+
},
95+
)
96+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
97+
assert request.url.params["format"] == "info"
98+
assert request.url.params["trace"] == "sync"
99+
assert request.headers["X-Debug"] == "sync"
100+
return httpx.Response(
101+
200,
102+
json=build_file_info_payload(
103+
output_id,
104+
"custom-zip.zip",
105+
"application/zip",
106+
),
107+
)
108+
msg = f"Unexpected request {request.method} {request.url}"
109+
raise AssertionError(msg)
110+
111+
transport = httpx.MockTransport(handler)
112+
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
113+
response = client.zip_files(
114+
source,
115+
output="custom-zip",
116+
extra_query={"trace": "sync"},
117+
extra_headers={"X-Debug": "sync"},
118+
extra_body={"diagnostics": "on"},
119+
timeout=0.5,
120+
)
121+
122+
assert isinstance(response, PdfRestFileBasedResponse)
123+
assert response.output_file.name == "custom-zip.zip"
124+
timeout_value = captured_timeout["value"]
125+
assert timeout_value is not None
126+
if isinstance(timeout_value, dict):
127+
assert all(pytest.approx(0.5) == value for value in timeout_value.values())
128+
else:
129+
assert timeout_value == pytest.approx(0.5)
130+
131+
132+
def test_zip_files_requires_input(monkeypatch: pytest.MonkeyPatch) -> None:
133+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
134+
transport = httpx.MockTransport(lambda request: (_ for _ in ()).throw(RuntimeError))
135+
136+
with (
137+
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
138+
pytest.raises(ValidationError, match="at least 1 item"),
139+
):
140+
client.zip_files([])
141+
142+
143+
def test_zip_files_rejects_invalid_output(monkeypatch: pytest.MonkeyPatch) -> None:
144+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
145+
source = make_pdf_file(PdfRestFileID.generate(1))
146+
transport = httpx.MockTransport(lambda request: (_ for _ in ()).throw(RuntimeError))
147+
148+
with (
149+
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
150+
pytest.raises(ValidationError, match="must not start with a `\\.`"),
151+
):
152+
client.zip_files(source, output=".hidden")
153+
154+
155+
@pytest.mark.asyncio
156+
async def test_async_zip_files(monkeypatch: pytest.MonkeyPatch) -> None:
157+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
158+
source = make_pdf_file(PdfRestFileID.generate(1))
159+
output_id = str(PdfRestFileID.generate())
160+
161+
payload_dump = ZipPayload.model_validate({"files": source}).model_dump(
162+
mode="json", by_alias=True, exclude_none=True, exclude_unset=True
163+
)
164+
165+
def handler(request: httpx.Request) -> httpx.Response:
166+
if request.method == "POST" and request.url.path == "/zip":
167+
payload = json.loads(request.content.decode("utf-8"))
168+
assert payload == payload_dump
169+
return httpx.Response(
170+
200,
171+
json={
172+
"inputId": [source.id],
173+
"outputId": [output_id],
174+
},
175+
)
176+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
177+
return httpx.Response(
178+
200,
179+
json=build_file_info_payload(
180+
output_id,
181+
"async.zip",
182+
"application/zip",
183+
),
184+
)
185+
msg = f"Unexpected request {request.method} {request.url}"
186+
raise AssertionError(msg)
187+
188+
transport = httpx.MockTransport(handler)
189+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
190+
response = await client.zip_files(source)
191+
192+
assert isinstance(response, PdfRestFileBasedResponse)
193+
assert response.output_file.name == "async.zip"
194+
assert str(response.input_id) == str(source.id)

0 commit comments

Comments
 (0)