oxidite_testing/
request.rs

1use http::{Method, HeaderMap, HeaderName, HeaderValue};
2use http_body_util::Full;
3use bytes::Bytes;
4use serde::Serialize;
5
6/// Test request builder
7pub struct TestRequest {
8    method: Method,
9    uri: String,
10    headers: HeaderMap,
11    body: Vec<u8>,
12}
13
14impl TestRequest {
15    /// Create a new test request builder
16    pub fn new(method: Method, uri: impl Into<String>) -> Self {
17        Self {
18            method,
19            uri: uri.into(),
20            headers: HeaderMap::new(),
21            body: Vec::new(),
22        }
23    }
24
25    /// Create a GET request
26    pub fn get(uri: impl Into<String>) -> Self {
27        Self::new(Method::GET, uri)
28    }
29
30    /// Create a POST request
31    pub fn post(uri: impl Into<String>) -> Self {
32        Self::new(Method::POST, uri)
33    }
34
35    /// Create a PUT request
36    pub fn put(uri: impl Into<String>) -> Self {
37        Self::new(Method::PUT, uri)
38    }
39
40    /// Create a DELETE request
41    pub fn delete(uri: impl Into<String>) -> Self {
42        Self::new(Method::DELETE, uri)
43    }
44
45    /// Add a header
46    pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
47        let name = HeaderName::from_bytes(name.into().as_bytes()).unwrap();
48        let value = HeaderValue::from_str(&value.into()).unwrap();
49        self.headers.insert(name, value);
50        self
51    }
52
53    /// Set JSON body
54    pub fn json<T: Serialize>(mut self, body: &T) -> Self {
55        self.body = serde_json::to_vec(body).unwrap();
56        self = self.header("content-type", "application/json");
57        self
58    }
59
60    /// Set raw body
61    pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
62        self.body = body.into();
63        self
64    }
65
66    /// Build the request
67    pub fn build(self) -> http::Request<Full<Bytes>> {
68        let mut builder = http::Request::builder()
69            .method(self.method)
70            .uri(self.uri);
71
72        for (name, value) in self.headers.iter() {
73            builder = builder.header(name, value);
74        }
75
76        builder.body(Full::new(Bytes::from(self.body))).unwrap()
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use serde::Deserialize;
84
85    #[derive(Serialize, Deserialize)]
86    struct TestData {
87        name: String,
88    }
89
90    #[test]
91    fn test_request_builder() {
92        let data = TestData {
93            name: "test".to_string(),
94        };
95
96        let request = TestRequest::post("/api/test")
97            .json(&data)
98            .header("x-custom", "value")
99            .build();
100
101        assert_eq!(request.method(), Method::POST);
102        assert_eq!(request.uri(), "/api/test");
103        assert!(request.headers().contains_key("content-type"));
104    }
105}