use codetwin::config::Config;
use codetwin::discovery;
use codetwin::ir::{Blueprint, Element, Visibility};
use std::env;
use std::path::PathBuf;
#[test]
fn test_error_context_chains() {
let result = Config::load("non_existent_path/codetwin.toml");
assert!(
result.is_err(),
"Should fail when config file doesn't exist"
);
let err_msg = format!("{:#}", result.unwrap_err());
assert!(
err_msg.contains("Failed to") || err_msg.contains("toml"),
"Error should provide context about failure: {}",
err_msg
);
}
#[test]
fn test_error_context_in_discovery() {
let result = discovery::find_source_files(&["non_existent_directory".to_string()], &[]);
match result {
Ok(files) => {
assert_eq!(files.len(), 0);
}
Err(_e) => {
}
}
}
#[test]
fn test_discovery_excludes_target_directory() {
let src_files =
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover src directory");
assert!(
!src_files.is_empty(),
"Should discover source files in src/"
);
for file in &src_files {
assert!(
!file.to_string_lossy().contains("target/"),
"Should not include files from target/ directory: {:?}",
file
);
}
}
#[test]
fn test_discovery_finds_source_files() {
let src_files =
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover src directory");
assert!(
src_files.len() > 0,
"Should discover at least one source file"
);
for file in &src_files {
assert!(
matches!(
file.extension().and_then(|ext| ext.to_str()),
Some("rs") | Some("py")
),
"Should only find supported source files: {:?}",
file
);
}
}
#[test]
fn test_discovery_results_sorted() {
let files =
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover src directory");
let mut sorted = files.clone();
sorted.sort();
assert_eq!(
files, sorted,
"Discovery results should be sorted for consistency"
);
}
#[test]
fn test_blueprint_serialization() {
let blueprint = Blueprint {
source_path: PathBuf::from("test.rs"),
language: "rust".to_string(),
elements: vec![],
dependencies: vec!["std".to_string()],
};
let json = serde_json::to_value(&blueprint).expect("Should serialize to JSON");
assert!(
json["source_path"].is_string(),
"Should have source_path field"
);
assert!(json["language"].is_string(), "Should have language field");
assert!(json["elements"].is_array(), "Should have elements array");
assert!(
json["dependencies"].is_array(),
"Should have dependencies array"
);
}
#[test]
fn test_config_serialization() {
let config = Config::defaults();
let json = serde_json::to_value(&config).expect("Should serialize to JSON");
assert!(json["source_dirs"].is_array(), "Should have source_dirs");
assert!(json["output_file"].is_string(), "Should have output_file");
assert!(json["layout"].is_string(), "Should have layout");
}
#[test]
fn test_element_enum_serialization() {
use codetwin::ir::{Class, Documentation};
let class_elem = Element::Class(Class {
name: "TestClass".to_string(),
visibility: Visibility::Public,
methods: vec![],
properties: vec![],
documentation: Documentation {
summary: Some("A test class".to_string()),
description: None,
examples: vec![],
},
});
let json = serde_json::to_value(&class_elem).expect("Should serialize");
assert!(json["Class"].is_object(), "Should serialize Class variant");
assert_eq!(json["Class"]["name"], "TestClass");
}
#[test]
fn test_logging_env_setup() {
unsafe {
env::set_var("RUST_LOG", "debug");
}
let level = env::var("RUST_LOG").expect("Should set RUST_LOG");
assert_eq!(level, "debug");
unsafe {
env::remove_var("RUST_LOG");
}
}
#[test]
fn test_logging_env_info_level() {
unsafe {
env::set_var("RUST_LOG", "info");
}
let level = env::var("RUST_LOG").expect("Should set RUST_LOG");
assert_eq!(level, "info");
unsafe {
env::remove_var("RUST_LOG");
}
}
#[test]
fn test_config_defaults() {
let config = Config::defaults();
assert!(
!config.source_dirs.is_empty(),
"Should have default source dirs"
);
assert!(
!config.output_file.is_empty(),
"Should have default output file"
);
assert!(!config.layout.is_empty(), "Should have default layout");
}
#[test]
fn test_config_has_exclude_patterns() {
let config = Config::defaults();
assert!(
!config.exclude_patterns.is_empty() || !config.layers.is_empty(),
"Should have some patterns configured"
);
}
#[test]
fn test_discovery_consistency() {
let results1 =
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover files");
let results2 =
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover files again");
assert_eq!(
results1, results2,
"Discovery should produce consistent results across runs"
);
}
#[test]
fn test_multiple_discovery_runs_same_count() {
let counts: Vec<usize> = (0..3)
.map(|_| {
discovery::find_source_files(&["src".to_string()], &Config::defaults().exclude_patterns)
.expect("Should discover files")
.len()
})
.collect();
assert_eq!(counts[0], counts[1], "Discovery run 1 and 2 should match");
assert_eq!(counts[1], counts[2], "Discovery run 2 and 3 should match");
}
#[test]
fn test_glob_pattern_matching() {
use glob::Pattern;
let patterns = vec![
("**/target/**", true), ("**/.git/**", true), ("**/tests/**", true), ("**/.hidden/*", true), ];
for (pattern_str, should_compile) in patterns {
let result = Pattern::new(pattern_str);
if should_compile {
assert!(result.is_ok(), "Pattern '{}' should compile", pattern_str);
}
}
}
#[test]
fn test_pathbuf_conversion() {
let path = PathBuf::from("src/drivers/rust.rs");
let lossy_str = path.to_string_lossy();
assert!(lossy_str.len() > 0, "Should convert to string");
assert!(lossy_str.contains("src"), "Should preserve path components");
}
#[test]
fn test_empty_discovery_result() {
let result = discovery::find_source_files(&[], &[]);
match result {
Ok(files) => assert_eq!(files.len(), 0),
Err(_) => { }
}
}
#[test]
fn test_config_and_discovery_integration() {
let config = Config::defaults();
let files = discovery::find_source_files(&config.source_dirs, &config.exclude_patterns)
.expect("Should discover files from config source directories");
assert!(
files.len() > 0,
"Should find files in configured source directories"
);
}
#[test]
fn test_visibility_enum_serialization() {
let public_vis = Visibility::Public;
let private_vis = Visibility::Private;
let pub_json = serde_json::to_value(&public_vis).expect("Should serialize");
let priv_json = serde_json::to_value(&private_vis).expect("Should serialize");
assert!(
pub_json.is_string(),
"Should serialize Visibility as string"
);
assert!(
priv_json.is_string(),
"Should serialize Visibility as string"
);
}