sal/text/tests/template_tests.rs
Mahmoud-Emad a7a7353aa1
Some checks failed
Rhai Tests / Run Rhai Tests (push) Has been cancelled
feat: Add sal-text crate
- Add a new crate `sal-text` for text manipulation utilities.
- Integrate `sal-text` into the main `sal` crate.
- Remove the previous `text` module from `sal`.  This improves
  organization and allows for independent development of the
  `sal-text` library.
2025-06-19 14:43:27 +03:00

298 lines
10 KiB
Rust

//! Unit tests for template functionality
//!
//! These tests validate the TemplateBuilder including:
//! - Template loading from files
//! - Variable substitution (string, int, float, bool, array)
//! - Template rendering to string and file
//! - Error handling for missing variables and invalid templates
//! - Complex template scenarios with loops and conditionals
use sal_text::TemplateBuilder;
use std::collections::HashMap;
use std::fs;
use tempfile::NamedTempFile;
#[test]
fn test_template_builder_basic_string_variable() {
// Create a temporary template file
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "Hello {{name}}!";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("name", "World")
.render()
.expect("Failed to render template");
assert_eq!(result, "Hello World!");
}
#[test]
fn test_template_builder_multiple_variables() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "{{greeting}} {{name}}, you have {{count}} messages.";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("greeting", "Hello")
.add_var("name", "Alice")
.add_var("count", 5)
.render()
.expect("Failed to render template");
assert_eq!(result, "Hello Alice, you have 5 messages.");
}
#[test]
fn test_template_builder_different_types() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "String: {{text}}, Int: {{number}}, Float: {{decimal}}, Bool: {{flag}}";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("text", "hello")
.add_var("number", 42)
.add_var("decimal", 3.14)
.add_var("flag", true)
.render()
.expect("Failed to render template");
assert_eq!(result, "String: hello, Int: 42, Float: 3.14, Bool: true");
}
#[test]
fn test_template_builder_array_variable() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "Items: {% for item in items %}{{item}}{% if not loop.last %}, {% endif %}{% endfor %}";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let items = vec!["apple", "banana", "cherry"];
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("items", items)
.render()
.expect("Failed to render template");
assert_eq!(result, "Items: apple, banana, cherry");
}
#[test]
fn test_template_builder_add_vars_hashmap() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "{{title}}: {{description}}";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let mut vars = HashMap::new();
vars.insert("title".to_string(), "Report".to_string());
vars.insert("description".to_string(), "Monthly summary".to_string());
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_vars(vars)
.render()
.expect("Failed to render template");
assert_eq!(result, "Report: Monthly summary");
}
#[test]
fn test_template_builder_render_to_file() {
// Create template file
let mut template_file = NamedTempFile::new().expect("Failed to create template file");
let template_content = "Hello {{name}}, today is {{day}}.";
fs::write(template_file.path(), template_content).expect("Failed to write template");
// Create output file
let output_file = NamedTempFile::new().expect("Failed to create output file");
TemplateBuilder::open(template_file.path())
.expect("Failed to open template")
.add_var("name", "Bob")
.add_var("day", "Monday")
.render_to_file(output_file.path())
.expect("Failed to render to file");
let result = fs::read_to_string(output_file.path()).expect("Failed to read output file");
assert_eq!(result, "Hello Bob, today is Monday.");
}
#[test]
fn test_template_builder_conditional() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "{% if show_message %}Message: {{message}}{% else %}No message{% endif %}";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
// Test with condition true
let result_true = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("show_message", true)
.add_var("message", "Hello World")
.render()
.expect("Failed to render template");
assert_eq!(result_true, "Message: Hello World");
// Test with condition false
let result_false = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("show_message", false)
.add_var("message", "Hello World")
.render()
.expect("Failed to render template");
assert_eq!(result_false, "No message");
}
#[test]
fn test_template_builder_loop_with_index() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "{% for item in items %}{{loop.index}}: {{item}}\n{% endfor %}";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let items = vec!["first", "second", "third"];
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("items", items)
.render()
.expect("Failed to render template");
assert_eq!(result, "1: first\n2: second\n3: third\n");
}
#[test]
fn test_template_builder_nested_variables() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "User: {{user.name}} ({{user.email}})";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let mut user = HashMap::new();
user.insert("name".to_string(), "John Doe".to_string());
user.insert("email".to_string(), "john@example.com".to_string());
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("user", user)
.render()
.expect("Failed to render template");
assert_eq!(result, "User: John Doe (john@example.com)");
}
#[test]
fn test_template_builder_missing_variable_error() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "Hello {{missing_var}}!";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.render();
assert!(result.is_err());
}
#[test]
fn test_template_builder_invalid_template_syntax() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "Hello {{unclosed_var!";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.render();
assert!(result.is_err());
}
#[test]
fn test_template_builder_nonexistent_file() {
let result = TemplateBuilder::open("/nonexistent/template.txt");
assert!(result.is_err());
}
#[test]
fn test_template_builder_empty_template() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
fs::write(temp_file.path(), "").expect("Failed to write empty template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.render()
.expect("Failed to render empty template");
assert_eq!(result, "");
}
#[test]
fn test_template_builder_template_with_no_variables() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = "This is a static template with no variables.";
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.render()
.expect("Failed to render template");
assert_eq!(result, template_content);
}
#[test]
fn test_template_builder_complex_report() {
let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
let template_content = r#"
# {{report_title}}
Generated on: {{date}}
## Summary
Total items: {{total_items}}
Status: {{status}}
## Items
{% for item in items %}
- {{item.name}}: {{item.value}}{% if item.important %} (IMPORTANT){% endif %}
{% endfor %}
## Footer
{% if show_footer %}
Report generated by {{generator}}
{% endif %}
"#;
fs::write(temp_file.path(), template_content).expect("Failed to write template");
let mut item1 = HashMap::new();
item1.insert("name".to_string(), "Item 1".to_string());
item1.insert("value".to_string(), "100".to_string());
item1.insert("important".to_string(), true.to_string());
let mut item2 = HashMap::new();
item2.insert("name".to_string(), "Item 2".to_string());
item2.insert("value".to_string(), "200".to_string());
item2.insert("important".to_string(), false.to_string());
let items = vec![item1, item2];
let result = TemplateBuilder::open(temp_file.path())
.expect("Failed to open template")
.add_var("report_title", "Monthly Report")
.add_var("date", "2023-12-01")
.add_var("total_items", 2)
.add_var("status", "Complete")
.add_var("items", items)
.add_var("show_footer", true)
.add_var("generator", "SAL Text")
.render()
.expect("Failed to render template");
assert!(result.contains("# Monthly Report"));
assert!(result.contains("Generated on: 2023-12-01"));
assert!(result.contains("Total items: 2"));
assert!(result.contains("- Item 1: 100"));
assert!(result.contains("- Item 2: 200"));
assert!(result.contains("Report generated by SAL Text"));
}