An AI agent built to do Ralph loops - plan mode for planning and ralph mode for implementing.
at main 111 lines 3.2 kB view raw
1use chrono::Utc; 2use rustagent::spec::{Spec, Task, TaskStatus}; 3use tempfile::TempDir; 4 5#[test] 6fn test_spec_serialization() { 7 let spec = Spec { 8 name: "test-feature".to_string(), 9 description: "A test feature".to_string(), 10 branch_name: "feature/test".to_string(), 11 created_at: Utc::now(), 12 tasks: vec![Task { 13 id: "task-1".to_string(), 14 title: "Implement X".to_string(), 15 description: "Description".to_string(), 16 acceptance_criteria: vec!["Criterion 1".to_string()], 17 status: TaskStatus::Pending, 18 blocked_reason: None, 19 completed_at: None, 20 }], 21 learnings: vec![], 22 }; 23 24 let json = serde_json::to_string_pretty(&spec).unwrap(); 25 assert!(json.contains("test-feature")); 26 assert!(json.contains("pending")); 27} 28 29#[test] 30fn test_spec_save_and_load() { 31 let temp = TempDir::new().unwrap(); 32 let spec_path = temp.path().join("test.json"); 33 34 let spec = Spec { 35 name: "test".to_string(), 36 description: "Test".to_string(), 37 branch_name: "feature/test".to_string(), 38 created_at: Utc::now(), 39 tasks: vec![], 40 learnings: vec![], 41 }; 42 43 spec.save(&spec_path).unwrap(); 44 let loaded = Spec::load(&spec_path).unwrap(); 45 46 assert_eq!(loaded.name, "test"); 47} 48 49#[test] 50fn test_spec_uses_datetime_types() { 51 let now = Utc::now(); 52 let spec = Spec { 53 name: "test".to_string(), 54 description: "test spec".to_string(), 55 branch_name: "feature/test".to_string(), 56 created_at: now, 57 tasks: vec![], 58 learnings: vec![], 59 }; 60 61 // Should serialize to RFC3339 format 62 let json = serde_json::to_string(&spec).unwrap(); 63 // Chrono serializes with 'Z' suffix, which is valid RFC3339 64 assert!(json.contains(&format!("{}Z", now.format("%Y-%m-%dT%H:%M:%S%.f")))); 65} 66 67#[test] 68fn test_task_completion_timestamp() { 69 let completed = Utc::now(); 70 let task = Task { 71 id: "task-1".to_string(), 72 title: "Test".to_string(), 73 description: "desc".to_string(), 74 acceptance_criteria: vec![], 75 status: TaskStatus::Complete, 76 blocked_reason: None, 77 completed_at: Some(completed), 78 }; 79 80 let json = serde_json::to_string(&task).unwrap(); 81 // Chrono serializes with 'Z' suffix, which is valid RFC3339 82 assert!(json.contains(&format!("{}Z", completed.format("%Y-%m-%dT%H:%M:%S%.f")))); 83} 84 85#[test] 86fn test_spec_save_creates_parent_directories() { 87 let dir = tempfile::tempdir().unwrap(); 88 let nested_path = dir 89 .path() 90 .join("level1") 91 .join("level2") 92 .join("level3") 93 .join("spec.json"); 94 95 let spec = Spec { 96 name: "test".to_string(), 97 description: "test spec".to_string(), 98 branch_name: "feature/test".to_string(), 99 created_at: Utc::now(), 100 tasks: vec![], 101 learnings: vec![], 102 }; 103 104 // Should create all parent directories 105 spec.save(&nested_path).unwrap(); 106 assert!(nested_path.exists()); 107 108 // Should be able to load it back 109 let loaded = Spec::load(&nested_path).unwrap(); 110 assert_eq!(loaded.name, "test"); 111}