use church_core::{ ChurchApiClient, ChurchCoreConfig, models::*, error::ChurchApiError, }; use mockito::{self, mock}; use serde_json::json; use std::time::Duration; use tokio_test; #[cfg(test)] mod integration_tests { use super::*; fn create_test_client() -> ChurchApiClient { let config = ChurchCoreConfig::new() .with_base_url(&mockito::server_url()) .with_timeout(Duration::from_secs(5)) .with_retry_attempts(1) .with_offline_mode(false); ChurchApiClient::new(config).unwrap() } #[tokio::test] async fn test_get_upcoming_events_success() { let _m = mock("GET", "/events/upcoming") .with_status(200) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": [{ "id": "event-1", "title": "Sunday Service", "description": "Weekly worship service", "start_time": "2024-07-14T11:00:00Z", "end_time": "2024-07-14T12:30:00Z", "location": "Main Sanctuary", "location_url": null, "image": null, "thumbnail": null, "category": "service", "is_featured": true, "recurring_type": "weekly", "tags": ["worship", "sunday"], "contact_email": null, "contact_phone": null, "registration_url": null, "max_attendees": null, "current_attendees": null, "created_at": "2024-07-01T10:00:00Z", "updated_at": "2024-07-01T10:00:00Z" }] }).to_string()) .create(); let client = create_test_client(); let events = client.get_upcoming_events(None).await.unwrap(); assert_eq!(events.len(), 1); assert_eq!(events[0].id, "event-1"); assert_eq!(events[0].title, "Sunday Service"); assert_eq!(events[0].category, EventCategory::Service); assert!(events[0].is_featured); } #[tokio::test] async fn test_get_upcoming_events_with_limit() { let _m = mock("GET", "/events/upcoming?limit=5") .with_status(200) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": [] }).to_string()) .create(); let client = create_test_client(); let events = client.get_upcoming_events(Some(5)).await.unwrap(); assert_eq!(events.len(), 0); } #[tokio::test] async fn test_get_event_success() { let _m = mock("GET", "/events/event-123") .with_status(200) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": { "id": "event-123", "title": "Bible Study", "description": "Weekly Bible study group", "start_time": "2024-07-15T19:00:00Z", "end_time": "2024-07-15T21:00:00Z", "location": "Fellowship Hall", "location_url": null, "image": null, "thumbnail": null, "category": "education", "is_featured": false, "recurring_type": null, "tags": ["bible", "study"], "contact_email": "study@church.org", "contact_phone": null, "registration_url": null, "max_attendees": 20, "current_attendees": 12, "created_at": "2024-07-01T10:00:00Z", "updated_at": "2024-07-01T10:00:00Z" } }).to_string()) .create(); let client = create_test_client(); let event = client.get_event("event-123").await.unwrap(); assert!(event.is_some()); let event = event.unwrap(); assert_eq!(event.id, "event-123"); assert_eq!(event.title, "Bible Study"); assert_eq!(event.category, EventCategory::Education); assert_eq!(event.spots_remaining(), Some(8)); } #[tokio::test] async fn test_get_event_not_found() { let _m = mock("GET", "/events/nonexistent") .with_status(404) .with_header("content-type", "application/json") .with_body(json!({ "success": false, "error": "Event not found" }).to_string()) .create(); let client = create_test_client(); let event = client.get_event("nonexistent").await.unwrap(); assert!(event.is_none()); } #[tokio::test] async fn test_create_event_success() { let _m = mock("POST", "/events") .with_status(201) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": "new-event-id" }).to_string()) .create(); let client = create_test_client(); let new_event = NewEvent { title: "New Event".to_string(), description: "A new event".to_string(), start_time: chrono::Utc::now(), end_time: chrono::Utc::now() + chrono::Duration::hours(2), location: "Main Hall".to_string(), location_url: None, image: None, category: EventCategory::Ministry, is_featured: false, recurring_type: None, tags: None, contact_email: None, contact_phone: None, registration_url: None, max_attendees: None, }; let event_id = client.create_event(new_event).await.unwrap(); assert_eq!(event_id, "new-event-id"); } #[tokio::test] async fn test_get_current_bulletin_success() { let _m = mock("GET", "/bulletins/current") .with_status(200) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": { "id": "bulletin-current", "title": "This Week's Bulletin", "date": "2024-07-13", "sabbath_school": "9:30 AM", "divine_worship": "11:00 AM", "scripture_reading": "Psalm 23", "sunset": "7:45 PM", "pdf_path": "/bulletins/current.pdf", "cover_image": "/images/cover.jpg", "is_active": true, "announcements": [{ "id": "ann-1", "title": "Potluck Next Week", "content": "Join us for fellowship after service", "category": "social", "is_urgent": false, "contact_info": null, "expires_at": "2025-12-31T00:00:00Z" }], "hymns": [{ "number": 1, "title": "Holy, Holy, Holy", "category": "opening", "verses": [1, 2, 3] }], "special_music": null, "offering_type": "Local Church Budget", "sermon_title": "Walking by Faith", "speaker": "Pastor Smith", "liturgy": null, "created_at": "2024-07-01T10:00:00Z", "updated_at": "2024-07-13T08:00:00Z" } }).to_string()) .create(); let client = create_test_client(); let bulletin = client.get_current_bulletin().await.unwrap(); assert!(bulletin.is_some()); let bulletin = bulletin.unwrap(); assert_eq!(bulletin.id, "bulletin-current"); assert_eq!(bulletin.title, "This Week's Bulletin"); assert!(bulletin.has_pdf()); assert!(bulletin.has_cover_image()); assert_eq!(bulletin.active_announcements().len(), 1); } #[tokio::test] async fn test_get_current_bulletin_not_found() { let _m = mock("GET", "/bulletins/current") .with_status(404) .with_header("content-type", "application/json") .with_body(json!({ "success": false, "error": "No current bulletin found" }).to_string()) .create(); let client = create_test_client(); let bulletin = client.get_current_bulletin().await.unwrap(); assert!(bulletin.is_none()); } #[tokio::test] async fn test_get_config_success() { let _m = mock("GET", "/config") .with_status(200) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": { "church_name": "Test Church", "church_address": "123 Faith Street, Hometown, ST 12345", "contact_phone": "555-123-4567", "contact_email": "info@testchurch.org", "website_url": "https://testchurch.org", "google_maps_url": "https://maps.google.com/test", "facebook_url": "https://facebook.com/testchurch", "youtube_url": null, "instagram_url": null, "about_text": "A welcoming church community", "mission_statement": "Spreading God's love", "service_times": { "sabbath_school": "9:30 AM", "divine_worship": "11:00 AM", "prayer_meeting": "7:00 PM Wednesday", "youth_service": null, "special_services": null }, "pastoral_staff": [{ "name": "Pastor John Smith", "title": "Senior Pastor", "email": "pastor@testchurch.org", "phone": "555-123-4568", "photo": null, "bio": "Leading our church with love", "responsibilities": ["Preaching", "Pastoral Care"] }], "ministries": null, "app_settings": { "enable_notifications": true, "enable_calendar_sync": true, "enable_offline_mode": true, "theme": "system", "default_language": "en", "jellyfin_server": null, "owncast_server": null, "bible_version": "KJV", "hymnal_version": "1985", "cache_duration_minutes": 60, "auto_refresh_interval_minutes": 15 }, "emergency_contacts": null } }).to_string()) .create(); let client = create_test_client(); let config = client.get_config().await.unwrap(); assert_eq!(config.church_name, Some("Test Church".to_string())); assert_eq!(config.contact_phone, Some("555-123-4567".to_string())); assert_eq!(config.get_display_name(), "Test Church"); assert!(config.has_social_media()); assert_eq!(config.get_contact_info().len(), 3); // phone, email, address } #[tokio::test] async fn test_submit_contact_form_success() { let _m = mock("POST", "/contact") .with_status(201) .with_header("content-type", "application/json") .with_body(json!({ "success": true, "data": "contact-submission-123" }).to_string()) .create(); let client = create_test_client(); let contact_form = ContactForm::new( "Jane Doe".to_string(), "jane@example.com".to_string(), "Question about baptism".to_string(), "I'm interested in learning about baptism.".to_string(), ).with_category(ContactCategory::Baptism); let submission_id = client.submit_contact_form(contact_form).await.unwrap(); assert_eq!(submission_id, "contact-submission-123"); } #[tokio::test] async fn test_api_error_handling() { 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(_))); } } #[tokio::test] async fn test_health_check() { let _m = mock("GET", "/health") .with_status(200) .with_header("content-type", "application/json") .with_body("OK") .create(); let client = create_test_client(); let is_healthy = client.health_check().await.unwrap(); assert!(is_healthy); } }