use ggen_domain::generation::codeowners::{
generate_codeowners, generate_codeowners_default, CodeownersConfig,
};
use std::fs;
use tempfile::TempDir;
#[test]
fn test_generate_codeowners_default() -> std::io::Result<()> {
let temp_dir = TempDir::new()?;
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/user"))?;
fs::create_dir_all(base_path.join("ontology/product"))?;
fs::write(
base_path.join("ontology/user/OWNERS"),
"@user-team\n@alice\n",
)?;
fs::write(
base_path.join("ontology/product/OWNERS"),
"@product-team\n@bob\n",
)?;
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string(), "src/domain".to_string()],
output_path: Some(
base_path
.join(".github/CODEOWNERS")
.to_string_lossy()
.to_string(),
),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(result.is_ok(), "CODEOWNERS generation should succeed");
Ok(())
}
#[test]
fn test_codeowners_aggregates_multiple_owners() -> std::io::Result<()> {
let temp_dir = TempDir::new()?;
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/users"))?;
fs::create_dir_all(base_path.join("ontology/payments"))?;
fs::create_dir_all(base_path.join("ontology/notifications"))?;
fs::write(base_path.join("ontology/users/OWNERS"), "@user-team\n")?;
fs::write(
base_path.join("ontology/payments/OWNERS"),
"@finance-team\n",
)?;
fs::write(
base_path.join("ontology/notifications/OWNERS"),
"@platform-team\n",
)?;
let output_path = base_path.join(".github/CODEOWNERS");
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(result.is_ok(), "Generation should succeed");
if let Ok(codeowners_content) = fs::read_to_string(&output_path) {
assert!(
codeowners_content.contains("@user-team"),
"Should contain user team"
);
assert!(
codeowners_content.contains("@finance-team"),
"Should contain finance team"
);
assert!(
codeowners_content.contains("@platform-team"),
"Should contain platform team"
);
}
Ok(())
}
#[test]
fn test_codeowners_path_mappings() -> std::io::Result<()> {
let temp_dir = TempDir::new()?;
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/user"))?;
fs::write(base_path.join("ontology/user/OWNERS"), "@user-team\n")?;
fs::create_dir_all(base_path.join(".github"))?;
let output_path = base_path.join(".github/CODEOWNERS");
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string(), "src/domain".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(result.is_ok(), "Generation should succeed");
if let Ok(content) = fs::read_to_string(&output_path) {
assert!(!content.is_empty(), "CODEOWNERS should not be empty");
}
Ok(())
}
#[test]
fn test_missing_owners_files_graceful() -> std::io::Result<()> {
let temp_dir = TempDir::new()?;
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/user"))?;
let output_path = base_path.join(".github/CODEOWNERS");
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(
result.is_ok(),
"Should handle missing OWNERS files gracefully"
);
Ok(())
}
#[test]
fn test_default_codeowners_format() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/users")).unwrap();
fs::write(base_path.join("ontology/users/OWNERS"), "@user-team\n").unwrap();
fs::create_dir_all(base_path.join(".github")).unwrap();
let output_path = base_path.join(".github/CODEOWNERS");
let result = generate_codeowners_default(base_path, &output_path);
assert!(
result.is_ok(),
"Default CODEOWNERS generation should succeed"
);
}
#[test]
fn test_codeowners_respects_enabled_flag() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let output_path = base_path.join(".github/CODEOWNERS");
let config = CodeownersConfig {
enabled: false,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(result.is_err(), "Generation should fail when disabled");
}
#[test]
fn test_codeowners_idempotent_generation() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/user")).unwrap();
fs::write(base_path.join("ontology/user/OWNERS"), "@team\n").unwrap();
fs::create_dir_all(base_path.join(".github")).unwrap();
let output_path = base_path.join(".github/CODEOWNERS");
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let first = generate_codeowners(&config, base_path);
assert!(first.is_ok(), "First generation should succeed");
let second = generate_codeowners(&config, base_path);
assert!(second.is_ok(), "Second generation should succeed");
if first.is_ok() && second.is_ok() {
if let (Ok(content1), Ok(content2)) = (
fs::read_to_string(&output_path),
fs::read_to_string(&output_path),
) {
assert_eq!(
content1, content2,
"CODEOWNERS should be consistent on regeneration"
);
}
}
}
#[test]
fn test_complex_owners_patterns() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
fs::create_dir_all(base_path.join("ontology/user")).unwrap();
fs::write(
base_path.join("ontology/user/OWNERS"),
"@user-team\n@alice @bob\n*.breaking.ttl @platform-team\n",
)
.unwrap();
let output_path = base_path.join(".github/CODEOWNERS");
fs::create_dir_all(base_path.join(".github")).unwrap();
let config = CodeownersConfig {
enabled: true,
source_dirs: vec!["ontology".to_string()],
base_dirs: vec!["src/generated".to_string()],
output_path: Some(output_path.to_string_lossy().to_string()),
auto_regenerate: false,
};
let result = generate_codeowners(&config, base_path);
assert!(result.is_ok(), "Should handle complex patterns");
}