use git_iris::context::{ChangeType, StagedFile}; use git_iris::file_analyzers::get_analyzer; #[test] fn test_rust_analyzer() { let analyzer = get_analyzer("test.rs"); let change = StagedFile { path: "test.rs".to_string(), change_type: ChangeType::Modified, diff: r#" +pub fn new_function() { + println!("Hello, world!"); +} -struct OldStruct { - field: i32, -} +struct NewStruct { + field: String, +} "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.rs", &change); println!("Rust Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified functions: new_function".to_string())); assert!(analysis.contains(&"Modified structs: OldStruct, NewStruct".to_string())); } #[test] fn test_javascript_analyzer() { let analyzer = get_analyzer("test.js"); let change = StagedFile { path: "test.js".to_string(), change_type: ChangeType::Modified, diff: r#" +function newFunction() { + console.log("Hello, world!"); +} -class OldClass { - constructor() {} -} +class NewClass extends React.Component { + render() { + return
Hello
; + } +} +const FunctionalComponent = () => { + return
Functional
; +} +import { useState } from 'react'; "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.js", &change); println!("JavaScript Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified functions: newFunction, FunctionalComponent".to_string())); assert!(analysis.contains(&"Modified classes: OldClass, NewClass".to_string())); assert!(analysis.contains(&"Import statements have been modified".to_string())); let react_components = analysis .iter() .find(|&s| s.starts_with("Modified React components:")) .expect("No React components analysis found"); assert!(react_components.contains("NewClass")); assert!(react_components.contains("FunctionalComponent")); } #[test] fn test_python_analyzer() { let analyzer = get_analyzer("test.py"); let change = StagedFile { path: "test.py".to_string(), change_type: ChangeType::Modified, diff: r#" +def new_function(): + print("Hello, world!") -class OldClass: - pass +class NewClass: + def __init__(self): + pass +@decorator +def decorated_function(): + pass +from module import something "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.py", &change); println!("Python Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified functions: new_function, decorated_function".to_string())); assert!(analysis.contains(&"Modified classes: OldClass, NewClass".to_string())); assert!(analysis.contains(&"Import statements have been modified".to_string())); assert!(analysis.contains(&"Modified decorators: decorator".to_string())); } #[test] fn test_yaml_analyzer() { let analyzer = get_analyzer("test.yaml"); let change = StagedFile { path: "test.yaml".to_string(), change_type: ChangeType::Modified, diff: r" +new_key: value -old_key: value list: + - new item - - old item nested: + inner_key: value " .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.yaml", &change); println!("YAML Test Debug: Analysis results: {analysis:?}"); let top_level_keys_analysis = analysis .iter() .find(|&s| s.starts_with("Modified top-level keys:")) .expect("No top-level keys analysis found"); assert!(top_level_keys_analysis.contains("new_key")); assert!(top_level_keys_analysis.contains("old_key")); assert!(!top_level_keys_analysis.contains("inner_key")); assert!(analysis.contains(&"List structures have been modified".to_string())); assert!(analysis.contains(&"Nested structures have been modified".to_string())); } #[test] fn test_json_analyzer() { let analyzer = get_analyzer("test.json"); let change = StagedFile { path: "test.json".to_string(), change_type: ChangeType::Modified, diff: r#" + "new_key": "value", - "old_key": "value", "array": [ + "new item", - "old item" ], "nested": { + "inner_key": "value" } "# .to_string(), analysis: Vec::new(), content_excluded: false, content: None, }; let analysis = analyzer.analyze("test.json", &change); println!("JSON Test Debug: Analysis results: {analysis:?}"); assert!(analysis .iter() .any(|s| s.starts_with("Modified top-level keys:"))); assert!(analysis.contains(&"Array structures have been modified".to_string())); assert!(analysis.contains(&"Nested objects have been modified".to_string())); let top_level_keys_analysis = analysis .iter() .find(|&s| s.starts_with("Modified top-level keys:")) .expect("No top-level keys analysis found"); assert!(top_level_keys_analysis.contains("new_key")); assert!(top_level_keys_analysis.contains("old_key")); assert!(!top_level_keys_analysis.contains("inner_key")); } #[test] fn test_markdown_analyzer() { let analyzer = get_analyzer("test.md"); let change = StagedFile { path: "test.md".to_string(), change_type: ChangeType::Modified, diff: r" +# New Header -## Old Header + - New list item - * Old list item +``` +New code block +``` +[New link](https://example.com) -[Old link](https://old-example.com) " .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.md", &change); println!("Markdown Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified headers: New Header, Old Header".to_string())); assert!(analysis.contains(&"List structures have been modified".to_string())); assert!(analysis.contains(&"Code blocks have been modified".to_string())); assert!(analysis.contains(&"Links have been modified".to_string())); } #[test] fn test_default_analyzer() { let analyzer = get_analyzer("unknown.xyz"); let change = StagedFile { path: "unknown.xyz".to_string(), change_type: ChangeType::Modified, diff: "Some changes".to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("unknown.xyz", &change); println!("Default Analyzer Test Debug: Analysis results: {analysis:?}"); assert!(analysis.is_empty()); } #[test] fn test_java_analyzer() { let analyzer = get_analyzer("test.java"); let change = StagedFile { path: "test.java".to_string(), change_type: ChangeType::Modified, diff: r#" +public class NewClass { + public void newMethod() { + System.out.println("Hello, World!"); + } +} -private class OldClass { - private void oldMethod() { - // Do nothing - } -} +import java.util.List; -import java.util.ArrayList; "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.java", &change); println!("Java analysis results: {analysis:?}"); // Check for modified classes let class_analysis = analysis .iter() .find(|&s| s.starts_with("Modified classes:")) .expect("No class analysis found"); assert!(class_analysis.contains("NewClass"), "NewClass not detected"); assert!(class_analysis.contains("OldClass"), "OldClass not detected"); // Check for modified methods let method_analysis = analysis .iter() .find(|&s| s.starts_with("Modified methods:")) .expect("No method analysis found"); assert!( method_analysis.contains("newMethod"), "newMethod not detected" ); assert!( method_analysis.contains("oldMethod"), "oldMethod not detected" ); // Check for import changes assert!( analysis.contains(&"Import statements have been modified".to_string()), "Failed to detect import changes. Analysis: {analysis:?}" ); } #[test] fn test_kotlin_analyzer() { let analyzer = get_analyzer("test.kt"); let change = StagedFile { path: "test.kt".to_string(), change_type: ChangeType::Modified, diff: r#" +class NewClass { + fun newFunction() { + println("Hello, Kotlin!") + } +} -object OldObject { - fun oldFunction() { - // Do nothing - } -} +import kotlin.collections.List -import kotlin.collections.ArrayList "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.kt", &change); println!("Kotlin analysis results: {analysis:?}"); // Helper function to check if any string in the analysis contains all expected substrings #[allow(clippy::items_after_statements)] fn contains_all_substrings(analysis: &[String], substrings: &[&str]) -> bool { analysis .iter() .any(|s| substrings.iter().all(|&sub| s.contains(sub))) } // Check for the presence of the entire expected strings assert!(contains_all_substrings( &analysis, &["NewClass", "OldObject"] )); assert!(contains_all_substrings( &analysis, &["newFunction", "oldFunction"] )); assert!(analysis.contains(&"Import statements have been modified".to_string())); } #[test] fn test_gradle_analyzer() { let analyzer = get_analyzer("build.gradle"); let change = StagedFile { path: "build.gradle".to_string(), change_type: ChangeType::Modified, diff: r" + implementation 'com.example:new-library:1.0.0' - implementation 'com.example:old-library:0.9.0' +plugins { + id 'com.android.application' +} -apply plugin: 'java' +task newTask { + doLast { + println 'Executing new task' + } +} " .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("build.gradle", &change); assert!(analysis.contains(&"Dependencies have been modified".to_string())); assert!(analysis.contains(&"Plugins have been modified".to_string())); assert!(analysis.contains(&"Tasks have been modified".to_string())); } #[test] fn test_c_analyzer() { let analyzer = get_analyzer("test.c"); let change = StagedFile { path: "test.c".to_string(), change_type: ChangeType::Modified, diff: r#" +void new_function() { + printf("Hello, world!"); +} -struct OldStruct { - int field; -} +struct NewStruct { + char field; +} +#include -#include "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.c", &change); println!("C Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified functions: new_function".to_string())); assert!(analysis .iter() .any(|s| s.contains("OldStruct") && s.contains("NewStruct"))); assert!(analysis.contains(&"Include statements have been modified".to_string())); } #[test] fn test_c_analyzer_metadata() { let analyzer = get_analyzer("Makefile"); let content = r" VERSION = 1.0 LIBS += -lm "; let metadata = analyzer.extract_metadata("Makefile", content); assert_eq!(metadata.language, Some("C".to_string())); assert_eq!(metadata.build_system, Some("Makefile".to_string())); assert_eq!(metadata.version, Some("1.0".to_string())); assert_eq!(metadata.dependencies, vec!["-lm".to_string()]); } #[test] fn test_cpp_analyzer() { let analyzer = get_analyzer("test.cpp"); let change = StagedFile { path: "test.cpp".to_string(), change_type: ChangeType::Modified, diff: r#" +void newFunction() { + std::cout << "Hello, world!" << std::endl; +} -class OldClass { - OldClass() {} -} +class NewClass { + NewClass() {} +} +#include -#include "# .to_string(), analysis: Vec::new(), content: None, content_excluded: false, }; let analysis = analyzer.analyze("test.cpp", &change); println!("C++ Test Debug: Analysis results: {analysis:?}"); assert!(analysis.contains(&"Modified functions: newFunction".to_string())); assert!(analysis .iter() .any(|s| s.contains("OldClass") && s.contains("NewClass"))); assert!(analysis.contains(&"Include statements have been modified".to_string())); } #[test] fn test_cpp_analyzer_metadata() { let analyzer = get_analyzer("CMakeLists.txt"); let content = r" project(MyProject VERSION 1.0) find_package(Boost REQUIRED) "; let metadata = analyzer.extract_metadata("CMakeLists.txt", content); assert_eq!(metadata.language, Some("C++".to_string())); assert_eq!(metadata.build_system, Some("CMake".to_string())); assert_eq!(metadata.version, Some("1.0".to_string())); assert!(metadata.dependencies.contains(&"Boost".to_string())); }