concept-analyzer 0.1.1

A unified pipeline that analyzes code repositories and extracts first-principles instructions for AI agents
Documentation
//! Integration tests for concept_analyzer

use concept_analyzer::{BatchFileCollector, ConceptRegistry, FirstPrinciplesOutput};
use tempfile::TempDir;

#[tokio::test]
async fn test_file_collector() {
    // Create a temporary directory with some files
    let temp_dir = TempDir::new().unwrap();
    let file_path = temp_dir.path().join("test.rs");
    std::fs::write(&file_path, "fn main() { println!(\"Hello\"); }").unwrap();

    // Test file collection
    let collector = BatchFileCollector::new()
        .with_max_files_per_batch(10)
        .with_exclude_patterns(vec!["*.txt".to_string()]);

    let collections = collector.collect_repository(temp_dir.path()).await.unwrap();

    assert!(!collections.is_empty());
    assert_eq!(collections[0].files.len(), 1);
    assert_eq!(collections[0].files[0].path, file_path);
}

#[test]
fn test_concept_registry() {
    use concept_analyzer::Abstraction;

    let mut registry = ConceptRegistry::new();

    // Add some test abstractions
    let abstractions = vec![
        Abstraction {
            name: "UserService".to_string(),
            description: "Manages users".to_string(),
            related_files: vec!["user.rs".to_string()],
        },
        Abstraction {
            name: "AuthService".to_string(),
            description: "Handles authentication".to_string(),
            related_files: vec!["auth.rs".to_string()],
        },
    ];

    registry.add_project("test-project", abstractions);

    // Registry should now contain these concepts
    let gaps = registry.detect_gaps();
    // In this simple case, no gaps should be detected
    assert_eq!(gaps.len(), 0);
}

#[test]
fn test_first_principles_output_serialization() {
    use concept_analyzer::{ConceptRelation, CriticalGap, EssentialConcept, RebuildStep};

    let output = FirstPrinciplesOutput {
        project_name: "test-project".to_string(),
        core_purpose: "A test project for demonstration".to_string(),
        essential_concepts: vec![EssentialConcept {
            name: "Core".to_string(),
            purpose: "Main functionality".to_string(),
            core_responsibilities: vec!["Process data".to_string()],
            interfaces: vec!["process()".to_string()],
        }],
        concept_relationships: vec![ConceptRelation {
            from: "Core".to_string(),
            to: "Utils".to_string(),
            relationship_type: "uses".to_string(),
            reason: "Needs utility functions".to_string(),
        }],
        implementation_order: vec!["Utils".to_string(), "Core".to_string()],
        critical_gaps: vec![CriticalGap {
            missing_functionality: "Error handling".to_string(),
            impact: "System may crash".to_string(),
            suggested_solution: "Add try-catch blocks".to_string(),
        }],
        rebuild_instructions: vec![RebuildStep {
            step_number: 1,
            concept: "Utils".to_string(),
            implementation_details: "Create utility functions".to_string(),
            dependencies: vec![],
            validation_criteria: vec!["Tests pass".to_string()],
        }],
    };

    // Test serialization
    let json = serde_json::to_string_pretty(&output).unwrap();
    assert!(json.contains("test-project"));
    assert!(json.contains("essential_concepts"));

    // Test deserialization
    let parsed: FirstPrinciplesOutput = serde_json::from_str(&json).unwrap();
    assert_eq!(parsed.project_name, "test-project");
    assert_eq!(parsed.essential_concepts.len(), 1);
}