diff --git a/app/gitignore-gen/tests/unit/combine_tests.rs b/app/gitignore-gen/tests/unit/combine_tests.rs new file mode 100644 index 0000000..6872735 --- /dev/null +++ b/app/gitignore-gen/tests/unit/combine_tests.rs @@ -0,0 +1,207 @@ +use crate::templates::TemplateLoader; + +#[cfg(test)] +mod combine_tests { + use super::*; + + #[test] + fn test_combine_removes_duplicates() { + let loader = TemplateLoader::new(None); + + let result1 = loader.combine_templates(&["rust"]); + assert!(result1.is_ok()); + + let result2 = loader.combine_templates(&["rust", "rust"]); + assert!(result2.is_ok()); + + let count1 = result1.unwrap().lines().filter(|l| !l.starts_with("#")).count(); + let count2 = result2.unwrap().lines().filter(|l| !l.starts_with("#")).count(); + + assert_eq!(count1, count2); + } + + #[test] + fn test_combine_preserves_unique_patterns() { + let loader = TemplateLoader::new(None); + + let rust_result = loader.combine_templates(&["rust"]); + let python_result = loader.combine_templates(&["python"]); + let combined = loader.combine_templates(&["rust", "python"]); + + assert!(combined.is_ok()); + + let combined_content = combined.unwrap(); + + assert!(combined_content.contains("# Generated by gitignore-gen")); + assert!(combined_content.contains("rust") || combined_content.contains("python")); + } + + #[test] + fn test_combine_multiple_templates() { + let loader = TemplateLoader::new(None); + + let templates = ["rust", "python", "go"]; + let result = loader.combine_templates(&templates); + + assert!(result.is_ok()); + let content = result.unwrap(); + assert!(!content.is_empty()); + } + + #[test] + fn test_combine_with_nonexistent_template() { + let loader = TemplateLoader::new(None); + + let result = loader.combine_templates(&["rust", "nonexistent_template"]); + assert!(result.is_ok()); + } + + #[test] + fn test_combine_empty_list() { + let loader = TemplateLoader::new(None); + + let result = loader.combine_templates(&[]); + assert!(result.is_ok()); + let content = result.unwrap(); + assert!(content.contains("Combined templates:")); + } + + #[test] + fn test_combine_order() { + let loader = TemplateLoader::new(None); + + let rust_result = loader.combine_templates(&["rust"]); + let python_result = loader.combine_templates(&["python"]); + let combined = loader.combine_templates(&["rust", "python"]); + + assert!(combined.is_ok()); + let combined_content = combined.unwrap(); + + assert!(rust_result.unwrap().len() > 0); + assert!(python_result.unwrap().len() > 0); + assert!(combined_content.len() >= rust_result.unwrap().len()); + } + + #[test] + fn test_combine_header_format() { + let loader = TemplateLoader::new(None); + + let result = loader.combine_templates(&["rust", "python", "go"]); + assert!(result.is_ok()); + + let content = result.unwrap(); + let lines: Vec<&str> = content.lines().collect(); + + assert_eq!(lines[0], "# Generated by gitignore-gen"); + assert!(lines[1].starts_with("# Combined templates:")); + } + + #[test] + fn test_combine_pattern_deduplication_across_templates() { + let loader = TemplateLoader::new(None); + + let rust_templates = loader.get_template("rust"); + let python_templates = loader.get_template("python"); + + assert!(rust_templates.is_some()); + assert!(python_templates.is_some()); + + let combined = loader.combine_templates(&["rust", "python"]); + assert!(combined.is_ok()); + + let content = combined.unwrap(); + let lines: Vec<&str> = content.lines().collect(); + let pattern_lines: Vec<&str> = lines + .iter() + .filter(|l| !l.starts_with("#")) + .filter(|l| !l.is_empty()) + .cloned() + .collect(); + + let unique_patterns: std::collections::HashSet<&str> = + pattern_lines.iter().cloned().collect(); + + assert_eq!(pattern_lines.len(), unique_patterns.len()); + } +} + +#[cfg(test)] +mod pattern_tests { + use super::*; + + #[test] + fn test_pattern_format_valid() { + let valid_patterns = [ + "*.log", + "target/", + ".env", + "/build", + "*.py[cod]", + "!.gitignore", + ]; + + for pattern in valid_patterns { + assert!(!pattern.is_empty()); + } + } + + #[test] + fn test_pattern_with_directory() { + let loader = TemplateLoader::new(None); + let rust_template = loader.get_template("rust"); + + assert!(rust_template.is_some()); + + let patterns = &rust_template.unwrap().patterns; + let has_target = patterns.iter().any(|p| p.contains("target")); + assert!(has_target); + } + + #[test] + fn test_pattern_with_wildcard() { + let loader = TemplateLoader::new(None); + let python_template = loader.get_template("python"); + + assert!(python_template.is_some()); + + let patterns = &python_template.unwrap().patterns; + let has_wildcard = patterns.iter().any(|p| p.contains('*')); + assert!(has_wildcard); + } +} + +#[cfg(test)] +mod edge_case_tests { + use super::*; + + #[test] + fn test_combine_very_large_list() { + let loader = TemplateLoader::new(None); + let templates = loader.list_templates(); + let result = loader.combine_templates(&templates); + assert!(result.is_ok()); + } + + #[test] + fn test_search_results_sorted() { + let loader = TemplateLoader::new(None); + + let results = loader.search_templates(""); + + for i in 0..results.len().saturating_sub(1) { + assert!(results[i] <= results[i + 1]); + } + } + + #[test] + fn test_all_embedded_templates_loadable() { + let loader = TemplateLoader::new(None); + let templates = loader.list_templates(); + + for name in templates { + let template = loader.get_template(name); + assert!(template.is_some()); + assert_eq!(template.unwrap().name, name); + } + } +}