
Some checks are pending
iOS UniFFI Build / build-ios (push) Waiting to run
Add church management API library with cross-platform support for iOS, Android, and WASM. Features include event management, bulletin handling, contact forms, and authentication.
208 lines
6.9 KiB
Rust
208 lines
6.9 KiB
Rust
use church_core::{
|
|
ChurchApiClient, ChurchCoreConfig,
|
|
error::ChurchApiError,
|
|
};
|
|
use mockito::{self, mock};
|
|
use serde_json::json;
|
|
use std::time::Duration;
|
|
|
|
#[cfg(test)]
|
|
mod error_handling_tests {
|
|
use super::*;
|
|
|
|
fn create_test_client() -> ChurchApiClient {
|
|
let config = ChurchCoreConfig::new()
|
|
.with_base_url(&mockito::server_url())
|
|
.with_timeout(Duration::from_millis(100))
|
|
.with_retry_attempts(1)
|
|
.with_offline_mode(false);
|
|
|
|
ChurchApiClient::new(config).unwrap()
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_http_404_error() {
|
|
let _m = mock("GET", "/events/nonexistent")
|
|
.with_status(404)
|
|
.with_header("content-type", "application/json")
|
|
.with_body(json!({
|
|
"success": false,
|
|
"error": "Not found"
|
|
}).to_string())
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let result = client.get_event("nonexistent").await;
|
|
|
|
// For get_event, 404 should return None, not an error
|
|
assert!(result.is_ok());
|
|
assert!(result.unwrap().is_none());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_http_401_unauthorized() {
|
|
let _m = mock("POST", "/events")
|
|
.with_status(401)
|
|
.with_header("content-type", "application/json")
|
|
.with_body(json!({
|
|
"success": false,
|
|
"error": "Unauthorized access"
|
|
}).to_string())
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let new_event = church_core::models::NewEvent {
|
|
title: "Protected Event".to_string(),
|
|
description: "Requires authentication".to_string(),
|
|
start_time: chrono::Utc::now(),
|
|
end_time: chrono::Utc::now() + chrono::Duration::hours(1),
|
|
location: "Secure Location".to_string(),
|
|
location_url: None,
|
|
image: None,
|
|
category: church_core::models::EventCategory::Other,
|
|
is_featured: false,
|
|
recurring_type: None,
|
|
tags: None,
|
|
contact_email: None,
|
|
contact_phone: None,
|
|
registration_url: None,
|
|
max_attendees: None,
|
|
};
|
|
|
|
let result = client.create_event(new_event).await;
|
|
|
|
assert!(result.is_err());
|
|
if let Err(error) = result {
|
|
assert!(matches!(error, ChurchApiError::Auth(_)));
|
|
assert!(error.is_auth_error());
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_http_403_forbidden() {
|
|
let _m = mock("PUT", "/config")
|
|
.with_status(403)
|
|
.with_header("content-type", "application/json")
|
|
.with_body(json!({
|
|
"success": false,
|
|
"error": "Forbidden - insufficient permissions"
|
|
}).to_string())
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let config = church_core::models::ChurchConfig {
|
|
church_name: Some("Test Church".to_string()),
|
|
church_address: None,
|
|
contact_phone: None,
|
|
contact_email: None,
|
|
website_url: None,
|
|
google_maps_url: None,
|
|
facebook_url: None,
|
|
youtube_url: None,
|
|
instagram_url: None,
|
|
about_text: None,
|
|
mission_statement: None,
|
|
service_times: None,
|
|
pastoral_staff: None,
|
|
ministries: None,
|
|
app_settings: None,
|
|
emergency_contacts: None,
|
|
};
|
|
|
|
let result = client.update_config(config).await;
|
|
|
|
assert!(result.is_err());
|
|
if let Err(error) = result {
|
|
assert!(matches!(error, ChurchApiError::PermissionDenied));
|
|
assert!(error.is_auth_error());
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_http_500_server_error() {
|
|
let _m = mock("GET", "/events/upcoming")
|
|
.with_status(500)
|
|
.with_header("content-type", "application/json")
|
|
.with_body(json!({
|
|
"success": false,
|
|
"error": "Internal server error"
|
|
}).to_string())
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let result = client.get_upcoming_events(None).await;
|
|
|
|
assert!(result.is_err());
|
|
if let Err(error) = result {
|
|
assert!(matches!(error, ChurchApiError::Http(_)));
|
|
assert!(error.is_network_error());
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_invalid_json_response() {
|
|
let _m = mock("GET", "/events/upcoming")
|
|
.with_status(200)
|
|
.with_header("content-type", "application/json")
|
|
.with_body("invalid json {")
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let result = client.get_upcoming_events(None).await;
|
|
|
|
assert!(result.is_err());
|
|
// Invalid JSON will likely cause an HTTP parsing error instead of JSON error
|
|
// since the response can't be properly parsed as JSON
|
|
if let Err(error) = result {
|
|
// Could be either JSON or HTTP error depending on how reqwest handles it
|
|
assert!(matches!(error, ChurchApiError::Json(_)) || matches!(error, ChurchApiError::Http(_)));
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_api_error_response() {
|
|
let _m = mock("GET", "/events/upcoming")
|
|
.with_status(200)
|
|
.with_header("content-type", "application/json")
|
|
.with_body(json!({
|
|
"success": false,
|
|
"data": null,
|
|
"error": "Custom API error message"
|
|
}).to_string())
|
|
.create();
|
|
|
|
let client = create_test_client();
|
|
let result = client.get_upcoming_events(None).await;
|
|
|
|
assert!(result.is_err());
|
|
if let Err(error) = result {
|
|
assert!(matches!(error, ChurchApiError::Api(_)));
|
|
if let ChurchApiError::Api(message) = error {
|
|
assert_eq!(message, "Custom API error message");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_classification() {
|
|
let auth_error = ChurchApiError::Auth("Invalid token".to_string());
|
|
assert!(!auth_error.is_network_error());
|
|
assert!(!auth_error.is_temporary());
|
|
assert!(auth_error.is_auth_error());
|
|
|
|
let rate_limit_error = ChurchApiError::RateLimit;
|
|
assert!(!rate_limit_error.is_network_error());
|
|
assert!(rate_limit_error.is_temporary());
|
|
assert!(!rate_limit_error.is_auth_error());
|
|
|
|
let permission_error = ChurchApiError::PermissionDenied;
|
|
assert!(!permission_error.is_network_error());
|
|
assert!(!permission_error.is_temporary());
|
|
assert!(permission_error.is_auth_error());
|
|
|
|
let not_found_error = ChurchApiError::NotFound;
|
|
assert!(!not_found_error.is_network_error());
|
|
assert!(!not_found_error.is_temporary());
|
|
assert!(!not_found_error.is_auth_error());
|
|
}
|
|
} |