mod common; use chrono::Utc; use common::TestDb; use flalingo_lib::models::{ exercise::Exercise, node::Node, path::{Metadata, Path}, }; use flalingo_lib::repositories::repository_manager::RepositoryManager; #[tokio::test] async fn test_database_connection() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Test database health let is_healthy = repo_manager.health_check().await?; assert!(is_healthy); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_simple_path_crud() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Create a simple test path let test_path = create_simple_test_path(); // Save the path let saved_path_id = repo_manager.paths().save_path(test_path.clone()).await?; assert_eq!(saved_path_id, test_path.id); // Retrieve the path let path_id_int = saved_path_id.parse::()?; let retrieved_path = repo_manager.paths().get_path_by_id(path_id_int).await?; // Basic assertions assert_eq!(retrieved_path.id, test_path.id); assert_eq!(retrieved_path.title, test_path.title); assert_eq!(retrieved_path.nodes.len(), 1); assert_eq!(retrieved_path.nodes[0].exercises.len(), 1); // Delete the path repo_manager.paths().delete_path(path_id_int).await?; // Verify deletion let path_exists = repo_manager.paths().path_exists(path_id_int).await?; assert!(!path_exists); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_database_stats() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Initially empty let initial_stats = repo_manager.get_stats().await?; assert_eq!(initial_stats.path_count, 0); assert!(initial_stats.is_empty()); // Add a path let test_path = create_simple_test_path(); repo_manager.paths().save_path(test_path).await?; // Check updated stats let updated_stats = repo_manager.get_stats().await?; assert_eq!(updated_stats.path_count, 1); assert_eq!(updated_stats.node_count, 1); assert_eq!(updated_stats.exercise_count, 1); assert!(!updated_stats.is_empty()); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_json_export_import() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Create and save a path let test_path = create_simple_test_path(); let path_id = repo_manager.paths().save_path(test_path.clone()).await?; let path_id_int = path_id.parse::()?; // Export to JSON let exported_json = repo_manager.export_path_to_json(path_id_int).await?; assert!(exported_json.contains(&test_path.id)); assert!(exported_json.contains(&test_path.title)); // Import as new path let modified_json = exported_json.replace("simple_test_path", "imported_test_path"); let imported_path_id = repo_manager.import_path_from_json(&modified_json).await?; // Verify import let imported_path_id_int = imported_path_id.parse::()?; let imported_path = repo_manager .paths() .get_path_by_id(imported_path_id_int) .await?; assert_eq!(imported_path.id, "imported_test_path"); assert_eq!(imported_path.title, test_path.title); assert_eq!(imported_path.nodes.len(), test_path.nodes.len()); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_search_functionality() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Create multiple paths let path1 = create_simple_test_path(); let mut path2 = create_simple_test_path(); path2.id = "search_test_2".to_string(); path2.title = "Advanced German Grammar".to_string(); repo_manager.paths().save_path(path1).await?; repo_manager.paths().save_path(path2).await?; // Search for paths let results = repo_manager.search_paths("German").await?; assert_eq!(results.len(), 2); // Search for specific term let advanced_results = repo_manager.search_paths("Advanced").await?; assert_eq!(advanced_results.len(), 1); assert_eq!(advanced_results[0].path_id, "search_test_2"); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_path_cloning() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Create and save original path let original_path = create_simple_test_path(); let original_path_id = repo_manager .paths() .save_path(original_path.clone()) .await?; let original_id_int = original_path_id.parse::()?; // Clone the path let cloned_path_id = repo_manager .clone_path_complete(original_id_int, "cloned_simple_path", "Cloned Simple Path") .await?; // Verify clone let cloned_id_int = cloned_path_id.parse::()?; let cloned_path = repo_manager.paths().get_path_by_id(cloned_id_int).await?; assert_eq!(cloned_path.id, "cloned_simple_path"); assert_eq!(cloned_path.title, "Cloned Simple Path"); assert_eq!(cloned_path.description, original_path.description); assert_eq!(cloned_path.nodes.len(), original_path.nodes.len()); test_db.cleanup().await?; Ok(()) } #[tokio::test] async fn test_error_handling() -> Result<(), Box> { let test_db = TestDb::new().await?; let repo_manager = RepositoryManager::new(&test_db.pool); // Test getting non-existent path let result = repo_manager.paths().get_path_by_id(999).await; assert!(result.is_err()); // Test deleting non-existent path let delete_result = repo_manager.paths().delete_path(999).await; assert!(delete_result.is_err()); // Test invalid JSON import let invalid_json = r#"{"invalid": "structure"}"#; let import_result = repo_manager.import_path_from_json(invalid_json).await; assert!(import_result.is_err()); test_db.cleanup().await?; Ok(()) } // Helper function to create simple test data fn create_simple_test_path() -> Path { let now = Utc::now(); let metadata = vec![Metadata { path_id: "simple_test_path".to_string(), version: "1.0.0".to_string(), created_at: now, updated_at: now, }]; let exercise = Exercise { id: 1, ex_type: "vocabulary".to_string(), content: r#"{"word": "Hallo", "translation": "Hello", "example": "Hallo, wie geht's?"}"# .to_string(), node_id: 1, }; let node = Node { id: 1, title: "Basic Greetings".to_string(), description: "Learn German greetings".to_string(), path_id: "simple_test_path".to_string(), exercises: vec![exercise], }; Path { id: "simple_test_path".to_string(), title: "Simple German Test".to_string(), description: "A simple test path for German learning".to_string(), metadata, nodes: vec![node], } }