trillium_testing/assertions.rs
1/**
2assert that the status code of a conn is as specified.
3
4```
5use trillium_testing::prelude::*;
6async fn handler(conn: trillium::Conn) -> trillium::Conn {
7 conn.with_status(418)
8}
9
10
11assert_status!(get("/").on(&handler), 418);
12assert_status!(get("/").on(&handler), Status::ImATeapot);
13
14let conn = get("/").on(&handler);
15assert_status!(&conn, 418);
16assert_status!(conn, 418);
17```
18
19
20```rust,should_panic
21use trillium_testing::prelude::*;
22async fn handler(conn: trillium::Conn) -> trillium::Conn {
23 conn.ok("handled")
24}
25
26assert_status!(get("/").on(&handler), 418);
27```
28*/
29
30#[macro_export]
31macro_rules! assert_status {
32 ($conn:expr, $status:expr) => {{
33 use std::convert::TryInto;
34 let expected_status: $crate::prelude::Status =
35 $status.try_into().expect("expected a status code");
36
37 match $conn.status() {
38 Some(status) => assert_eq!(status, expected_status),
39 None => panic!("expected status code, but none was set"),
40 }
41 }};
42}
43
44/**
45assert that all of the following are true:
46* the status was not set
47* the body was not set
48* the conn was not halted
49
50```
51use trillium_testing::prelude::*;
52async fn handler(conn: trillium::Conn) -> trillium::Conn {
53 conn
54}
55
56
57assert_not_handled!(get("/").on(&handler));
58
59let conn = get("/").on(&handler);
60assert_not_handled!(&conn);
61assert_not_handled!(conn);
62```
63
64
65```rust,should_panic
66use trillium_testing::prelude::*;
67async fn handler(conn: trillium::Conn) -> trillium::Conn {
68 conn.ok("handled")
69}
70
71assert_not_handled!(get("/").on(&handler));
72```
73*/
74
75#[macro_export]
76macro_rules! assert_not_handled {
77 ($conn:expr) => {{
78 let conn = $conn;
79 assert_eq!(conn.status(), None);
80 assert!(conn.inner().response_body().is_none());
81 assert!(!conn.is_halted());
82 }};
83}
84
85/**
86assert that the response body is as specified. this assertion requires mutation of the conn.
87
88```
89use trillium_testing::prelude::*;
90async fn handler(conn: trillium::Conn) -> trillium::Conn {
91 conn.ok("it's-a-me, trillium")
92}
93
94
95assert_body!(get("/").on(&handler), "it's-a-me, trillium");
96
97let mut conn = get("/").on(&handler);
98assert_body!(&mut conn, "it's-a-me, trillium");
99
100let mut conn = get("/").on(&handler);
101assert_body!(conn, "it's-a-me, trillium");
102```
103
104
105```rust,should_panic
106use trillium_testing::prelude::*;
107assert_body!(get("/").on(&()), "what body?");
108```
109
110```rust,should_panic
111use trillium_testing::prelude::*;
112assert_body!(get("/").on(&"beach body"), "winter body");
113```
114*/
115
116#[macro_export]
117macro_rules! assert_body {
118 ($conn:expr, $body:expr) => {
119 match $conn.take_response_body_string().unwrap_or_default() {
120 body => {
121 assert_eq!(body.trim_end(), $body.trim_end());
122 }
123 }
124 };
125}
126
127/**
128
129asserts that the response body matches the specified pattern, using [`str::contains`]
130```
131use trillium_testing::prelude::*;
132let handler = "there's a needle in this haystack";
133assert_body_contains!(get("/").on(&handler), "needle");
134
135let mut conn = get("/").on(&handler);
136let body = assert_body_contains!(&mut conn, "needle");
137assert!(body.contains("haystack"));
138
139```
140
141
142```rust,should_panic
143use trillium_testing::prelude::*;
144assert_body_contains!(get("/").on(&()), "what body?");
145```
146
147```rust,should_panic
148use trillium_testing::prelude::*;
149assert_body_contains!(get("/").on(&"just a haystack"), "needle");
150```
151*/
152
153#[macro_export]
154macro_rules! assert_body_contains {
155 ($conn:expr, $pattern:expr) => {
156 match $conn.take_response_body_string().unwrap_or_default() {
157 body => {
158 assert!(
159 body.contains($pattern),
160 "\nexpected \n`{}`\n to contain `{}`\n but it did not",
161 &body,
162 $pattern
163 );
164
165 body
166 }
167 }
168 };
169}
170
171/**
172combines several other assertions. this assertion can be used to assert:
173* just a status code,
174* a status code and a response body, or
175* a status code, a response body, and any number of headers
176
177```
178use trillium_testing::prelude::*;
179async fn handler(conn: Conn) -> Conn {
180 conn.with_body("just tea stuff here")
181 .with_status(418)
182 .with_response_header("server", "zojirushi")
183}
184
185assert_response!(get("/").on(&handler), 418);
186assert_response!(get("/").on(&handler), Status::ImATeapot);
187assert_response!(get("/").on(&handler), 418, "just tea stuff here");
188assert_response!(get("/").on(&handler), Status::ImATeapot, "just tea stuff here");
189
190assert_response!(
191 get("/").on(&handler),
192 Status::ImATeapot,
193 "just tea stuff here",
194 "server" => "zojirushi",
195 "content-length" => "19"
196);
197
198```
199
200
201*/
202
203#[macro_export]
204macro_rules! assert_response {
205 ($conn:expr, $status:expr, $body:expr) => {{
206 let mut conn = $conn;
207 $crate::assert_status!(conn, $status);
208 $crate::assert_body!(conn, $body);
209 }};
210
211 ($conn:expr, $status:expr) => {
212 $crate::assert_status!($conn, $status);
213 };
214
215 ($conn:expr, $status:expr, $body:expr, $($header_name:literal => $header_value:expr,)+) => {
216 assert_response!($conn, $status, $body, $($header_name => $header_value),+);
217 };
218
219 ($conn:expr, $status:expr, $body:expr, $($header_name:literal => $header_value:expr),*) => {
220 let mut conn = $conn;
221 $crate::assert_response!(&mut conn, $status, $body);
222 $crate::assert_headers!(&conn, $($header_name => $header_value),*);
223 };
224
225}
226
227/**
228asserts any number of response headers
229
230```
231use trillium_testing::prelude::*;
232async fn handler(conn: Conn) -> Conn {
233 conn.ok("headers")
234 .with_response_header("server", "special-custom-server")
235 .with_response_header("request-id", "10")
236}
237
238assert_headers!(get("/").on(&handler), "server" => "special-custom-server");
239assert_headers!(
240 get("/").on(&handler),
241 "server" => "special-custom-server",
242 "request-id" => "10",
243 "content-length" => "7"
244);
245
246```
247*/
248#[macro_export]
249macro_rules! assert_headers {
250 (@pair, $conn:expr, $header_name:tt, None) => {
251 match $conn.inner().response_headers().get_str($header_name) {
252 actual => {
253 assert_eq!(actual, None, concat!("for header ", stringify!($header_name)));
254 }
255 };
256 };
257
258 (@pair, $conn:expr, $header_name:tt, $header_value:expr) => {
259 match ($conn.inner().response_headers().get_str($header_name), $header_value) {
260 (actual, expected) => {
261 assert_eq!(actual, Some(expected), concat!("for header ", stringify!($header_name)));
262 }
263 };
264 };
265
266 ($conn:expr, $($header_name:tt => $header_value:tt,)+) => {
267 assert_headers!($conn, $($header_name => $header_value),+);
268 };
269
270 ($conn:expr, $($header_name:tt => $header_value:tt),*) => {
271 match $conn {
272 conn => {
273 $(assert_headers!(@pair, conn, $header_name, $header_value);)*
274 }
275 };
276 }
277}
278
279/**
280assert_ok is like [`assert_response!`] except it always asserts a status of 200 Ok.
281
282it can be used to assert:
283* just that the response was successful,
284* that the response was successful and a response body, or
285* that the response was successful, a response body, and any number of headers
286
287```
288use trillium_testing::prelude::*;
289async fn handler(conn: Conn) -> Conn {
290 conn.ok("body")
291 .with_response_header("server", "special-custom-server")
292 .with_response_header("request-id", "10")
293}
294
295assert_ok!(get("/").on(&handler));
296assert_ok!(get("/").on(&handler), "body");
297assert_ok!(get("/").on(&handler), "body");
298assert_ok!(get("/").on(&handler), "body", "server" => "special-custom-server");
299
300assert_ok!(
301 get("/").on(&handler),
302 "body",
303 "server" => "special-custom-server",
304 "request-id" => "10",
305 "content-length" => "4"
306);
307
308```
309
310
311*/
312
313#[macro_export]
314macro_rules! assert_ok {
315 ($conn:expr) => {
316 $crate::assert_response!($conn, 200);
317 };
318
319 ($conn:expr, $body:expr) => {
320 $crate::assert_response!($conn, 200, $body);
321 };
322
323
324 ($conn:expr, $body:expr, $($header_name:literal => $header_value:expr,)+) => {
325 assert_ok!($conn, $body, $($header_name => $header_value),+);
326 };
327
328 ($conn:expr, $body:expr, $($header_name:literal => $header_value:expr),*) => {
329 $crate::assert_response!($conn, 200, $body, $($header_name => $header_value),*);
330 };
331}