shopify_sdk/clients/rest/
errors.rs1use crate::clients::HttpError;
34use thiserror::Error;
35
36#[derive(Debug, Error)]
55pub enum RestError {
56 #[error("The Admin REST API has been deprecated. Please use the GraphQL Admin API. For more information see https://www.shopify.com/ca/partners/blog/all-in-on-graphql")]
61 RestApiDisabled,
62
63 #[error("Invalid REST API path: {path}")]
68 InvalidPath {
69 path: String,
71 },
72
73 #[error(transparent)]
77 Http(#[from] HttpError),
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::clients::{HttpResponseError, MaxHttpRetriesExceededError};
84
85 #[test]
86 fn test_rest_api_disabled_error_message_matches_ruby_sdk() {
87 let error = RestError::RestApiDisabled;
88 let message = error.to_string();
89
90 assert!(message.contains("The Admin REST API has been deprecated"));
92 assert!(message.contains("Please use the GraphQL Admin API"));
93 assert!(message.contains("https://www.shopify.com/ca/partners/blog/all-in-on-graphql"));
94 }
95
96 #[test]
97 fn test_invalid_path_error_includes_path_in_message() {
98 let error = RestError::InvalidPath {
99 path: "/invalid/path".to_string(),
100 };
101 let message = error.to_string();
102
103 assert!(message.contains("Invalid REST API path"));
104 assert!(message.contains("/invalid/path"));
105 }
106
107 #[test]
108 fn test_invalid_path_error_with_empty_path() {
109 let error = RestError::InvalidPath {
110 path: String::new(),
111 };
112 let message = error.to_string();
113
114 assert!(message.contains("Invalid REST API path"));
115 assert_eq!(message, "Invalid REST API path: ");
117 }
118
119 #[test]
120 fn test_http_error_wraps_http_response_error() {
121 let http_error = HttpError::Response(HttpResponseError {
122 code: 404,
123 message: r#"{"error":"Not Found"}"#.to_string(),
124 error_reference: Some("abc-123".to_string()),
125 });
126
127 let rest_error = RestError::Http(http_error);
128 let message = rest_error.to_string();
129
130 assert!(message.contains("Not Found"));
131 }
132
133 #[test]
134 fn test_from_http_error_conversion() {
135 let http_error = HttpError::Response(HttpResponseError {
136 code: 500,
137 message: r#"{"error":"Internal Server Error"}"#.to_string(),
138 error_reference: None,
139 });
140
141 let rest_error: RestError = http_error.into();
143
144 assert!(matches!(rest_error, RestError::Http(_)));
145 }
146
147 #[test]
148 fn test_all_error_variants_implement_std_error() {
149 let disabled_error: &dyn std::error::Error = &RestError::RestApiDisabled;
151 let _ = disabled_error;
152
153 let path_error: &dyn std::error::Error = &RestError::InvalidPath {
155 path: "test".to_string(),
156 };
157 let _ = path_error;
158
159 let http_error: &dyn std::error::Error =
161 &RestError::Http(HttpError::Response(HttpResponseError {
162 code: 400,
163 message: "test".to_string(),
164 error_reference: None,
165 }));
166 let _ = http_error;
167 }
168
169 #[test]
170 fn test_http_error_wraps_max_retries_exceeded() {
171 let http_error = HttpError::MaxRetries(MaxHttpRetriesExceededError {
172 code: 429,
173 tries: 3,
174 message: r#"{"error":"Rate limited"}"#.to_string(),
175 error_reference: None,
176 });
177
178 let rest_error = RestError::Http(http_error);
179 let message = rest_error.to_string();
180
181 assert!(message.contains("Exceeded maximum retry count"));
182 assert!(message.contains("3"));
183 }
184}