@@ -31,6 +31,15 @@ impl ReqwestGitHubApiClient {
31
31
. send ( )
32
32
. await
33
33
. with_context ( || format ! ( "Failed to send request to GitHub API: {}" , url) ) ?;
34
+ match response. status ( ) {
35
+ reqwest:: StatusCode :: OK => { }
36
+ status => {
37
+ return Err ( anyhow ! (
38
+ "GitHub API request failed with status code: {}" ,
39
+ status
40
+ ) ) ;
41
+ }
42
+ }
34
43
let body = response. text ( ) . await ?;
35
44
let parsed_body = serde_json:: from_str :: < T > ( & body)
36
45
. with_context ( || format ! ( "Failed to parse response from GitHub API: {:?}" , body) ) ?;
@@ -91,3 +100,86 @@ impl GitHubReleaseRetriever for ReqwestGitHubApiClient {
91
100
Ok ( releases)
92
101
}
93
102
}
103
+
104
+ #[ cfg( test) ]
105
+ mod tests {
106
+ use httpmock:: { Method :: GET , MockServer } ;
107
+ use reqwest:: StatusCode ;
108
+ use serde:: Deserialize ;
109
+
110
+ use super :: * ;
111
+
112
+ #[ derive( Debug , Deserialize , PartialEq ) ]
113
+ struct FakeApiResponse {
114
+ key : String ,
115
+ }
116
+
117
+ #[ tokio:: test]
118
+ async fn download_succeeds_with_valid_json ( ) {
119
+ let server = MockServer :: start ( ) ;
120
+ let _mock = server. mock ( |when, then| {
121
+ when. method ( GET ) . path ( "/endpoint" ) ;
122
+ then. status ( 200 ) . body ( r#"{ "key": "value" }"# ) ;
123
+ } ) ;
124
+ let client = ReqwestGitHubApiClient :: new ( ) . unwrap ( ) ;
125
+
126
+ let result: FakeApiResponse = client
127
+ . download ( format ! ( "{}/endpoint" , server. base_url( ) ) )
128
+ . await
129
+ . unwrap ( ) ;
130
+
131
+ assert_eq ! (
132
+ result,
133
+ FakeApiResponse {
134
+ key: "value" . into( )
135
+ }
136
+ ) ;
137
+ }
138
+
139
+ #[ tokio:: test]
140
+ async fn download_fails_on_invalid_json ( ) {
141
+ let server = MockServer :: start ( ) ;
142
+ let _mock = server. mock ( |when, then| {
143
+ when. method ( GET ) . path ( "/endpoint" ) ;
144
+ then. status ( 200 ) . body ( "this is not json" ) ;
145
+ } ) ;
146
+ let client = ReqwestGitHubApiClient :: new ( ) . unwrap ( ) ;
147
+
148
+ let result: MithrilResult < FakeApiResponse > = client
149
+ . download ( format ! ( "{}/endpoint" , server. base_url( ) ) )
150
+ . await ;
151
+
152
+ assert ! (
153
+ result. is_err( ) ,
154
+ "Expected an error with invalid JSON response"
155
+ ) ;
156
+ }
157
+
158
+ #[ tokio:: test]
159
+ async fn download_fails_on_invalid_url ( ) {
160
+ let client = ReqwestGitHubApiClient :: new ( ) . unwrap ( ) ;
161
+
162
+ let result: MithrilResult < FakeApiResponse > = client. download ( "not a valid url" ) . await ;
163
+
164
+ assert ! ( result. is_err( ) , "Expected an error for an invalid URL" ) ;
165
+ }
166
+
167
+ #[ tokio:: test]
168
+ async fn download_fails_when_server_returns_error_and_includes_status_in_error ( ) {
169
+ let server = MockServer :: start ( ) ;
170
+ let _mock = server. mock ( |when, then| {
171
+ when. method ( GET ) . path ( "/endpoint" ) ;
172
+ then. status ( StatusCode :: INTERNAL_SERVER_ERROR . into ( ) ) ;
173
+ } ) ;
174
+ let client = ReqwestGitHubApiClient :: new ( ) . unwrap ( ) ;
175
+
176
+ let result: MithrilResult < FakeApiResponse > = client
177
+ . download ( format ! ( "{}/endpoint" , server. base_url( ) ) )
178
+ . await ;
179
+ let error = result. expect_err ( "Expected an error due to 500 status" ) ;
180
+
181
+ assert ! ( error
182
+ . to_string( )
183
+ . contains( & StatusCode :: INTERNAL_SERVER_ERROR . to_string( ) ) ) ;
184
+ }
185
+ }
0 commit comments