use super::{loader::VoiceLoader, principles::principles_addendum, types::*};
#[test]
fn voice_package_roundtrip_serde() {
let toml = r#"
[meta]
name = "test"
version = "1.0.0"
description = "A test voice"
generated_at = "2026-06-04"
pipeline_version = "tr-voice-0.1"
corpus_cutoff = "2025-01-01"
llm_model = "opus"
[meta.provenance]
source_reviewers = ["Alice", "Bob"]
reviewers_count = 2
total_comments_analyzed = 100
notes = "Test corpus"
[voice]
system_addendum = "Focus on correctness above all."
[knobs]
tone = "formal"
block_bias = "strict"
comment_length = "verbose"
[custom]
extra_addendum = "Also check for performance regressions."
"#;
let pkg: VoicePackage = toml::from_str(toml).expect("should parse test voice.toml");
assert_eq!(pkg.meta.name, "test");
assert_eq!(pkg.meta.version, "1.0.0");
assert_eq!(pkg.meta.provenance.reviewers_count, 2);
assert_eq!(pkg.meta.provenance.total_comments_analyzed, 100);
assert!(
pkg.voice.system_addendum.contains("correctness"),
"voice addendum must be present"
);
assert_eq!(pkg.knobs.tone, "formal");
assert_eq!(pkg.knobs.block_bias, "strict");
assert!(
pkg.custom.extra_addendum.contains("performance"),
"custom extra_addendum must be present"
);
}
#[test]
fn effective_addendum_base_only() {
let pkg = VoicePackage {
voice: VoiceSection {
system_addendum: "Review carefully.".to_string(),
},
..Default::default()
};
assert_eq!(pkg.effective_addendum(), "Review carefully.");
}
#[test]
fn effective_addendum_custom_append() {
let pkg = VoicePackage {
voice: VoiceSection {
system_addendum: "Base review guidance.".to_string(),
},
custom: CustomOverlay {
extra_addendum: "Additional org-specific rule.".to_string(),
voice: None,
},
..Default::default()
};
let effective = pkg.effective_addendum();
let base_pos = effective.find("Base review").unwrap();
let extra_pos = effective.find("Additional org").unwrap();
assert!(
base_pos < extra_pos,
"extra_addendum must come AFTER the base"
);
assert!(
effective.contains("Base review guidance."),
"base must be present"
);
assert!(
effective.contains("Additional org-specific rule."),
"extra must be present"
);
}
#[test]
fn effective_addendum_custom_replace() {
let pkg = VoicePackage {
voice: VoiceSection {
system_addendum: "Generated base.".to_string(),
},
custom: CustomOverlay {
extra_addendum: String::new(),
voice: Some(CustomVoiceOverride {
system_addendum: "Full user replacement.".to_string(),
}),
},
..Default::default()
};
let effective = pkg.effective_addendum();
assert!(
!effective.contains("Generated base"),
"custom replace must remove the generated base"
);
assert!(
effective.contains("Full user replacement"),
"custom replacement must be present"
);
}
#[test]
fn principles_addendum_is_non_empty() {
let p = principles_addendum();
assert!(!p.is_empty(), "principles addendum must not be empty");
assert!(p.len() > 100, "principles addendum must be substantive");
}
#[test]
fn principles_contains_key_concepts() {
let p = principles_addendum();
assert!(
p.contains("correctness") || p.contains("design"),
"principles must mention design/correctness priority"
);
assert!(
p.contains("BLOCK"),
"principles must reference BLOCK severity"
);
assert!(
p.contains("actionable") || p.contains("explain"),
"principles must reference actionable feedback"
);
assert!(
p.to_lowercase().contains("label")
|| p.to_lowercase().contains("nitpick")
|| p.to_lowercase().contains("suggestion"),
"principles must reference comment labeling (Conventional Comments)"
);
assert!(
p.to_lowercase().contains("scope"),
"principles must reference scope discipline"
);
}
#[test]
fn principles_contains_do_not_flag_guardrails() {
let p = principles_addendum();
assert!(
p.contains("Do NOT flag"),
"principles must carry the do-not-flag section"
);
let lower = p.to_lowercase();
assert!(
lower.contains("fmt/clippy") || lower.contains("linters"),
"must mention linter-enforced style nits"
);
assert!(
lower.contains("speculative") || lower.contains("hypothetical"),
"must mention speculative/hypothetical concerns"
);
assert!(
lower.contains("restat") || lower.contains("narrat"),
"must mention restating what the diff does"
);
}
#[test]
fn load_bundled_duetto_voice() {
let loader = VoiceLoader::new();
let pkg = loader.load("duetto").expect("bundled duetto must load");
assert_eq!(pkg.meta.name, "duetto", "meta.name must be duetto");
assert!(
!pkg.voice.system_addendum.is_empty(),
"duetto voice.system_addendum must be non-empty"
);
assert!(
pkg.voice.system_addendum.contains("correctness"),
"duetto addendum must mention correctness"
);
assert!(
pkg.meta.provenance.reviewers_count >= 5,
"duetto must have >= 5 source reviewers"
);
}
#[test]
fn load_missing_voice_errors() {
let loader = VoiceLoader::new();
let err = loader
.load("nonexistent-voice-xyz-abc")
.expect_err("missing voice must produce an error");
assert!(
matches!(err, super::loader::VoiceLoaderError::NotFound { .. }),
"error must be NotFound, got: {err}"
);
assert!(
err.to_string().contains("nonexistent-voice-xyz-abc"),
"error message must include the requested name"
);
}
#[test]
fn load_from_custom_dir() {
let dir = tempfile::tempdir().expect("tempdir");
let voice_dir = dir.path().join("myvoice");
std::fs::create_dir_all(&voice_dir).unwrap();
std::fs::write(
voice_dir.join("voice.toml"),
r#"
[meta]
name = "myvoice"
version = "0.1.0"
[voice]
system_addendum = "Custom guidance for tests."
"#,
)
.unwrap();
let loader = VoiceLoader::with_extra_dirs(vec![dir.path().to_path_buf()]);
let pkg = loader.load("myvoice").expect("custom voice must load");
assert_eq!(pkg.meta.name, "myvoice");
assert!(pkg.voice.system_addendum.contains("Custom guidance"));
}
#[test]
fn custom_dir_takes_priority_over_bundled() {
let dir = tempfile::tempdir().expect("tempdir");
let voice_dir = dir.path().join("duetto");
std::fs::create_dir_all(&voice_dir).unwrap();
std::fs::write(
voice_dir.join("voice.toml"),
r#"
[meta]
name = "duetto"
version = "99.0.0"
[voice]
system_addendum = "Overridden for test."
"#,
)
.unwrap();
let loader = VoiceLoader::with_extra_dirs(vec![dir.path().to_path_buf()]);
let pkg = loader.load("duetto").expect("custom duetto must load");
assert_eq!(
pkg.meta.version, "99.0.0",
"custom version must take priority"
);
assert!(
pkg.voice.system_addendum.contains("Overridden"),
"custom addendum must take priority"
);
}
#[test]
fn list_includes_bundled_duetto() {
let loader = VoiceLoader::new();
let names = loader.list();
assert!(
names.contains(&"duetto".to_string()),
"list must include bundled duetto; got: {names:?}"
);
}
#[test]
fn list_includes_extra_dir_voices() {
let dir = tempfile::tempdir().expect("tempdir");
for name in ["alpha", "beta"] {
let vd = dir.path().join(name);
std::fs::create_dir_all(&vd).unwrap();
std::fs::write(
vd.join("voice.toml"),
format!("[meta]\nname = \"{name}\"\n"),
)
.unwrap();
}
let loader = VoiceLoader::with_extra_dirs(vec![dir.path().to_path_buf()]);
let names = loader.list();
assert!(names.contains(&"alpha".to_string()));
assert!(names.contains(&"beta".to_string()));
assert!(names.contains(&"duetto".to_string())); }