|
1 | | -use openapi_to_rust::http_error::{HttpError, HttpResult}; |
| 1 | +use openapi_to_rust::http_error::{ApiError, HttpError, HttpResult}; |
| 2 | +use reqwest::header::HeaderMap; |
| 3 | + |
| 4 | +#[derive(Debug)] |
| 5 | +enum TypedApiError { |
| 6 | + Invalid, |
| 7 | +} |
| 8 | + |
| 9 | +fn api_error<E>( |
| 10 | + body: impl Into<String>, |
| 11 | + typed: Option<E>, |
| 12 | + parse_error: Option<&str>, |
| 13 | +) -> ApiError<E> { |
| 14 | + ApiError { |
| 15 | + status: 422, |
| 16 | + headers: HeaderMap::new(), |
| 17 | + body: body.into(), |
| 18 | + typed, |
| 19 | + parse_error: parse_error.map(str::to_owned), |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +#[test] |
| 24 | +fn test_api_error_display_normal_body() { |
| 25 | + let error = api_error::<TypedApiError>("small response", None, None); |
| 26 | + |
| 27 | + assert_eq!(error.to_string(), "API error 422: small response"); |
| 28 | +} |
| 29 | + |
| 30 | +#[test] |
| 31 | +fn test_api_error_display_truncates_body_without_mutating_it() { |
| 32 | + let body = "é".repeat(600); |
| 33 | + let error = api_error::<TypedApiError>(body.clone(), None, None); |
| 34 | + let displayed = error.to_string(); |
| 35 | + |
| 36 | + assert_eq!( |
| 37 | + displayed, |
| 38 | + format!("API error 422: {}... [truncated]", "é".repeat(500)) |
| 39 | + ); |
| 40 | + assert_eq!(error.body, body); |
| 41 | +} |
| 42 | + |
| 43 | +#[test] |
| 44 | +fn test_api_error_display_includes_typed_error() { |
| 45 | + let error = api_error("validation failed", Some(TypedApiError::Invalid), None); |
| 46 | + |
| 47 | + assert_eq!( |
| 48 | + error.to_string(), |
| 49 | + "API error 422: validation failed; typed: Invalid" |
| 50 | + ); |
| 51 | +} |
| 52 | + |
| 53 | +#[test] |
| 54 | +fn test_api_error_display_includes_parse_error() { |
| 55 | + let error = |
| 56 | + api_error::<TypedApiError>("not json", None, Some("expected value at line 1 column 1")); |
| 57 | + |
| 58 | + assert_eq!( |
| 59 | + error.to_string(), |
| 60 | + "API error 422: not json; parse error: expected value at line 1 column 1" |
| 61 | + ); |
| 62 | +} |
2 | 63 |
|
3 | 64 | #[test] |
4 | 65 | fn test_http_error_creation() { |
@@ -312,6 +373,22 @@ fn test_generated_error_code() { |
312 | 373 | client_content.contains("pub fn is_retryable"), |
313 | 374 | "Generated code should contain is_retryable method" |
314 | 375 | ); |
| 376 | + assert!( |
| 377 | + client_content.contains("API_ERROR_BODY_DISPLAY_LIMIT"), |
| 378 | + "Generated code should bound the displayed API error body" |
| 379 | + ); |
| 380 | + assert!( |
| 381 | + client_content.contains("API_ERROR_BODY_TRUNCATION_MARKER"), |
| 382 | + "Generated code should include a clear body truncation marker" |
| 383 | + ); |
| 384 | + assert!( |
| 385 | + client_content.contains("typed: {typed:?}"), |
| 386 | + "Generated code should display typed API error details" |
| 387 | + ); |
| 388 | + assert!( |
| 389 | + client_content.contains("parse error: {parse_error}"), |
| 390 | + "Generated code should display typed parsing failures" |
| 391 | + ); |
315 | 392 |
|
316 | 393 | // Verify HttpResult type alias |
317 | 394 | assert!( |
|
0 commit comments