|
39 | 39 | - When calling pdfRest, supply the API key via the `Api-Key` header (not |
40 | 40 | `Authorization: Bearer`); keep tests and client defaults in sync with this |
41 | 41 | convention. |
| 42 | +- Avoid `@field_validator` on payload models. Prefer existing `BeforeValidator` |
| 43 | + helpers (e.g., `_allowed_mime_types`) so validation remains declarative and |
| 44 | + consistent across schemas. |
42 | 45 | - Treat `PdfRestClient` and `AsyncPdfRestClient` as context managers in both |
43 | 46 | production code and tests so transports are disposed deterministically. |
44 | 47 | - When uploading content, always send the multipart field name `file`; when |
45 | 48 | uploading by URL, send a JSON payload using the `url` key with a list of |
46 | 49 | http/https addresses (single values are promoted to lists internally). |
| 50 | +- Always upload local assets before invoking an endpoint helper. Public client |
| 51 | + APIs must accept `PdfRestFile` objects (or sequences) rather than raw paths or |
| 52 | + ids, including optional resources such as compression profiles. Never expose |
| 53 | + `PdfRestFileID` in the interface—callers should upload the profile JSON, get |
| 54 | + the resulting `PdfRestFile`, then pass that object into helpers like |
| 55 | + `compress_pdf`. |
| 56 | +- When an endpoint supports both an inline upload parameter and an `*_id` |
| 57 | + variant, ignore the upload form and expose only the base parameter (without |
| 58 | + `_id`) typed as `PdfRestFile`. Serialize via `_serialize_as_first_file_id` |
| 59 | + with `serialization_alias` pointing to the server’s `*_id` field so requests |
| 60 | + always reference already-uploaded resources. |
47 | 61 | - `prepare_request` rejects mixed multipart (`files`) and JSON payloads; only |
48 | 62 | URL uploads (`create_from_urls`) should combine JSON bodies with the request. |
49 | 63 | - Replicate server-side safeguards when porting validation logic: the output |
|
111 | 125 |
|
112 | 126 | ## Testing Guidelines |
113 | 127 |
|
| 128 | +- **Live Test Requirement (Do Not Skip):** Every new endpoint or service must |
| 129 | + ship with a matching live pytest module under `tests/live/` before the work is |
| 130 | + considered complete. Mirror the naming/structure used by the graphic |
| 131 | + conversion suites: one module per endpoint, parameterized success cases that |
| 132 | + enumerate all accepted literals, at least one invalid input that hits the |
| 133 | + server, and coverage for any request options surfaced on the client. If an |
| 134 | + endpoint cannot be exercised live, call that out explicitly in the PR |
| 135 | + description with the reason and the follow-up plan; otherwise reviewers should |
| 136 | + block the change. Treat this as a release gate on par with unit tests. |
| 137 | + |
114 | 138 | - Write pytest tests: files named `test_*.py`, test functions `test_*`, fixtures |
115 | 139 | in `conftest.py` where shared. |
| 140 | + |
116 | 141 | - Ensure high-value coverage of public functions and edge cases; document intent |
117 | 142 | in test docstrings when non-obvious. |
| 143 | + |
118 | 144 | - Use `uvx nox -s tests` to exercise the full interpreter matrix locally when |
119 | 145 | validating compatibility. |
| 146 | + |
120 | 147 | - When writing live tests for URL uploads, first create the remote resources via |
121 | 148 | `create_from_paths`, then reuse the returned URLs in `create_from_urls` to |
122 | 149 | avoid relying on third-party availability. |
| 150 | + |
123 | 151 | - For parameterized tests prefer `pytest.param(..., id="short-label")` so test |
124 | 152 | IDs stay readable; make assertions for every relevant response attribute (name |
125 | 153 | prefix, MIME type, size, URLs, warnings). |
| 154 | + |
126 | 155 | - Avoid manual loops over test parameters; prefer `@pytest.mark.parametrize` |
127 | 156 | with explicit `id=` values so each combination is visible and reproducible. |
| 157 | + |
128 | 158 | - Always couple `pytest.raises` with an explicit `match=` regex that reflects |
129 | 159 | the intended validation error wording—mirror the human-readable text rather |
130 | 160 | than relying on default exception formatting. |
| 161 | + |
131 | 162 | - Mirror PNG’s request/response scenarios for each graphic conversion endpoint: |
132 | 163 | maintain per-endpoint test modules (`test_convert_to_png.py`, |
133 | 164 | `test_convert_to_bmp.py`, etc.) covering success, parameter customization, |
134 | 165 | validation errors, multi-file guards, and async flows. Keep shared payload |
135 | 166 | validation (output prefix and page-range cases) in a dedicated suite (e.g., |
136 | 167 | `tests/test_graphic_payload_validation.py`) that exercises every payload |
137 | 168 | model. |
| 169 | + |
138 | 170 | - When introducing additional pdfRest endpoints, follow the same pattern used |
139 | 171 | for graphic conversions: encapsulate shared request validation in a typed |
140 | 172 | payload model, expose fully named client methods, and create a dedicated test |
|
143 | 175 | checks (e.g., common field requirements, payload serialization) in shared |
144 | 176 | helper tests so new services inherit consistent coverage with minimal |
145 | 177 | duplication. |
| 178 | + |
146 | 179 | - Prefer `pytest.mark.parametrize` (with `pytest.param(..., id="...")`) over |
147 | | - explicit loops inside tests; nest parametrization for multi-dimensional |
148 | | - coverage so each case appears as an individual test item. |
| 180 | + explicit loops or copy/paste blocks—if only the input value or expected error |
| 181 | + changes, parameterize it so failures point to the exact case and reviewers |
| 182 | + don’t have to diff almost-identical code. Nest parametrization for |
| 183 | + multi-dimensional coverage so each combination appears as its own test item. |
| 184 | + |
149 | 185 | - Live tests should verify that literal enumerations match pdfRest’s accepted |
150 | 186 | values. Exercise format-specific options (e.g., each image format’s |
151 | 187 | `color_model`) individually, and run smoothing enumerations through every |
152 | 188 | enabled endpoint to confirm consistent server behaviour. Include “wildly” |
153 | 189 | invalid values (e.g., bogus literals or mixed lists) alongside boundary |
154 | 190 | failures so the server-side error messaging is exercised. |
| 191 | + |
155 | 192 | - Provide live integration tests under `tests/live/` (with an `__init__.py` so |
156 | 193 | pytest discovers the package) that introspect payload models to enumerate |
157 | 194 | valid/invalid literal values and numeric boundaries. These tests should vary a |
|
162 | 199 | exception surfaced by the client). When test fixtures produce deterministic |
163 | 200 | results (e.g., `tests/resources/report.pdf`), assert the concrete values |
164 | 201 | returned by pdfRest rather than only checking for presence or type. |
| 202 | + |
165 | 203 | - Use `tests/resources/20-pages.pdf` for high-page-count scenarios such as split |
166 | 204 | and merge endpoints so boundary coverage (multi-output splits, staggered page |
167 | 205 | selections) remains reproducible. Parameterize live split/merge tests to cover |
168 | 206 | multiple page-group patterns, and pair each success case with an invalid input |
169 | 207 | that reaches the server by overriding the JSON body via `extra_body`. |
| 208 | + |
170 | 209 | - Developers can load a pdfRest API key from `.env` during ad-hoc exploration. |
171 | 210 | The repo includes `python-dotenv`; call `load_dotenv()` (optionally pointing |
172 | 211 | to `.env`) in temporary scripts to drive the in-flight client against live |
|
0 commit comments