use crate::manifest::{DetailedDependency, Manifest, ResourceDependency};
use anyhow::Result;
use tempfile::tempdir;
fn make_detailed_dep(source: &str, path: &str, version: &str) -> ResourceDependency {
ResourceDependency::Detailed(Box::new(DetailedDependency {
source: Some(source.to_string()),
path: path.to_string(),
version: Some(version.to_string()),
branch: None,
rev: None,
command: None,
args: None,
target: None,
filename: None,
dependencies: None,
tool: Some("claude-code".to_string()),
flatten: None,
install: None,
template_vars: Some(serde_json::Value::Object(serde_json::Map::new())),
}))
}
#[test]
fn test_validate_patches_success() -> Result<()> {
let temp = tempdir()?;
let manifest_path = temp.path().join("agpm.toml");
let toml_content = r#"
[sources]
community = "https://github.com/example/agpm-community.git"
[agents]
test-agent = { source = "community", path = "agents/test.md", version = "v1.0.0" }
[patch.agents.test-agent]
model = "claude-3-haiku"
temperature = "0.8"
"#;
std::fs::write(&manifest_path, toml_content)?;
let manifest = Manifest::load(&manifest_path)?;
manifest.validate()?;
Ok(())
}
#[test]
fn test_validate_patches_unknown_dependency() -> Result<()> {
let temp = tempdir()?;
let manifest_path = temp.path().join("agpm.toml");
let toml_content = r#"
[sources]
community = "https://github.com/example/agpm-community.git"
[agents]
test-agent = { source = "community", path = "agents/test.md", version = "v1.0.0" }
[patch.agents.non-existent]
model = "claude-3-haiku"
"#;
std::fs::write(&manifest_path, toml_content)?;
let result = Manifest::load(&manifest_path);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("Patch references unknown"));
Ok(())
}
#[test]
fn test_validate_sources() -> Result<()> {
let mut manifest = Manifest::new();
manifest.add_dependency(
"local".to_string(),
ResourceDependency::Simple("../local/agent.md".to_string()),
true,
);
manifest.validate()?;
manifest.add_dependency(
"remote".to_string(),
ResourceDependency::Detailed(Box::new(DetailedDependency {
source: Some("undefined".to_string()),
path: "agents/test.md".to_string(),
version: Some("v1.0.0".to_string()),
branch: None,
rev: None,
command: None,
args: None,
target: None,
filename: None,
dependencies: None,
tool: Some("claude-code".to_string()),
flatten: None,
install: None,
template_vars: Some(serde_json::Value::Object(serde_json::Map::new())),
})),
true,
);
assert!(manifest.validate().is_err());
manifest.add_source("undefined".to_string(), "https://github.com/test/repo.git".to_string());
manifest.validate()?;
Ok(())
}
#[test]
fn test_validate_version_constraints() -> Result<()> {
let mut manifest = Manifest::new();
manifest.add_source("test".to_string(), "https://github.com/test/repo.git".to_string());
manifest.add_dependency(
"no-version".to_string(),
ResourceDependency::Detailed(Box::new(DetailedDependency {
source: Some("test".to_string()),
path: "agents/test.md".to_string(),
version: None,
branch: None,
rev: None,
command: None,
args: None,
target: None,
filename: None,
dependencies: None,
tool: Some("claude-code".to_string()),
flatten: None,
install: None,
template_vars: Some(serde_json::Value::Object(serde_json::Map::new())),
})),
true,
);
manifest.validate()?;
manifest.agents.remove("no-version");
manifest.add_dependency(
"with-version".to_string(),
ResourceDependency::Detailed(Box::new(DetailedDependency {
source: Some("test".to_string()),
path: "agents/test.md".to_string(),
version: Some("v1.0.0".to_string()),
branch: None,
rev: None,
command: None,
args: None,
target: None,
filename: None,
dependencies: None,
tool: Some("claude-code".to_string()),
flatten: None,
install: None,
template_vars: Some(serde_json::Value::Object(serde_json::Map::new())),
})),
true,
);
manifest.validate()?;
Ok(())
}
#[test]
fn test_same_name_different_sections_allowed() -> Result<()> {
let mut manifest = Manifest::new();
manifest.add_source("test".to_string(), "https://github.com/test/repo.git".to_string());
manifest
.agents
.insert("example".to_string(), make_detailed_dep("test", "agents/example.md", "v1.0.0"));
manifest
.commands
.insert("example".to_string(), make_detailed_dep("test", "commands/example.md", "v2.0.0"));
manifest.validate()?;
Ok(())
}
#[test]
fn test_case_conflict_same_section() {
let mut manifest = Manifest::new();
manifest.add_source("test".to_string(), "https://github.com/test/repo.git".to_string());
manifest
.agents
.insert("Helper".to_string(), make_detailed_dep("test", "agents/helper1.md", "v1.0.0"));
manifest
.agents
.insert("helper".to_string(), make_detailed_dep("test", "agents/helper2.md", "v1.0.0"));
let result = manifest.validate();
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Case conflict"));
assert!(err_msg.contains("[agents]")); }
#[test]
fn test_case_different_sections_allowed() -> Result<()> {
let mut manifest = Manifest::new();
manifest.add_source("test".to_string(), "https://github.com/test/repo.git".to_string());
manifest
.agents
.insert("Helper".to_string(), make_detailed_dep("test", "agents/helper.md", "v1.0.0"));
manifest
.commands
.insert("helper".to_string(), make_detailed_dep("test", "commands/helper.md", "v1.0.0"));
manifest.validate()?;
Ok(())
}