use anyhow::Result;
use lumin::search::{SearchOptions, search_files};
use serial_test::serial;
use std::path::Path;
mod test_helpers;
use test_helpers::{TEST_DIR, TestEnvironment};
#[cfg(test)]
mod search_tests {
use super::*;
#[test]
#[serial]
fn test_search_default_options() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "fn";
let options = SearchOptions::default();
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(!results.lines.is_empty());
for result in &results.lines {
assert!(result.line_content.contains(pattern));
}
assert!(
!results
.lines
.iter()
.any(|r| r.file_path.to_string_lossy().contains(".hidden"))
);
Ok(())
}
#[test]
#[serial]
fn test_search_case_sensitive() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "Fn"; let mut options = SearchOptions::default();
options.case_sensitive = true;
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(!results.lines.iter().any(|r| r.line_content.contains("fn ")));
Ok(())
}
#[test]
#[serial]
fn test_search_case_insensitive() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "FN"; let mut options = SearchOptions::default();
options.case_sensitive = false;
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(results.lines.iter().any(|r| r.line_content.contains("fn ")));
Ok(())
}
#[test]
#[serial]
fn test_search_respect_gitignore() -> Result<()> {
let _env = TestEnvironment::setup()?;
let secret_file = Path::new(TEST_DIR).join(".hidden").join("secret.txt");
assert!(
secret_file.exists(),
"Test setup error: .hidden/secret.txt doesn't exist"
);
let content = std::fs::read_to_string(&secret_file)?;
assert!(
content.contains("API_KEY"),
"Test setup error: API_KEY not found in secret.txt"
);
let pattern = "API_KEY";
let options = SearchOptions::default();
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(
!results
.lines
.iter()
.any(|r| r.file_path.to_string_lossy().contains(".hidden")),
"Found .hidden files when respecting gitignore"
);
Ok(())
}
#[test]
#[serial]
fn test_search_ignore_gitignore() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "API_KEY";
let mut options = SearchOptions::default();
options.respect_gitignore = false;
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(
results
.lines
.iter()
.any(|r| r.file_path.to_string_lossy().contains(".hidden")),
"Did not find .hidden files when ignoring gitignore"
);
Ok(())
}
#[test]
#[serial]
fn test_search_no_matches() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "THIS_PATTERN_SHOULD_NOT_EXIST_ANYWHERE";
let options = SearchOptions::default();
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(results.lines.is_empty());
Ok(())
}
#[test]
#[serial]
fn test_no_trailing_newlines() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "fn";
let options = SearchOptions::default();
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(!results.lines.is_empty());
for result in &results.lines {
assert!(
!result.line_content.ends_with('\n'),
"line_content contains trailing newline: {:?}",
result.line_content
);
}
Ok(())
}
#[test]
#[serial]
fn test_no_trailing_newlines_in_context() -> Result<()> {
let _env = TestEnvironment::setup()?;
let pattern = "fn";
let mut options = SearchOptions::default();
options.before_context = 2;
options.after_context = 2;
let results = search_files(pattern, Path::new(TEST_DIR), &options)?;
assert!(!results.lines.is_empty());
assert!(results.lines.iter().any(|r| r.is_context));
for result in &results.lines {
assert!(
!result.line_content.ends_with('\n'),
"line_content contains trailing newline: {:?}",
result.line_content
);
}
Ok(())
}
}