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}