Skip to main content

armature_testing/
assertions.rs

1// Test assertions for HTTP responses
2
3use crate::TestResponse;
4use armature_core::{HttpResponse, HttpStatus};
5
6/// Assert that a response has a specific status code
7pub fn assert_status(response: &TestResponse, expected: u16) {
8    let actual = response.status().unwrap_or(0);
9    assert_eq!(
10        actual, expected,
11        "Expected status {}, got {}",
12        expected, actual
13    );
14}
15
16/// Assert that a response has a specific HTTP status
17#[allow(dead_code)]
18pub fn assert_http_status(response: &HttpResponse, expected: HttpStatus) {
19    assert_eq!(
20        response.status,
21        expected.code(),
22        "Expected status {}, got {}",
23        expected.code(),
24        response.status
25    );
26}
27
28/// Assert that a response body contains JSON matching expected value
29pub fn assert_json<T>(response: &TestResponse, expected: &T)
30where
31    T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
32{
33    let actual: T = response
34        .body_json()
35        .expect("Failed to deserialize response body");
36    assert_eq!(actual, *expected, "JSON bodies do not match");
37}
38
39/// Assert that a response has a specific header
40pub fn assert_header(response: &TestResponse, key: &str, expected: &str) {
41    let actual = response.header(key).map(|s| s.as_str());
42    assert_eq!(
43        actual,
44        Some(expected),
45        "Expected header '{}' to be '{}', got {:?}",
46        key,
47        expected,
48        actual
49    );
50}
51
52/// Assert that a response body contains a string
53#[allow(dead_code)]
54pub fn assert_body_contains(response: &TestResponse, expected: &str) {
55    let body = response.body_string().unwrap_or_default();
56    assert!(
57        body.contains(expected),
58        "Expected body to contain '{}', but it didn't. Body: {}",
59        expected,
60        body
61    );
62}
63
64/// Assert that a response is successful (2xx status)
65#[allow(dead_code)]
66pub fn assert_success(response: &TestResponse) {
67    let status = response.status().unwrap_or(0);
68    assert!(
69        (200..300).contains(&status),
70        "Expected successful status (2xx), got {}",
71        status
72    );
73}
74
75/// Assert that a response is a client error (4xx status)
76#[allow(dead_code)]
77pub fn assert_client_error(response: &TestResponse) {
78    let status = response.status().unwrap_or(0);
79    assert!(
80        (400..500).contains(&status),
81        "Expected client error status (4xx), got {}",
82        status
83    );
84}
85
86/// Assert that a response is a server error (5xx status)
87#[allow(dead_code)]
88pub fn assert_server_error(response: &TestResponse) {
89    let status = response.status().unwrap_or(0);
90    assert!(
91        (500..600).contains(&status),
92        "Expected server error status (5xx), got {}",
93        status
94    );
95}
96
97/// Assert that a response has JSON content type
98#[allow(dead_code)]
99pub fn assert_json_content_type(response: &TestResponse) {
100    let content_type = response.header("Content-Type");
101    assert!(
102        content_type
103            .map(|ct| ct.contains("application/json"))
104            .unwrap_or(false),
105        "Expected JSON content type, got {:?}",
106        content_type
107    );
108}
109
110/// Assert that a response has HTML content type
111#[allow(dead_code)]
112pub fn assert_html_content_type(response: &TestResponse) {
113    let content_type = response.header("Content-Type");
114    assert!(
115        content_type
116            .map(|ct| ct.contains("text/html"))
117            .unwrap_or(false),
118        "Expected HTML content type, got {:?}",
119        content_type
120    );
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126    use armature_core::HttpResponse;
127
128    fn create_test_response(status: u16, body: &str) -> TestResponse {
129        let mut response = HttpResponse::new(status);
130        response.body = armature_core::Bytes::copy_from_slice(body.as_bytes());
131        TestResponse::Success(response)
132    }
133
134    #[test]
135    fn test_assert_status() {
136        let response = create_test_response(200, "OK");
137        assert_status(&response, 200);
138    }
139
140    #[test]
141    fn test_assert_success() {
142        let response = create_test_response(200, "OK");
143        assert_success(&response);
144    }
145
146    #[test]
147    fn test_assert_body_contains() {
148        let response = create_test_response(200, "Hello World");
149        assert_body_contains(&response, "Hello");
150    }
151
152    #[test]
153    fn test_assert_client_error() {
154        let response = create_test_response(404, "Not Found");
155        assert_client_error(&response);
156    }
157
158    #[test]
159    fn test_assert_server_error() {
160        let response = create_test_response(500, "Internal Error");
161        assert_server_error(&response);
162    }
163
164    #[test]
165    fn test_assert_json_content_type() {
166        let mut response = HttpResponse::ok();
167        response
168            .headers
169            .insert("Content-Type".to_string(), "application/json".to_string());
170        let test_response = TestResponse::Success(response);
171        assert_json_content_type(&test_response);
172    }
173
174    #[test]
175    fn test_assert_html_content_type() {
176        let mut response = HttpResponse::ok();
177        response
178            .headers
179            .insert("Content-Type".to_string(), "text/html".to_string());
180        let test_response = TestResponse::Success(response);
181        assert_html_content_type(&test_response);
182    }
183
184    #[test]
185    fn test_assert_header() {
186        let mut response = HttpResponse::ok();
187        response
188            .headers
189            .insert("X-Custom".to_string(), "value".to_string());
190        let test_response = TestResponse::Success(response);
191        assert_header(&test_response, "X-Custom", "value");
192    }
193
194    #[test]
195    fn test_assert_status_ranges() {
196        let response_200 = create_test_response(200, "OK");
197        let response_201 = create_test_response(201, "Created");
198        let response_204 = create_test_response(204, "No Content");
199
200        assert_success(&response_200);
201        assert_success(&response_201);
202        assert_success(&response_204);
203    }
204
205    #[test]
206    fn test_assert_various_4xx_errors() {
207        let response_400 = create_test_response(400, "Bad Request");
208        let response_401 = create_test_response(401, "Unauthorized");
209        let response_403 = create_test_response(403, "Forbidden");
210        let response_404 = create_test_response(404, "Not Found");
211
212        assert_client_error(&response_400);
213        assert_client_error(&response_401);
214        assert_client_error(&response_403);
215        assert_client_error(&response_404);
216    }
217
218    #[test]
219    fn test_assert_various_5xx_errors() {
220        let response_500 = create_test_response(500, "Internal Server Error");
221        let response_502 = create_test_response(502, "Bad Gateway");
222        let response_503 = create_test_response(503, "Service Unavailable");
223
224        assert_server_error(&response_500);
225        assert_server_error(&response_502);
226        assert_server_error(&response_503);
227    }
228
229    #[test]
230    fn test_assert_body_contains_multiple_strings() {
231        let response = create_test_response(200, "Hello World from Armature");
232        assert_body_contains(&response, "Hello");
233        assert_body_contains(&response, "World");
234        assert_body_contains(&response, "Armature");
235    }
236
237    #[test]
238    fn test_assert_empty_body() {
239        let response = create_test_response(204, "");
240        assert_body_contains(&response, ""); // Empty string should match
241    }
242}