use anyhow::Result;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
use crate::traverse::{TraverseOptions, traverse_directory};
fn create_test_files(dir: &Path) -> Result<Vec<String>> {
let test_files = [
"file1.txt",
"file2.rs",
"README.md",
"src/main.rs",
"src/lib.rs",
"docs/api.md",
"tests/test_util.rs",
"assets/images/logo.png",
];
for file_path in &test_files {
let full_path = dir.join(file_path);
if let Some(parent) = full_path.parent() {
std::fs::create_dir_all(parent)?;
}
let mut file = File::create(full_path)?;
file.write_all(format!("Test content for {}", file_path).as_bytes())?;
}
Ok(test_files.iter().map(|s| s.to_string()).collect())
}
fn normalize_path(path: &Path) -> String {
path.to_string_lossy().replace("\\", "/").to_string()
}
#[test]
fn test_omit_path_prefix_basic() -> Result<()> {
let temp_dir = TempDir::new()?;
let temp_path = temp_dir.path();
let test_files = create_test_files(temp_path)?;
let options = TraverseOptions {
case_sensitive: false,
respect_gitignore: false, only_text_files: false, pattern: None,
depth: None,
omit_path_prefix: Some(temp_path.to_path_buf()),
};
let results = traverse_directory(temp_path, &options)?;
assert_eq!(
results.len(),
test_files.len(),
"Should find all test files"
);
for result in &results {
assert!(
!result.file_path.starts_with(temp_path),
"Path {} should not start with prefix {}",
result.file_path.display(),
temp_path.display()
);
let normalized_path = normalize_path(&result.file_path);
let found = test_files.iter().any(|f| normalized_path == *f);
assert!(
found,
"File path '{}' not found in test files",
normalized_path
);
}
Ok(())
}
#[test]
fn test_omit_path_prefix_without_removal() -> Result<()> {
let temp_dir = TempDir::new()?;
let temp_path = temp_dir.path();
let _test_files = create_test_files(temp_path)?;
let options = TraverseOptions {
case_sensitive: false,
respect_gitignore: false,
only_text_files: false,
pattern: None,
depth: None,
omit_path_prefix: None, };
let results = traverse_directory(temp_path, &options)?;
for result in &results {
assert!(
result.file_path.starts_with(temp_path),
"Path {} should start with prefix {}",
result.file_path.display(),
temp_path.display()
);
}
Ok(())
}
#[test]
fn test_omit_path_prefix_with_pattern() -> Result<()> {
let temp_dir = TempDir::new()?;
let temp_path = temp_dir.path();
let _test_files = create_test_files(temp_path)?;
let options = TraverseOptions {
case_sensitive: false,
respect_gitignore: false,
only_text_files: false,
pattern: Some("**/*.rs".to_string()), depth: None,
omit_path_prefix: Some(temp_path.to_path_buf()),
};
let results = traverse_directory(temp_path, &options)?;
assert!(results.len() > 0, "Should find some Rust files");
assert!(results.len() < 8, "Should not find all test files");
for result in &results {
assert!(!result.file_path.starts_with(temp_path));
let normalized_path = normalize_path(&result.file_path);
assert!(
normalized_path.ends_with(".rs"),
"File '{}' should be a Rust file",
normalized_path
);
assert_eq!(result.file_type, "rs");
}
Ok(())
}
#[test]
fn test_omit_path_prefix_partial_match() -> Result<()> {
let temp_dir = TempDir::new()?;
let temp_path = temp_dir.path();
let _test_files = create_test_files(temp_path)?;
let non_matching_prefix = if cfg!(windows) {
PathBuf::from("C:\\some\\other\\path")
} else {
PathBuf::from("/some/other/path")
};
let options = TraverseOptions {
case_sensitive: false,
respect_gitignore: false,
only_text_files: false,
pattern: None,
depth: None,
omit_path_prefix: Some(non_matching_prefix.clone()),
};
let results = traverse_directory(temp_path, &options)?;
for result in &results {
assert!(
result.file_path.starts_with(temp_path),
"Path {} should start with temp dir {} when prefix {} doesn't match",
result.file_path.display(),
temp_path.display(),
non_matching_prefix.display()
);
}
Ok(())
}
#[test]
fn test_omit_path_prefix_with_depth_limit() -> Result<()> {
let temp_dir = TempDir::new()?;
let temp_path = temp_dir.path();
let _test_files = create_test_files(temp_path)?;
let options = TraverseOptions {
case_sensitive: false,
respect_gitignore: false,
only_text_files: false,
pattern: None,
depth: Some(1), omit_path_prefix: Some(temp_path.to_path_buf()),
};
let results = traverse_directory(temp_path, &options)?;
assert!(results.len() > 0, "Should find some files");
assert!(results.len() < 8, "Should not find files in subdirectories");
for result in &results {
assert!(!result.file_path.starts_with(temp_path));
let normalized_path = normalize_path(&result.file_path);
assert!(
!normalized_path.contains('/'),
"File '{}' should be in the root directory",
normalized_path
);
}
Ok(())
}