use std::collections::HashMap;
use super::*;
#[test]
fn render_replaces_variables() {
let template = "Hello {{name}}, welcome to {{project}}!";
let vars = HashMap::from([("name", "Alice"), ("project", "zig")]);
assert_eq!(render(template, &vars), "Hello Alice, welcome to zig!");
}
#[test]
fn render_leaves_unknown_variables() {
let template = "Hello {{name}}, your id is {{id}}";
let vars = HashMap::from([("name", "Bob")]);
assert_eq!(render(template, &vars), "Hello Bob, your id is {{id}}");
}
#[test]
fn render_empty_vars() {
let template = "No variables here";
let vars = HashMap::new();
assert_eq!(render(template, &vars), "No variables here");
}
#[test]
fn render_multiple_occurrences() {
let template = "{{x}} + {{x}} = 2 * {{x}}";
let vars = HashMap::from([("x", "5")]);
assert_eq!(render(template, &vars), "5 + 5 = 2 * 5");
}
#[test]
fn render_multiline_template() {
let template = "## Reference\n\n{{content}}\n\n## End";
let vars = HashMap::from([("content", "line1\nline2\nline3")]);
assert_eq!(
render(template, &vars),
"## Reference\n\nline1\nline2\nline3\n\n## End"
);
}
#[test]
fn templates_are_embedded() {
assert!(!templates::create().is_empty());
assert!(!templates::update().is_empty());
assert!(!templates::config_sidecar().is_empty());
assert!(templates::create().contains("{{zwf_format_spec}}"));
assert!(templates::update().contains("{{zwf_format_spec}}"));
assert!(templates::config_sidecar().contains(".zwf"));
}
#[test]
fn templates_have_front_matter_stripped() {
let create = templates::create();
assert!(
!create.starts_with("---"),
"create prompt still begins with front matter delimiter"
);
assert!(
!create.contains("name: create"),
"create prompt still contains front matter `name` field"
);
assert!(
!create.contains("references:"),
"create prompt still contains front matter `references` field"
);
let update = templates::update();
assert!(
!update.starts_with("---"),
"update prompt still begins with front matter delimiter"
);
assert!(
!update.contains("name: update"),
"update prompt still contains front matter `name` field"
);
let sidecar = templates::config_sidecar();
assert!(
!sidecar.starts_with("---"),
"config sidecar still begins with front matter delimiter"
);
assert!(
!sidecar.contains("name: config-sidecar"),
"config sidecar still contains front matter `name` field"
);
}
#[test]
fn strip_front_matter_removes_block() {
let input = "---\nname: foo\nversion: \"1.0\"\n---\n\nbody line one\nbody line two\n";
assert_eq!(strip_front_matter(input), "body line one\nbody line two\n");
}
#[test]
fn strip_front_matter_without_trailing_blank_line() {
let input = "---\nname: foo\n---\nbody\n";
assert_eq!(strip_front_matter(input), "body\n");
}
#[test]
fn strip_front_matter_no_front_matter_passthrough() {
let input = "no front matter here\n---\nnot a delimiter\n";
assert_eq!(strip_front_matter(input), input);
}
#[test]
fn strip_front_matter_does_not_match_mid_file_delimiters() {
let input = "# heading\n\n---\n\nbody\n";
assert_eq!(strip_front_matter(input), input);
}
#[test]
fn strip_front_matter_handles_unterminated_block() {
let input = "---\nname: foo\nversion: 1.0\nbody without close\n";
assert_eq!(strip_front_matter(input), input);
}
#[test]
fn strip_front_matter_handles_crlf_line_endings() {
let input =
"---\r\nname: foo\r\nversion: \"1.0\"\r\n---\r\n\r\nbody line one\r\nbody line two\r\n";
assert_eq!(
strip_front_matter(input),
"body line one\r\nbody line two\r\n"
);
}
#[test]
fn strip_front_matter_crlf_without_trailing_blank_line() {
let input = "---\r\nname: foo\r\n---\r\nbody\r\n";
assert_eq!(strip_front_matter(input), "body\r\n");
}
#[test]
fn example_templates_are_embedded() {
let examples = all_examples();
assert_eq!(examples.len(), 7);
for (filename, content) in &examples {
assert!(
!content.is_empty(),
"example {filename} should not be empty"
);
assert!(
content.contains("[workflow]"),
"example {filename} should contain [workflow] section"
);
assert!(
filename.ends_with(".zwf"),
"example {filename} should use the .zwf extension"
);
}
}
#[test]
fn example_for_pattern_returns_some_for_all_known() {
let patterns = [
"sequential",
"fan-out",
"generator-critic",
"coordinator-dispatcher",
"hierarchical-decomposition",
"human-in-the-loop",
"inter-agent-communication",
];
for p in &patterns {
assert!(
example_for_pattern(p).is_some(),
"example_for_pattern('{p}') should return Some"
);
}
}
#[test]
fn example_for_pattern_returns_none_for_unknown() {
assert!(example_for_pattern("nonexistent").is_none());
assert!(example_for_pattern("").is_none());
}
#[test]
fn create_prompt_renders_with_sidecar() {
let vars = HashMap::from([
("zwf_format_spec", templates::config_sidecar()),
("zag_help", "(zag help placeholder)"),
("zag_orch", "(zag orch placeholder)"),
("examples_reference", "(examples placeholder)"),
]);
let rendered = render(templates::create(), &vars);
assert!(!rendered.contains("{{zwf_format_spec}}"));
assert!(!rendered.contains("{{zag_help}}"));
assert!(!rendered.contains("{{zag_orch}}"));
assert!(!rendered.contains("{{examples_reference}}"));
assert!(rendered.contains(".zwf Workflow Format Specification"));
assert!(rendered.contains("(zag help placeholder)"));
assert!(rendered.contains("(examples placeholder)"));
}
#[test]
fn examples_reference_block_lists_all_patterns() {
let block = examples_reference_block();
assert!(block.contains("~/.zig/examples/sequential.zwf"));
assert!(block.contains("~/.zig/examples/fan-out.zwf"));
assert!(block.contains("~/.zig/examples/generator-critic.zwf"));
assert!(block.contains("~/.zig/examples/coordinator-dispatcher.zwf"));
assert!(block.contains("~/.zig/examples/hierarchical-decomposition.zwf"));
assert!(block.contains("~/.zig/examples/human-in-the-loop.zwf"));
assert!(block.contains("~/.zig/examples/inter-agent-communication.zwf"));
}