gitignore_template_generator/http_client/
api.rs

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