The suite runs against mock servers written from the upstream source, so
it cannot catch a place where a real server disagrees with that reading.
`examples/smoke_test.rs` can: it lists every resource, checks the
pagination walk against a single oversized request, probes the per_page
cap, and exercises statics, search and health_check. The upload wire
format (POST plus `_method=PUT`) was read from the framework source
rather than observed, so its write tier is the real verification of it.
It prints PASS/FAIL per check and never the contents of a record.
Writes are guarded. `IN_SMOKE_WRITE_HOST` must equal the host in
`IN_BASE_URL`, so a write can only reach a server that was named
explicitly. `IN_BASE_URL` has no default, unlike the other example,
because defaulting to the hosted app is the wrong failure for a tool
that can write. The write tier leaves a gap in the client number
sequence and a soft-deleted row even after cleanup, so it is documented
as disposable-instance only.
Running it against a dead port exposed a diagnosability gap:
`Error::Http` printed "error sending request for url (...)" and nothing
else. reqwest's Display stops at the outermost layer, and the reason
("Connection refused", a DNS failure, a TLS error) lives in `source()`.
The error now renders its whole cause chain.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Covers Clients, Invoices, Quotes, Credits, Payments, Products, Expenses,
Projects, Tasks, and Vendors, each with list, list_all, get, create,
update, and delete, generated by the resource_methods! macro.
Every model carries a #[serde(flatten)] extra map so fields the API
returns but the crate does not model survive a get/update round-trip
instead of being silently dropped.
Includes a Nix dev shell (Rust via rust-overlay), a GitHub Actions CI
workflow running build/test/fmt/clippy, and round-trip tests for the
extra-preservation invariant.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>