{
    "sourceFile": "tests/chicago_tdd/marketplace/search_tests.rs",
    "activeCommit": 0,
    "commits": [
        {
            "activePatchIndex": 1,
            "patches": [
                {
                    "date": 1762978889181,
                    "content": "Index: \n===================================================================\n--- \n+++ \n"
                },
                {
                    "date": 1762979402416,
                    "content": "Index: \n===================================================================\n--- \n+++ \n@@ -117,9 +117,11 @@\n     let _temp = create_test_registry().unwrap();\n \n     // Act\n     let filters = SearchFilters::new();\n-    let results = search_packages(\"Rust CLI Template\", &filters).await.unwrap();\n+    let results = search_packages(\"Rust CLI Template\", &filters)\n+        .await\n+        .unwrap();\n \n     // Assert: Should find exact match first\n     assert!(!results.is_empty(), \"Should find exact match\");\n     assert_eq!(results[0].id, \"io.ggen.rust.cli\");\n@@ -342,9 +344,11 @@\n async_test!(test_search_no_results, async {\n     let _temp = create_test_registry().unwrap();\n \n     let filters = SearchFilters::new();\n-    let results = search_packages(\"nonexistent-language-xyz\", &filters).await.unwrap();\n+    let results = search_packages(\"nonexistent-language-xyz\", &filters)\n+        .await\n+        .unwrap();\n \n     // Should return empty results, not error\n     assert!(\n         results.is_empty(),\n"
                }
            ],
            "date": 1762978889181,
            "name": "Commit-0",
            "content": "//! Chicago TDD Tests for Marketplace Search\n//!\n//! These tests use REAL registry files and verify actual search behavior\n//! following the Classicist School of TDD.\n\nuse chicago_tdd_tools::prelude::*;\nuse ggen_domain::marketplace::search::{search_packages, SearchFilters};\nuse ggen_utils::error::Result;\nuse std::fs;\nuse tempfile::TempDir;\n\n/// Create a test registry with real packages\n/// Returns the temp dir - caller must set CARGO_MANIFEST_DIR before calling search_packages\nfn create_test_registry() -> Result<TempDir> {\n    let temp_dir = TempDir::new().unwrap();\n\n    // Create registry in parent dir to match expected structure\n    // search_packages looks for: CARGO_MANIFEST_DIR/../registry/index.json\n    let parent_dir = temp_dir.path();\n    let registry_path = parent_dir.join(\"registry\");\n    fs::create_dir_all(&registry_path).unwrap();\n\n    let index_content = r#\"{\n  \"updated\": \"2025-01-15T00:00:00Z\",\n  \"packs\": {\n    \"io.ggen.rust.cli\": {\n      \"id\": \"io.ggen.rust.cli\",\n      \"name\": \"Rust CLI Template\",\n      \"description\": \"Generate Rust CLI applications with clap\",\n      \"tags\": [\"rust\", \"cli\", \"clap\"],\n      \"keywords\": [\"command-line\", \"terminal\", \"argument-parsing\"],\n      \"category\": \"rust\",\n      \"author\": \"ggen-team\",\n      \"latest_version\": \"1.0.0\",\n      \"downloads\": 5000,\n      \"stars\": 100,\n      \"license\": \"MIT\"\n    },\n    \"io.ggen.rust.web\": {\n      \"id\": \"io.ggen.rust.web\",\n      \"name\": \"Rust Web Service\",\n      \"description\": \"Generate Rust web services with Axum framework\",\n      \"tags\": [\"rust\", \"web\", \"axum\", \"http\"],\n      \"keywords\": [\"web-service\", \"api\", \"rest\", \"async\"],\n      \"category\": \"rust\",\n      \"author\": \"ggen-team\",\n      \"latest_version\": \"2.1.0\",\n      \"downloads\": 8500,\n      \"stars\": 250,\n      \"license\": \"MIT\"\n    },\n    \"io.ggen.python.api\": {\n      \"id\": \"io.ggen.python.api\",\n      \"name\": \"Python FastAPI\",\n      \"description\": \"Generate Python REST APIs with FastAPI\",\n      \"tags\": [\"python\", \"api\", \"fastapi\", \"rest\"],\n      \"keywords\": [\"web-api\", \"rest\", \"async\", \"openapi\"],\n      \"category\": \"python\",\n      \"author\": \"python-dev\",\n      \"latest_version\": \"3.0.0\",\n      \"downloads\": 12000,\n      \"stars\": 500,\n      \"license\": \"Apache-2.0\"\n    },\n    \"io.ggen.typescript.react\": {\n      \"id\": \"io.ggen.typescript.react\",\n      \"name\": \"TypeScript React App\",\n      \"description\": \"Generate React applications with TypeScript\",\n      \"tags\": [\"typescript\", \"react\", \"frontend\", \"spa\"],\n      \"keywords\": [\"web\", \"frontend\", \"ui\", \"components\"],\n      \"category\": \"typescript\",\n      \"author\": \"frontend-team\",\n      \"latest_version\": \"1.5.0\",\n      \"downloads\": 15000,\n      \"stars\": 800,\n      \"license\": \"MIT\"\n    },\n    \"io.ggen.rust.microservice\": {\n      \"id\": \"io.ggen.rust.microservice\",\n      \"name\": \"Rust Microservice\",\n      \"description\": \"Generate production-ready Rust microservices\",\n      \"tags\": [\"rust\", \"microservice\", \"kubernetes\", \"docker\"],\n      \"keywords\": [\"cloud\", \"distributed\", \"scalable\", \"production\"],\n      \"category\": \"rust\",\n      \"author\": \"cloud-team\",\n      \"latest_version\": \"2.0.0\",\n      \"downloads\": 3500,\n      \"stars\": 150,\n      \"license\": \"MIT\"\n    }\n  }\n}\"#;\n\n    fs::write(registry_path.join(\"index.json\"), index_content).unwrap();\n\n    // Create a fake cli subdirectory to match the CARGO_MANIFEST_DIR/../registry structure\n    let cli_dir = parent_dir.join(\"cli\");\n    fs::create_dir_all(&cli_dir).unwrap();\n\n    // Create a fake home directory with .ggen/registry to override ~/.ggen\n    let fake_home = parent_dir.join(\"home\");\n    let home_registry = fake_home.join(\".ggen\").join(\"registry\");\n    fs::create_dir_all(&home_registry).unwrap();\n    fs::write(home_registry.join(\"index.json\"), index_content).unwrap();\n\n    // Set HOME to fake home so ~/.ggen/registry/index.json is found first\n    std::env::set_var(\"HOME\", fake_home.to_str().unwrap());\n\n    // Set CARGO_MANIFEST_DIR as fallback\n    std::env::set_var(\"CARGO_MANIFEST_DIR\", cli_dir.to_str().unwrap());\n\n    Ok(temp_dir)\n}\n\nasync_test!(test_search_exact_name_match, async {\n    // Arrange\n    let _temp = create_test_registry().unwrap();\n\n    // Act\n    let filters = SearchFilters::new();\n    let results = search_packages(\"Rust CLI Template\", &filters).await.unwrap();\n\n    // Assert: Should find exact match first\n    assert!(!results.is_empty(), \"Should find exact match\");\n    assert_eq!(results[0].id, \"io.ggen.rust.cli\");\n    assert_eq!(results[0].name, \"Rust CLI Template\");\n});\n\nasync_test!(test_search_partial_match, async {\n    // Arrange\n    let _temp = create_test_registry().unwrap();\n\n    // Act\n    let filters = SearchFilters::new();\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // Assert: Should find all rust packages\n    assert!(results.len() >= 3, \"Should find at least 3 rust packages\");\n\n    // All results should be rust-related\n    for result in &results {\n        let is_rust = result.name.to_lowercase().contains(\"rust\")\n            || result.description.to_lowercase().contains(\"rust\")\n            || result\n                .tags\n                .iter()\n                .any(|t| t.to_lowercase().contains(\"rust\"));\n        assert!(is_rust, \"Result {} should be rust-related\", result.name);\n    }\n});\n\nasync_test!(test_search_fuzzy_matching, async {\n    // Arrange\n    let _temp = create_test_registry().unwrap();\n\n    // Act: Search with typo\n    let filters = SearchFilters::new().with_fuzzy(true);\n    let results = search_packages(\"rst cli\", &filters).await.unwrap();\n\n    // Assert: Should still find rust CLI packages with fuzzy matching\n    assert!(\n        !results.is_empty(),\n        \"Fuzzy search should find results despite typo\"\n    );\n});\n\nasync_test!(test_search_category_filter, async {\n    // Arrange\n    let _temp = create_test_registry().unwrap();\n\n    // Act\n    let filters = SearchFilters::new().with_category(\"rust\");\n    let results = search_packages(\"web\", &filters).await.unwrap();\n\n    // Assert: Should only find rust web packages\n    for result in &results {\n        assert_eq!(result.category, Some(\"rust\".to_string()));\n    }\n});\n\nasync_test!(test_search_keyword_filter, async {\n    // Arrange\n    let _temp = create_test_registry().unwrap();\n\n    // Act\n    let mut filters = SearchFilters::new();\n    filters.keyword = Some(\"rest\".to_string());\n\n    let results = search_packages(\"api\", &filters).await.unwrap();\n\n    // Assert: Should only find packages with \"rest\" keyword\n    assert!(\n        !results.is_empty(),\n        \"Should find packages with rest keyword\"\n    );\n});\n\nasync_test!(test_search_author_filter, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.author = Some(\"ggen-team\".to_string());\n\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // All results should be by ggen-team\n    for result in &results {\n        assert_eq!(result.author, Some(\"ggen-team\".to_string()));\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_min_stars_filter, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.min_stars = Some(200);\n\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // All results should have >= 200 stars\n    for result in &results {\n        assert!(\n            result.stars >= 200,\n            \"Package {} has {} stars, expected >= 200\",\n            result.name,\n            result.stars\n        );\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_min_downloads_filter, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.min_downloads = Some(10000);\n\n    let results = search_packages(\"api\", &filters).await.unwrap();\n\n    // All results should have >= 10000 downloads\n    for result in &results {\n        assert!(\n            result.downloads >= 10000,\n            \"Package {} has {} downloads, expected >= 10000\",\n            result.name,\n            result.downloads\n        );\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_sort_by_downloads, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.sort = \"downloads\".to_string();\n    filters.order = \"desc\".to_string();\n    filters.limit = 10;\n\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // Results should be sorted by downloads descending\n    for i in 0..results.len().saturating_sub(1) {\n        assert!(\n            results[i].downloads >= results[i + 1].downloads,\n            \"Downloads not sorted: {} ({}) vs {} ({})\",\n            results[i].name,\n            results[i].downloads,\n            results[i + 1].name,\n            results[i + 1].downloads\n        );\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_sort_by_stars, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.sort = \"stars\".to_string();\n    filters.order = \"desc\".to_string();\n    filters.limit = 10;\n\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // Results should be sorted by stars descending\n    for i in 0..results.len().saturating_sub(1) {\n        assert!(\n            results[i].stars >= results[i + 1].stars,\n            \"Stars not sorted: {} ({}) vs {} ({})\",\n            results[i].name,\n            results[i].stars,\n            results[i + 1].name,\n            results[i + 1].stars\n        );\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_limit, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new().with_limit(2);\n    let results = search_packages(\"rust\", &filters).await.unwrap();\n\n    // Should respect limit\n    assert!(results.len() <= 2, \"Results should be limited to 2\");\n\n    // Assert\n});\n\nasync_test!(test_search_relevance_ranking, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new();\n    let results = search_packages(\"rust web\", &filters).await.unwrap();\n\n    // \"Rust Web Service\" should rank higher than generic rust packages\n    assert!(!results.is_empty());\n\n    // First result should be the most relevant (contains both \"rust\" and \"web\")\n    let first = &results[0];\n    let has_rust =\n        first.name.to_lowercase().contains(\"rust\") || first.tags.contains(&\"rust\".to_string());\n    let has_web =\n        first.name.to_lowercase().contains(\"web\") || first.tags.contains(&\"web\".to_string());\n\n    assert!(\n        has_rust && has_web,\n        \"Most relevant result should contain both rust and web\"\n    );\n\n    // Assert\n});\n\nasync_test!(test_search_no_results, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new();\n    let results = search_packages(\"nonexistent-language-xyz\", &filters).await.unwrap();\n\n    // Should return empty results, not error\n    assert!(\n        results.is_empty(),\n        \"Nonexistent query should return empty results\"\n    );\n\n    // Assert\n});\n\nasync_test!(test_search_performance, async {\n    let _temp = create_test_registry().unwrap();\n\n    let start = std::time::Instant::now();\n    let filters = SearchFilters::new();\n    let _results = search_packages(\"rust\", &filters).await.unwrap();\n    let elapsed = start.elapsed();\n\n    // Performance target: <100ms for small registry\n    // For larger registries (1000+), this should still be under 100ms\n    assert!(\n        elapsed.as_millis() < 100,\n        \"Search took {}ms, expected <100ms\",\n        elapsed.as_millis()\n    );\n\n    // Assert\n});\n\nasync_test!(test_search_multiple_filters_combined, async {\n    let _temp = create_test_registry().unwrap();\n\n    let mut filters = SearchFilters::new();\n    filters.category = Some(\"rust\".to_string());\n    filters.min_stars = Some(100);\n    filters.sort = \"downloads\".to_string();\n    filters.limit = 5;\n\n    let results = search_packages(\"web\", &filters).await.unwrap();\n\n    // All results should match all filters\n    for result in &results {\n        assert_eq!(result.category, Some(\"rust\".to_string()));\n        assert!(result.stars >= 100);\n    }\n\n    // Should be sorted by downloads\n    for i in 0..results.len().saturating_sub(1) {\n        assert!(results[i].downloads >= results[i + 1].downloads);\n    }\n\n    // Assert\n});\n\nasync_test!(test_search_empty_query, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new();\n    let results = search_packages(\"\", &filters).await.unwrap();\n\n    // Empty query might return all packages or none, but shouldn't error\n    // Result is already unwrapped, so just check it exists\n    let _ = results;\n\n    // Assert\n});\n\nasync_test!(test_search_tag_matching, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new();\n    let results = search_packages(\"axum\", &filters).await.unwrap();\n\n    // Should find packages tagged with \"axum\"\n    let has_axum = results.iter().any(|r| r.tags.contains(&\"axum\".to_string()));\n    assert!(has_axum, \"Should find packages with axum tag\");\n\n    // Assert\n});\n\nasync_test!(test_search_case_insensitive, async {\n    let _temp = create_test_registry().unwrap();\n\n    let filters = SearchFilters::new();\n\n    let results_lower = search_packages(\"rust\", &filters).await.unwrap();\n    let results_upper = search_packages(\"RUST\", &filters).await.unwrap();\n    let results_mixed = search_packages(\"RuSt\", &filters).await.unwrap();\n\n    // All should return same results (case insensitive)\n    assert_eq!(results_lower.len(), results_upper.len());\n    assert_eq!(results_lower.len(), results_mixed.len());\n\n    // Assert\n});\n"
        }
    ]
}