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