1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! Test helpers for `api-bones` consumers.
//!
//! Provides builder ergonomics for api-bones types and assertion helpers for
//! axum and reqwest responses so services share a single test vocabulary.
//!
//! # Feature flags
//!
//! | Feature | Adds |
//! |---------|------|
//! | `builders` (default) | [`builders`] — pure-Rust builders, no IO |
//! | `axum` | [`axum`] — `axum-test` assertion helpers and `TestServer` |
//! | `reqwest` | [`reqwest`] — reqwest assertion helpers |
//! | `nats` | [`nats`] — `JetStream` `AuditCapture` fixture |
//!
//! # Quick start — builders
//!
//! ```rust,ignore
//! use api_bones::error::ErrorCode;
//! use api_bones_test::builders::{FakeApiResponse, FakePaginated, FakeProblem};
//!
//! let resp = FakeApiResponse::new(42u32).build();
//! assert_eq!(resp.data, 42);
//!
//! let page = FakePaginated::new(vec![1u32, 2, 3]).build();
//! assert_eq!(page.total_count, 3);
//!
//! let err = FakeProblem::new(ErrorCode::ValidationFailed)
//! .field("/email", "must be a valid email")
//! .build();
//! assert!(!err.errors.is_empty());
//! ```
//!
//! # Quick start — axum assertions
//!
//! ```rust,no_run
//! # #[cfg(feature = "axum")]
//! # async fn run() {
//! use axum::Router;
//! use api_bones_test::axum::TestServer;
//!
//! let app = Router::new(); // your router
//! let server = TestServer::new(app);
//! let payload: u32 = server.get_envelope("/items/1").await;
//! # }
//! ```
//!
//! # Quick start — reqwest assertions
//!
//! ```rust,no_run
//! # #[cfg(feature = "reqwest")]
//! # async fn run() {
//! use api_bones_test::reqwest::assert_envelope_reqwest;
//!
//! let client = ::reqwest::Client::new();
//! let resp = client.get("http://localhost:3000/items/1").send().await.unwrap();
//! let payload: u32 = assert_envelope_reqwest(resp).await;
//! # }
//! ```
//!
//! # Quick start — NATS audit capture
//!
//! ```rust,no_run
//! # #[cfg(feature = "nats")]
//! # async fn run() {
//! use std::time::Duration;
//! use api_bones_test::nats::AuditCapture;
//!
//! // Requires a running NATS server (use testcontainers in CI)
//! let client = async_nats::connect("nats://localhost:4222").await.unwrap();
//! let capture = AuditCapture::new(&client, "my-service").await.unwrap();
//! capture.assert_no_events(Duration::from_millis(100)).await;
//! # }
//! ```