gitignore_template_generator/http_client/
api.rs

1pub use crate::http_client::impls::{MockClient, UreqClient};
2
3#[derive(Clone, PartialEq, Debug)]
4pub struct ProgramError {
5    pub message: String,
6    pub exit_status: i32,
7}
8
9pub trait HttpClient {
10    fn get(&self, url: &str) -> Result<String, ProgramError>;
11}
12
13#[cfg(test)]
14mod tests {
15    use super::*;
16    use crate::constant;
17    use mockito::Server;
18
19    mod ureq_client {
20        use super::*;
21
22        mod get {
23            use super::*;
24
25            mod success {
26                use super::*;
27
28                #[test]
29                fn it_fetches_data_as_string_when_200_response() {
30                    let mut mock_server = Server::new();
31                    let mock_body = "gitignore template for rust";
32                    let mock_uri = "/api/rust";
33                    let mock = mock_server
34                        .mock("GET", mock_uri)
35                        .with_status(200)
36                        .with_body(mock_body)
37                        .create();
38
39                    let server_url = mock_server.url();
40                    let http_client = UreqClient::default();
41
42                    let actual =
43                        http_client.get(&format!("{server_url}{mock_uri}"));
44                    let expected: Result<String, ProgramError> =
45                        Ok(String::from(mock_body));
46
47                    mock.assert();
48                    assert_eq!(actual, expected);
49                }
50
51                #[test]
52                fn it_fetches_data_as_string_from_given_server_url_when_200() {
53                    let mut mock_server = Server::new();
54                    let mock_body = "gitignore template for rust";
55                    let mock_uri = "/api/rust";
56                    let mock = mock_server
57                        .mock("GET", mock_uri)
58                        .with_status(200)
59                        .with_body(mock_body)
60                        .create();
61
62                    let server_url = mock_server.url();
63                    let http_client = UreqClient { server_url };
64
65                    let actual = http_client.get(mock_uri);
66                    let expected: Result<String, ProgramError> =
67                        Ok(String::from(mock_body));
68
69                    mock.assert();
70                    assert_eq!(actual, expected);
71                }
72            }
73
74            mod failure {
75                use super::*;
76
77                #[test]
78                fn it_fails_with_api_call_error_when_400_response() {
79                    let mut mock_server = Server::new();
80                    let mock_body = "error response";
81                    let mock_uri = "/api/rust";
82                    let mock = mock_server
83                        .mock("GET", mock_uri)
84                        .with_status(400)
85                        .with_body(mock_body)
86                        .create();
87
88                    let server_url = mock_server.url();
89                    let http_client = UreqClient::default();
90
91                    let actual =
92                        http_client.get(&format!("{server_url}{mock_uri}"));
93                    let expected: Result<String, ProgramError> =
94                        Err(ProgramError {
95                            message: constant::error_messages::API_CALL_FAILURE
96                                .replace(
97                                    "{error}",
98                                    constant::error_messages::HTTP_400,
99                                ),
100                            exit_status: constant::exit_status::GENERIC,
101                        });
102
103                    mock.assert();
104                    assert_eq!(actual, expected);
105                }
106
107                #[test]
108                fn it_fails_with_body_parsing_error_when_invalid_body() {
109                    let mut mock_server = Server::new();
110                    let mock_body = vec![0, 159, 146, 150];
111                    let mock_uri = "/api/rust";
112                    let mock = mock_server
113                        .mock("GET", mock_uri)
114                        .with_status(200)
115                        .with_body(mock_body)
116                        .create();
117
118                    let server_url = mock_server.url();
119                    let http_client = UreqClient::default();
120
121                    let actual =
122                        http_client.get(&format!("{server_url}{mock_uri}"));
123                    let expected: Result<String, ProgramError> =
124                        Err(ProgramError {
125                            message: String::from(
126                                constant::error_messages::BODY_PARSING_ISSUE,
127                            ),
128                            exit_status:
129                                constant::exit_status::BODY_PARSING_ISSUE,
130                        });
131
132                    mock.assert();
133                    assert_eq!(actual, expected);
134                }
135            }
136        }
137    }
138
139    mod mock_client {
140        use super::*;
141
142        mod get {
143            use super::*;
144
145            mod success {
146                use super::*;
147
148                #[test]
149                fn it_returns_ok_mocked_response() {
150                    let result_content = "success response";
151                    let http_client = MockClient {
152                        response: Ok(String::from(result_content)),
153                    };
154
155                    let actual = http_client.get("/api/rust");
156                    let expected: Result<String, ProgramError> =
157                        Ok(String::from(result_content));
158
159                    assert_eq!(actual, expected);
160                }
161
162                #[test]
163                fn it_returns_error_mocked_response() {
164                    let result_content = "error response";
165                    let http_client = MockClient {
166                        response: Err(ProgramError {
167                            message: String::from(result_content),
168                            exit_status: constant::exit_status::GENERIC,
169                        }),
170                    };
171
172                    let actual = http_client.get("/api/rust");
173                    let expected: Result<String, ProgramError> =
174                        Err(ProgramError {
175                            message: String::from(result_content),
176                            exit_status: constant::exit_status::GENERIC,
177                        });
178
179                    assert_eq!(actual, expected);
180                }
181            }
182        }
183    }
184}