//! Integration tests for CLI config file discovery. //! //! These tests verify that the CLI correctly discovers and loads configuration files //! in various formats (.toml, .yaml, .json) with case-insensitive extension //! matching, explicit --config flag support, and proper error handling. use std::fs; use std::path::PathBuf; use std::process::Command; use tempfile::tempdir; /// Get the path to the kreuzberg binary. fn get_binary_path() -> String { let manifest_dir = env!("CARGO_MANIFEST_DIR"); format!("{}/../../target/debug/kreuzberg", manifest_dir) } /// Build the binary before running tests. fn build_binary() { let status = Command::new("cargo") .args(["build", "--bin", "kreuzberg"]) .status() .expect("Failed to build kreuzberg binary"); assert!(status.success(), "Failed to build kreuzberg binary"); } /// Get the test_documents directory path. fn get_test_documents_dir() -> PathBuf { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); manifest_dir.parent().unwrap().parent().unwrap().join("test_documents") } /// Get a test file path relative to test_documents/. fn get_test_file(relative_path: &str) -> String { get_test_documents_dir() .join(relative_path) .to_string_lossy() .to_string() } #[test] fn test_discover_kreuzberg_toml_in_current_directory() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join(".kreuzberg.toml"); fs::write( &config_path, r#" use_cache = false enable_quality_processing = false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_discover_kreuzberg_yaml_in_current_directory() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join(".kreuzberg.yaml"); fs::write( &config_path, r#" use_cache: false enable_quality_processing: false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_discover_kreuzberg_yml_in_current_directory() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join(".kreuzberg.yaml"); fs::write( &config_path, r#" use_cache: false enable_quality_processing: false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_discover_kreuzberg_json_in_current_directory() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join(".kreuzberg.json"); fs::write( &config_path, r#"{ "use_cache": false, "enable_quality_processing": false }"#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_case_insensitive_toml_extension() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom.TOML"); fs::write( &config_path, r#" use_cache = false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_case_insensitive_yaml_extension() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom.Yaml"); fs::write( &config_path, r#" use_cache: false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_case_insensitive_yml_extension() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom.YML"); fs::write( &config_path, r#" use_cache: false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_case_insensitive_json_extension() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom.JSON"); fs::write( &config_path, r#"{ "use_cache": false }"#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_explicit_config_path_toml() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom_config.toml"); fs::write( &config_path, r#" use_cache = false enable_quality_processing = false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_explicit_config_path_yaml() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom_config.yaml"); fs::write( &config_path, r#" use_cache: false enable_quality_processing: false "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_explicit_config_path_json() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("custom_config.json"); fs::write( &config_path, r#"{ "use_cache": false, "enable_quality_processing": false }"#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_invalid_config_extension() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("config.txt"); fs::write(&config_path, "invalid content").unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); let stderr = String::from_utf8_lossy(&output.stderr); assert!( stderr.contains(".toml") || stderr.contains(".yaml") || stderr.contains(".json"), "Error message should mention supported extensions: {}", stderr ); } #[test] fn test_malformed_toml_config() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("bad_config.toml"); fs::write(&config_path, "use_cache = [[[[[").unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); } #[test] fn test_malformed_yaml_config() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("bad_config.yaml"); fs::write(&config_path, "use_cache: [[[[[").unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); } #[test] fn test_malformed_json_config() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("bad_config.json"); fs::write(&config_path, r#"{"use_cache": [[[[[}"#).unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); } #[test] fn test_nonexistent_config_file() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("nonexistent.toml"); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); } #[test] fn test_default_config_when_no_file_found() { build_binary(); let dir = tempdir().unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let output = Command::new(get_binary_path()) .current_dir(dir.path()) .args(["extract", test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!( output.status.success(), "Command failed: {}", String::from_utf8_lossy(&output.stderr) ); } #[test] fn test_invalid_config_values() { build_binary(); let dir = tempdir().unwrap(); let config_path = dir.path().join("invalid.toml"); fs::write( &config_path, r#" use_cache = "not_a_bool" "#, ) .unwrap(); let test_file = get_test_file("text/simple.txt"); if !PathBuf::from(&test_file).exists() { tracing::debug!("Skipping test: {} not found", test_file); return; } let config_arg = config_path.to_string_lossy().into_owned(); let output = Command::new(get_binary_path()) .args(["extract", "--config", config_arg.as_str(), test_file.as_str()]) .output() .expect("Failed to execute kreuzberg"); assert!(!output.status.success()); }