use mecha10_cli::services::template::*;
use tempfile::TempDir;
#[test]
fn test_create_vars() {
let service = TemplateService::new();
let mut vars = service.create_vars();
vars.add_name("camera_driver");
let map = vars.to_hashmap();
assert_eq!(map.get("name"), Some(&"camera_driver"));
assert_eq!(map.get("PascalName"), Some(&"CameraDriver"));
assert_eq!(map.get("UPPER_NAME"), Some(&"CAMERA_DRIVER"));
}
#[test]
fn test_render_string() {
let service = TemplateService::new();
let template = "Hello {{name}}, your type is {{type}}!";
let mut vars = HashMap::new();
vars.insert("name", "World");
vars.insert("type", "Robot");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Hello World, your type is Robot!");
}
#[tokio::test]
async fn test_generate_node_creates_directory_structure() -> Result<()> {
let temp = TempDir::new()?;
let _service = TemplateService::new();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("nodes")).await?;
tokio::fs::write(
template_dir.join("nodes").join("sensor.rs.template"),
"// Node: {{name}}\n// Type: {{PascalName}}",
)
.await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
service
.generate_node("temperature_sensor", "sensor", &output_dir)
.await?;
let generated_file = output_dir.join("temperature_sensor").join("src").join("lib.rs");
assert!(generated_file.exists());
let content = tokio::fs::read_to_string(generated_file).await?;
assert!(content.contains("// Node: temperature_sensor"));
assert!(content.contains("// Type: TemperatureSensor"));
Ok(())
}
#[tokio::test]
async fn test_generate_driver_creates_directory_structure() -> Result<()> {
let temp = TempDir::new()?;
let _service = TemplateService::new();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("drivers")).await?;
tokio::fs::write(
template_dir.join("drivers").join("camera.rs.template"),
"// Driver: {{name}}\n// Type: {{PascalName}}",
)
.await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
service.generate_driver("webcam_driver", "camera", &output_dir).await?;
let generated_file = output_dir.join("webcam_driver").join("src").join("lib.rs");
assert!(generated_file.exists());
let content = tokio::fs::read_to_string(generated_file).await?;
assert!(content.contains("// Driver: webcam_driver"));
assert!(content.contains("// Type: WebcamDriver"));
Ok(())
}
#[test]
fn test_new() {
let service = TemplateService::new();
let vars = service.create_vars();
assert!(vars.to_hashmap().is_empty());
}
#[test]
fn test_default() {
let service = TemplateService::default();
let vars = service.create_vars();
assert!(vars.to_hashmap().is_empty());
}
#[test]
fn test_with_template_dir() {
let temp = TempDir::new().unwrap();
let template_dir = temp.path().join("custom_templates");
std::fs::create_dir(&template_dir).unwrap();
let service = TemplateService::with_template_dir(&template_dir);
let vars = service.create_vars();
assert!(vars.to_hashmap().is_empty());
}
#[test]
fn test_render_string_multiple_variables() {
let service = TemplateService::new();
let template = "{{greeting}} {{name}}, your {{item}} is ready!";
let mut vars = HashMap::new();
vars.insert("greeting", "Hello");
vars.insert("name", "Alice");
vars.insert("item", "robot");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Hello Alice, your robot is ready!");
}
#[test]
fn test_render_string_no_variables() {
let service = TemplateService::new();
let template = "Static content with no placeholders";
let vars = HashMap::new();
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Static content with no placeholders");
}
#[test]
fn test_render_string_empty_template() {
let service = TemplateService::new();
let vars = HashMap::new();
let result = service.render_string("", &vars).unwrap();
assert_eq!(result, "");
}
#[test]
fn test_render_string_duplicate_placeholders() {
let service = TemplateService::new();
let template = "{{name}} and {{name}} are the same";
let mut vars = HashMap::new();
vars.insert("name", "Bob");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Bob and Bob are the same");
}
#[tokio::test]
async fn test_generate_type() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("types")).await?;
tokio::fs::write(
template_dir.join("types").join("custom.rs.template"),
"pub struct {{PascalName}} {{\n // {{name}}\n}}",
)
.await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
service.generate_type("sensor_data", &output_dir).await?;
let generated_file = output_dir.join("sensor_data.rs");
assert!(generated_file.exists());
let content = tokio::fs::read_to_string(generated_file).await?;
assert!(content.contains("pub struct SensorData"));
assert!(content.contains("// sensor_data"));
Ok(())
}
#[tokio::test]
async fn test_generate_cargo_toml() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("cargo")).await?;
tokio::fs::write(
template_dir.join("cargo").join("node.toml.template"),
"[package]\nname = \"{{name}}\"\nversion = \"0.1.0\"",
)
.await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
tokio::fs::create_dir(&output_dir).await?;
service.generate_cargo_toml("test_node", "node", &output_dir).await?;
let generated_file = output_dir.join("Cargo.toml");
assert!(generated_file.exists());
let content = tokio::fs::read_to_string(generated_file).await?;
assert!(content.contains("name = \"test_node\""));
assert!(content.contains("version = \"0.1.0\""));
Ok(())
}
#[tokio::test]
async fn test_generate_node_missing_template() {
let temp = TempDir::new().unwrap();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(&template_dir).await.unwrap();
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
let result = service.generate_node("test_node", "nonexistent", &output_dir).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Template not found"));
}
#[tokio::test]
async fn test_generate_driver_missing_template() {
let temp = TempDir::new().unwrap();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(&template_dir).await.unwrap();
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
let result = service.generate_driver("test_driver", "nonexistent", &output_dir).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Template not found"));
}
#[tokio::test]
async fn test_generate_type_missing_template() {
let temp = TempDir::new().unwrap();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(&template_dir).await.unwrap();
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
let result = service.generate_type("test_type", &output_dir).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Template not found"));
}
#[tokio::test]
async fn test_generate_cargo_toml_missing_template() {
let temp = TempDir::new().unwrap();
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(&template_dir).await.unwrap();
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
let result = service.generate_cargo_toml("test", "nonexistent", &output_dir).await;
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Template not found"));
}
#[tokio::test]
async fn test_generate_node_creates_parent_directories() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("nodes")).await?;
tokio::fs::write(template_dir.join("nodes").join("sensor.rs.template"), "// {{name}}").await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output").join("nested").join("path");
service.generate_node("test_node", "sensor", &output_dir).await?;
let generated_file = output_dir.join("test_node").join("src").join("lib.rs");
assert!(generated_file.exists());
Ok(())
}
#[tokio::test]
async fn test_generate_driver_creates_parent_directories() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("drivers")).await?;
tokio::fs::write(template_dir.join("drivers").join("motor.rs.template"), "// {{name}}").await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output").join("nested").join("path");
service.generate_driver("test_driver", "motor", &output_dir).await?;
let generated_file = output_dir.join("test_driver").join("src").join("lib.rs");
assert!(generated_file.exists());
Ok(())
}
#[tokio::test]
async fn test_generate_type_creates_parent_directories() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("types")).await?;
tokio::fs::write(template_dir.join("types").join("custom.rs.template"), "// {{name}}").await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output").join("nested").join("path");
tokio::fs::create_dir_all(&output_dir).await?;
service.generate_type("test_type", &output_dir).await?;
let generated_file = output_dir.join("test_type.rs");
assert!(generated_file.exists());
Ok(())
}
#[test]
fn test_render_string_with_special_characters() {
let service = TemplateService::new();
let template = "{{name}} has $pecial ch@rs!";
let mut vars = HashMap::new();
vars.insert("name", "Test");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Test has $pecial ch@rs!");
}
#[test]
fn test_render_string_with_unicode() {
let service = TemplateService::new();
let template = "Hello {{name}}! 你好 {{greeting}}";
let mut vars = HashMap::new();
vars.insert("name", "世界");
vars.insert("greeting", "🤖");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Hello 世界! 你好 🤖");
}
#[tokio::test]
async fn test_generate_cargo_toml_overwrites_existing() -> Result<()> {
let temp = TempDir::new()?;
let template_dir = temp.path().join("templates");
tokio::fs::create_dir_all(template_dir.join("cargo")).await?;
tokio::fs::write(
template_dir.join("cargo").join("driver.toml.template"),
"[package]\nname = \"{{name}}\"",
)
.await?;
let service = TemplateService::with_template_dir(template_dir);
let output_dir = temp.path().join("output");
tokio::fs::create_dir(&output_dir).await?;
tokio::fs::write(output_dir.join("Cargo.toml"), "old content").await?;
service.generate_cargo_toml("new_name", "driver", &output_dir).await?;
let content = tokio::fs::read_to_string(output_dir.join("Cargo.toml")).await?;
assert!(content.contains("name = \"new_name\""));
assert!(!content.contains("old content"));
Ok(())
}
#[test]
fn test_render_string_preserves_unmatched_braces() {
let service = TemplateService::new();
let template = "{{name}} has {unmatched} and {{type}}";
let mut vars = HashMap::new();
vars.insert("name", "Test");
vars.insert("type", "Robot");
let result = service.render_string(template, &vars).unwrap();
assert_eq!(result, "Test has {unmatched} and Robot");
}