@@ -31,6 +31,15 @@ impl ReqwestGitHubApiClient {
3131 . send ( )
3232 . await
3333 . 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+ }
3443 let body = response. text ( ) . await ?;
3544 let parsed_body = serde_json:: from_str :: < T > ( & body)
3645 . with_context ( || format ! ( "Failed to parse response from GitHub API: {:?}" , body) ) ?;
@@ -91,3 +100,86 @@ impl GitHubReleaseRetriever for ReqwestGitHubApiClient {
91100 Ok ( releases)
92101 }
93102}
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