Skip to content

Commit db03096

Browse files
Test Export Form Data
Assisted-by: Codex
1 parent 2f72cb1 commit db03096

2 files changed

Lines changed: 391 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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_pdf_with_forms(
13+
pdfrest_api_key: str,
14+
pdfrest_live_base_url: str,
15+
) -> PdfRestFile:
16+
resource = get_test_resource_path("form_with_data.pdf")
17+
with PdfRestClient(
18+
api_key=pdfrest_api_key,
19+
base_url=pdfrest_live_base_url,
20+
) as client:
21+
return client.files.create_from_paths([resource])[0]
22+
23+
24+
@pytest.mark.parametrize(
25+
"data_format",
26+
[
27+
pytest.param("xml", id="xml"),
28+
pytest.param("xfdf", id="xfdf"),
29+
],
30+
)
31+
def test_live_export_form_data(
32+
pdfrest_api_key: str,
33+
pdfrest_live_base_url: str,
34+
uploaded_pdf_with_forms: PdfRestFile,
35+
data_format: str,
36+
) -> None:
37+
with PdfRestClient(
38+
api_key=pdfrest_api_key,
39+
base_url=pdfrest_live_base_url,
40+
) as client:
41+
response = client.export_form_data(
42+
uploaded_pdf_with_forms,
43+
data_format=data_format, # type: ignore[arg-type]
44+
output=f"exported-{data_format}",
45+
)
46+
47+
assert response.output_files
48+
output_file = response.output_file
49+
assert output_file.name.startswith(f"exported-{data_format}")
50+
assert str(response.input_id) == str(uploaded_pdf_with_forms.id)
51+
52+
53+
@pytest.mark.asyncio
54+
async def test_live_async_export_form_data_success(
55+
pdfrest_api_key: str,
56+
pdfrest_live_base_url: str,
57+
uploaded_pdf_with_forms: PdfRestFile,
58+
) -> None:
59+
async with AsyncPdfRestClient(
60+
api_key=pdfrest_api_key,
61+
base_url=pdfrest_live_base_url,
62+
) as client:
63+
response = await client.export_form_data(
64+
uploaded_pdf_with_forms,
65+
data_format="xml",
66+
output="async-exported",
67+
)
68+
69+
assert response.output_files
70+
output_file = response.output_file
71+
assert output_file.name.startswith("async-exported")
72+
assert str(response.input_id) == str(uploaded_pdf_with_forms.id)
73+
74+
75+
def test_live_export_form_data_invalid_format_for_pdf_type(
76+
pdfrest_api_key: str,
77+
pdfrest_live_base_url: str,
78+
uploaded_pdf_with_forms: PdfRestFile,
79+
) -> None:
80+
with (
81+
PdfRestClient(
82+
api_key=pdfrest_api_key,
83+
base_url=pdfrest_live_base_url,
84+
) as client,
85+
pytest.raises(PdfRestApiError, match=r"(?i)data_format"),
86+
):
87+
client.export_form_data(
88+
uploaded_pdf_with_forms,
89+
data_format="xdp", # type: ignore[arg-type]
90+
)
91+
92+
93+
@pytest.mark.asyncio
94+
async def test_live_async_export_form_data_invalid_format_for_pdf_type(
95+
pdfrest_api_key: str,
96+
pdfrest_live_base_url: str,
97+
uploaded_pdf_with_forms: PdfRestFile,
98+
) -> None:
99+
async with AsyncPdfRestClient(
100+
api_key=pdfrest_api_key,
101+
base_url=pdfrest_live_base_url,
102+
) as client:
103+
with pytest.raises(PdfRestApiError, match=r"(?i)data_format"):
104+
await client.export_form_data(
105+
uploaded_pdf_with_forms,
106+
data_format="xdp", # type: ignore[arg-type]
107+
)

tests/test_export_form_data.py

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
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 PdfRestFile, PdfRestFileBasedResponse, PdfRestFileID
11+
from pdfrest.models._internal import PdfExportFormDataPayload
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_export_form_data_success(monkeypatch: pytest.MonkeyPatch) -> None:
22+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
23+
input_file = make_pdf_file(PdfRestFileID.generate(1))
24+
output_id = str(PdfRestFileID.generate())
25+
26+
payload_dump = PdfExportFormDataPayload.model_validate(
27+
{"files": [input_file], "data_format": "xml", "output": "exported-data"}
28+
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
29+
30+
seen: dict[str, int] = {"post": 0, "get": 0}
31+
32+
def handler(request: httpx.Request) -> httpx.Response:
33+
if request.method == "POST" and request.url.path == "/exported-form-data":
34+
seen["post"] += 1
35+
payload = json.loads(request.content.decode("utf-8"))
36+
assert payload == payload_dump
37+
return httpx.Response(
38+
200,
39+
json={
40+
"inputId": [input_file.id],
41+
"outputId": [output_id],
42+
},
43+
)
44+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
45+
seen["get"] += 1
46+
assert request.url.params["format"] == "info"
47+
return httpx.Response(
48+
200,
49+
json=build_file_info_payload(
50+
output_id,
51+
"exported-data.xml",
52+
"application/xml",
53+
),
54+
)
55+
msg = f"Unexpected request {request.method} {request.url}"
56+
raise AssertionError(msg)
57+
58+
transport = httpx.MockTransport(handler)
59+
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
60+
response = client.export_form_data(
61+
input_file,
62+
data_format="xml",
63+
output="exported-data",
64+
)
65+
66+
assert seen == {"post": 1, "get": 1}
67+
assert isinstance(response, PdfRestFileBasedResponse)
68+
assert response.output_file.name == "exported-data.xml"
69+
assert response.output_file.type == "application/xml"
70+
assert str(response.input_id) == str(input_file.id)
71+
assert response.warning is None
72+
73+
74+
def test_export_form_data_request_customization(
75+
monkeypatch: pytest.MonkeyPatch,
76+
) -> None:
77+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
78+
input_file = make_pdf_file(PdfRestFileID.generate(1))
79+
output_id = str(PdfRestFileID.generate())
80+
captured_timeout: dict[str, float | dict[str, float] | None] = {}
81+
82+
def handler(request: httpx.Request) -> httpx.Response:
83+
if request.method == "POST" and request.url.path == "/exported-form-data":
84+
assert request.url.params["trace"] == "true"
85+
assert request.headers["X-Debug"] == "sync"
86+
captured_timeout["value"] = request.extensions.get("timeout")
87+
payload = json.loads(request.content.decode("utf-8"))
88+
assert payload["id"] == str(input_file.id)
89+
assert payload["data_format"] == "fdf"
90+
assert payload["output"] == "custom-data"
91+
assert payload["flag"] == "yes"
92+
return httpx.Response(
93+
200,
94+
json={
95+
"inputId": [input_file.id],
96+
"outputId": [output_id],
97+
},
98+
)
99+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
100+
assert request.url.params["format"] == "info"
101+
assert request.url.params["trace"] == "true"
102+
assert request.headers["X-Debug"] == "sync"
103+
return httpx.Response(
104+
200,
105+
json=build_file_info_payload(
106+
output_id,
107+
"custom-data.fdf",
108+
"application/vnd.fdf",
109+
),
110+
)
111+
msg = f"Unexpected request {request.method} {request.url}"
112+
raise AssertionError(msg)
113+
114+
transport = httpx.MockTransport(handler)
115+
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
116+
response = client.export_form_data(
117+
input_file,
118+
data_format="fdf",
119+
output="custom-data",
120+
extra_query={"trace": "true"},
121+
extra_headers={"X-Debug": "sync"},
122+
extra_body={"flag": "yes"},
123+
timeout=0.37,
124+
)
125+
126+
assert isinstance(response, PdfRestFileBasedResponse)
127+
assert response.output_file.name == "custom-data.fdf"
128+
timeout_value = captured_timeout["value"]
129+
assert timeout_value is not None
130+
if isinstance(timeout_value, dict):
131+
assert all(
132+
component == pytest.approx(0.37) for component in timeout_value.values()
133+
)
134+
else:
135+
assert timeout_value == pytest.approx(0.37)
136+
137+
138+
@pytest.mark.asyncio
139+
async def test_async_export_form_data_success(
140+
monkeypatch: pytest.MonkeyPatch,
141+
) -> None:
142+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
143+
input_file = make_pdf_file(PdfRestFileID.generate(2))
144+
output_id = str(PdfRestFileID.generate())
145+
146+
payload_dump = PdfExportFormDataPayload.model_validate(
147+
{"files": [input_file], "data_format": "xfdf"}
148+
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
149+
150+
seen: dict[str, int] = {"post": 0, "get": 0}
151+
152+
def handler(request: httpx.Request) -> httpx.Response:
153+
if request.method == "POST" and request.url.path == "/exported-form-data":
154+
seen["post"] += 1
155+
payload = json.loads(request.content.decode("utf-8"))
156+
assert payload == payload_dump
157+
return httpx.Response(
158+
200,
159+
json={
160+
"inputId": [input_file.id],
161+
"outputId": [output_id],
162+
},
163+
)
164+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
165+
seen["get"] += 1
166+
assert request.url.params["format"] == "info"
167+
return httpx.Response(
168+
200,
169+
json=build_file_info_payload(
170+
output_id,
171+
"async-data.xfdf",
172+
"application/vnd.adobe.xfdf",
173+
),
174+
)
175+
msg = f"Unexpected request {request.method} {request.url}"
176+
raise AssertionError(msg)
177+
178+
transport = httpx.MockTransport(handler)
179+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
180+
response = await client.export_form_data(input_file, data_format="xfdf")
181+
182+
assert seen == {"post": 1, "get": 1}
183+
assert isinstance(response, PdfRestFileBasedResponse)
184+
assert response.output_file.name == "async-data.xfdf"
185+
assert response.output_file.type == "application/vnd.adobe.xfdf"
186+
assert str(response.input_id) == str(input_file.id)
187+
188+
189+
@pytest.mark.asyncio
190+
async def test_async_export_form_data_request_customization(
191+
monkeypatch: pytest.MonkeyPatch,
192+
) -> None:
193+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
194+
input_file = make_pdf_file(PdfRestFileID.generate(2))
195+
output_id = str(PdfRestFileID.generate())
196+
captured_timeout: dict[str, float | dict[str, float] | None] = {}
197+
198+
def handler(request: httpx.Request) -> httpx.Response:
199+
if request.method == "POST" and request.url.path == "/exported-form-data":
200+
assert request.url.params["trace"] == "async"
201+
assert request.headers["X-Debug"] == "async"
202+
captured_timeout["value"] = request.extensions.get("timeout")
203+
payload = json.loads(request.content.decode("utf-8"))
204+
assert payload["id"] == str(input_file.id)
205+
assert payload["data_format"] == "xml"
206+
assert payload["note"] == "details"
207+
return httpx.Response(
208+
200,
209+
json={
210+
"inputId": [input_file.id],
211+
"outputId": [output_id],
212+
},
213+
)
214+
if request.method == "GET" and request.url.path == f"/resource/{output_id}":
215+
assert request.url.params["format"] == "info"
216+
assert request.url.params["trace"] == "async"
217+
assert request.headers["X-Debug"] == "async"
218+
return httpx.Response(
219+
200,
220+
json=build_file_info_payload(
221+
output_id,
222+
"async-custom.xml",
223+
"application/xml",
224+
),
225+
)
226+
msg = f"Unexpected request {request.method} {request.url}"
227+
raise AssertionError(msg)
228+
229+
transport = httpx.MockTransport(handler)
230+
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
231+
response = await client.export_form_data(
232+
input_file,
233+
data_format="xml",
234+
extra_query={"trace": "async"},
235+
extra_headers={"X-Debug": "async"},
236+
extra_body={"note": "details"},
237+
timeout=0.62,
238+
)
239+
240+
assert isinstance(response, PdfRestFileBasedResponse)
241+
assert response.output_file.name == "async-custom.xml"
242+
timeout_value = captured_timeout["value"]
243+
assert timeout_value is not None
244+
if isinstance(timeout_value, dict):
245+
assert all(
246+
component == pytest.approx(0.62) for component in timeout_value.values()
247+
)
248+
else:
249+
assert timeout_value == pytest.approx(0.62)
250+
251+
252+
def test_export_form_data_validation(monkeypatch: pytest.MonkeyPatch) -> None:
253+
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
254+
pdf_file = make_pdf_file(PdfRestFileID.generate(1))
255+
png_file = PdfRestFile.model_validate(
256+
build_file_info_payload(
257+
PdfRestFileID.generate(),
258+
"example.png",
259+
"image/png",
260+
)
261+
)
262+
transport = httpx.MockTransport(lambda request: (_ for _ in ()).throw(RuntimeError))
263+
264+
with (
265+
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
266+
pytest.raises(ValidationError, match="Must be a PDF file"),
267+
):
268+
client.export_form_data(png_file, data_format="xml")
269+
270+
with (
271+
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
272+
pytest.raises(ValidationError, match="Input should be 'fdf'"),
273+
):
274+
client.export_form_data(pdf_file, data_format="yaml") # type: ignore[arg-type]
275+
276+
with (
277+
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
278+
pytest.raises(
279+
ValidationError, match="List should have at most 1 item after validation"
280+
),
281+
):
282+
client.export_form_data(
283+
[pdf_file, make_pdf_file(PdfRestFileID.generate())], data_format="xml"
284+
)

0 commit comments

Comments
 (0)