mod fixtures;
use codesearch::search::search_code;
use codesearch::types::SearchOptions;
use codesearch::{analysis, complexity, deadcode, export};
use fixtures::TestWorkspace;
use std::fs;
#[test]
fn test_search_and_export_workflow() {
let workspace = TestWorkspace::new();
let options = SearchOptions::default();
let results = search_code("test", workspace.path(), &options).expect("Search failed");
assert!(!results.is_empty(), "Should find test matches");
let export_path = workspace.path().join("results.json");
export::export_results(&results, export_path.to_str().unwrap(), "test").expect("Export failed");
assert!(export_path.exists());
let content = fs::read_to_string(&export_path).expect("Failed to read export");
assert!(content.contains("test"));
}
#[test]
fn test_search_with_multiple_extensions() {
let workspace = TestWorkspace::new();
let options = SearchOptions {
extensions: Some(vec!["rs".to_string(), "py".to_string()]),
..Default::default()
};
let results = search_code("main", workspace.path(), &options).expect("Search failed");
assert!(!results.is_empty());
for result in results {
assert!(result.file.ends_with(".rs") || result.file.ends_with(".py"));
}
}
#[test]
fn test_search_with_fuzzy_matching() {
let workspace = TestWorkspace::new();
let options = SearchOptions {
fuzzy: true,
fuzzy_threshold: 0.5,
..Default::default()
};
let results = search_code("tst", workspace.path(), &options).expect("Search failed");
assert!(!results.is_empty());
}
#[test]
fn test_analyze_then_search() {
let workspace = TestWorkspace::new();
let analyze_result = analysis::analyze_codebase(workspace.path(), None, None);
assert!(analyze_result.is_ok());
let options = SearchOptions::default();
let results = search_code("fn", workspace.path(), &options).expect("Search failed");
assert!(!results.is_empty());
}
#[test]
fn test_complexity_analysis_workflow() {
let mut workspace = TestWorkspace::new();
workspace.add_file(
"complex.rs",
r#"
fn complex_function(x: i32) -> i32 {
if x > 0 {
if x > 10 {
if x > 20 {
return x * 2;
}
return x + 10;
}
return x + 5;
}
return 0;
}
"#,
);
let result = complexity::analyze_complexity(
workspace.path(),
Some(&[String::from("rs")]),
None,
Some(1),
false,
);
assert!(result.is_ok());
}
#[test]
fn test_deadcode_detection_workflow() {
let mut workspace = TestWorkspace::new();
workspace.add_file(
"deadcode.rs",
r#"
fn used_function() {
println!("Used");
}
fn unused_function() {
// TODO: implement this
let unused_var = 42;
}
"#,
);
let result = deadcode::detect_dead_code(workspace.path(), Some(&[String::from("rs")]), None);
assert!(result.is_ok());
}
#[test]
fn test_search_ranking() {
let workspace = TestWorkspace::new();
let options = SearchOptions {
rank: true,
..Default::default()
};
let results = search_code("test", workspace.path(), &options).expect("Search failed");
if results.len() > 1 {
for i in 0..results.len() - 1 {
assert!(results[i].score >= results[i + 1].score);
}
}
}
#[test]
fn test_search_with_exclusions() {
let workspace = TestWorkspace::new();
let subdir = workspace.create_subdir("excluded");
fs::write(subdir.join("test.rs"), "fn excluded_test() {}").expect("Failed to write");
let options = SearchOptions {
exclude: Some(vec!["excluded".to_string()]),
..Default::default()
};
let results = search_code("excluded", workspace.path(), &options).expect("Search failed");
for result in results {
assert!(!result.file.contains("excluded"));
}
}
#[test]
fn test_max_results_limit() {
let mut workspace = TestWorkspace::new();
for i in 0..10 {
workspace.add_file(&format!("file{i}.txt"), "test test test test test");
}
let options = SearchOptions {
max_results: 2,
..Default::default()
};
let results = search_code("test", workspace.path(), &options).expect("Search failed");
for result in results {
assert!(result.matches.len() <= 2);
}
}
#[test]
fn test_case_sensitive_search() {
let mut workspace = TestWorkspace::new();
workspace.add_file("case.txt", "Test TEST test TeSt");
let options_sensitive = SearchOptions {
ignore_case: false,
..Default::default()
};
let results = search_code("Test", workspace.path(), &options_sensitive).expect("Search failed");
for result in results {
assert!(result.content.contains("Test"));
}
}
#[test]
fn test_case_insensitive_search() {
let mut workspace = TestWorkspace::new();
workspace.add_file("case.txt", "Test TEST test TeSt");
let options_insensitive = SearchOptions {
ignore_case: true,
..Default::default()
};
let results =
search_code("test", workspace.path(), &options_insensitive).expect("Search failed");
assert!(!results.is_empty());
}
#[test]
fn test_empty_directory() {
let workspace = TestWorkspace::with_files(&[]);
let options = SearchOptions::default();
let results = search_code("test", workspace.path(), &options).expect("Search failed");
assert!(results.is_empty());
}
#[test]
fn test_nested_directories() {
let workspace = TestWorkspace::new();
let subdir1 = workspace.create_subdir("level1");
let subdir2 = subdir1.join("level2");
fs::create_dir_all(&subdir2).expect("Failed to create nested dir");
fs::write(subdir2.join("nested.rs"), "fn nested_test() {}").expect("Failed to write");
let options = SearchOptions::default();
let results = search_code("nested", workspace.path(), &options).expect("Search failed");
assert!(!results.is_empty());
assert!(results[0].file.contains("level1"));
assert!(results[0].file.contains("level2"));
}