cratefield_testing/
request.rs1use axum::body::Body;
5use axum::http::{HeaderValue, Method, Request, StatusCode, header};
6use axum::response::Response;
7use bytes::Bytes;
8use futures_core::Stream;
9use serde_json::Value;
10use std::pin::Pin;
11use std::task::{Context, Poll};
12
13pub async fn request_as(
26 router: &axum::Router,
27 method: Method,
28 path: &str,
29 bearer: &str,
30 json: Option<&str>,
31) -> TestResponse {
32 use tower::ServiceExt;
33 let mut builder = Request::builder()
34 .method(method)
35 .uri(path)
36 .header(header::AUTHORIZATION, format!("Bearer {bearer}"));
37 let body = match json {
38 Some(payload) => {
39 builder = builder.header(
40 header::CONTENT_TYPE,
41 HeaderValue::from_static("application/json"),
42 );
43 Body::from(payload.to_owned())
44 }
45 None => Body::empty(),
46 };
47 let request = builder.body(body).expect("request builds");
48 let response = router
49 .clone()
50 .oneshot(request)
51 .await
52 .expect("router answers");
53 TestResponse::from(response).await
54}
55
56pub async fn request(
63 router: &axum::Router,
64 method: Method,
65 path: &str,
66 json: Option<&str>,
67) -> TestResponse {
68 use tower::ServiceExt;
69 let mut builder = Request::builder().method(method).uri(path);
70 let body = match json {
71 Some(payload) => {
72 builder = builder.header(
73 header::CONTENT_TYPE,
74 HeaderValue::from_static("application/json"),
75 );
76 Body::from(payload.to_owned())
77 }
78 None => Body::empty(),
79 };
80 let request = builder.body(body).expect("request builds");
81 let response = router
82 .clone()
83 .oneshot(request)
84 .await
85 .expect("router answers");
86 TestResponse::from(response).await
87}
88
89pub async fn request_chunks(
100 router: &axum::Router,
101 method: Method,
102 path: &str,
103 chunks: Vec<Bytes>,
104) -> TestResponse {
105 use tower::ServiceExt;
106 let body = Body::from_stream(Chunks {
107 items: chunks.into_iter(),
108 });
109 let request = Request::builder()
110 .method(method)
111 .uri(path)
112 .header(
113 header::CONTENT_TYPE,
114 HeaderValue::from_static("application/octet-stream"),
115 )
116 .body(body)
117 .expect("request builds");
118 let response = router
119 .clone()
120 .oneshot(request)
121 .await
122 .expect("router answers");
123 TestResponse::from(response).await
124}
125
126struct Chunks {
129 items: std::vec::IntoIter<Bytes>,
130}
131
132impl Stream for Chunks {
133 type Item = Result<Bytes, std::convert::Infallible>;
134
135 fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
136 Poll::Ready(self.get_mut().items.next().map(Ok))
137 }
138}
139
140pub struct TestResponse {
142 pub status: StatusCode,
143 pub headers: axum::http::HeaderMap,
144 body: Bytes,
145}
146
147impl TestResponse {
148 pub(crate) async fn of(response: Response) -> Self {
151 Self::from(response).await
152 }
153
154 async fn from(response: Response) -> Self {
155 let (parts, body) = response.into_parts();
156 let body = axum::body::to_bytes(body, 1024 * 1024)
157 .await
158 .expect("test body reads");
159 Self {
160 status: parts.status,
161 headers: parts.headers,
162 body,
163 }
164 }
165
166 #[must_use]
172 pub fn json(&self) -> Value {
173 serde_json::from_slice(&self.body).expect("body is JSON")
174 }
175
176 #[must_use]
178 pub fn body(&self) -> &Bytes {
179 &self.body
180 }
181}