use super::*;
use proptest::prelude::*;
fn valid_project_name() -> impl Strategy<Value = String> {
"[a-z][a-z0-9-]{0,63}".prop_map(|s| s.to_string())
}
fn valid_author() -> impl Strategy<Value = String> {
"[A-Za-z ]{3,30}".prop_map(|s| s.to_string())
}
proptest! {
#[test]
fn prop_template_render_deterministic(
name in valid_project_name(),
author in valid_author()
) {
let template = Template::from_string("{{name}} by {{author}}").unwrap();
let mut vars = HashMap::new();
vars.insert("name".into(), name.clone());
vars.insert("author".into(), author.clone());
let result1 = template.render(&vars).unwrap();
let result2 = template.render(&vars).unwrap();
prop_assert_eq!(result1, result2);
}
#[test]
fn prop_template_variables_substituted(
name in valid_project_name(),
author in valid_author()
) {
let template = Template::from_string("Project: {{name}}, Author: {{author}}").unwrap();
let mut vars = HashMap::new();
vars.insert("name".into(), name.clone());
vars.insert("author".into(), author.clone());
let result = template.render(&vars).unwrap();
prop_assert!(!result.contains("{{name}}"));
prop_assert!(!result.contains("{{author}}"));
prop_assert!(result.contains(&name));
prop_assert!(result.contains(&author));
}
#[test]
fn prop_pforge_yaml_valid(
name in valid_project_name(),
author in valid_author()
) {
let template = Template::pforge_yaml();
let mut vars = HashMap::new();
vars.insert("project_name".into(), name.clone());
vars.insert("author".into(), author);
vars.insert("description".into(), "Test project".into());
let rendered = template.render(&vars).unwrap();
let parsed: serde_yaml_ng::Value = serde_yaml_ng::from_str(&rendered).unwrap();
prop_assert!(parsed.is_mapping());
prop_assert!(parsed.get("forge").is_some());
prop_assert_eq!(parsed["forge"]["name"].as_str(), Some(name.as_str()));
}
#[test]
fn prop_cargo_toml_contains_name(
name in valid_project_name(),
author in valid_author()
) {
let template = Template::cargo_toml();
let mut vars = HashMap::new();
vars.insert("project_name".into(), name.clone());
vars.insert("author".into(), author);
let rendered = template.render(&vars).unwrap();
let package_name = format!("name = \"{}\"", name);
prop_assert!(rendered.contains(&package_name));
prop_assert!(rendered.contains("[package]"));
prop_assert!(rendered.contains("[dependencies]"));
}
#[test]
fn prop_handler_compiles_syntax(
handler_name in "[A-Z][a-zA-Z]{3,20}"
) {
let template = Template::handler_rs();
let mut vars = HashMap::new();
vars.insert("handler_name".into(), handler_name.clone());
vars.insert("handler_description".into(), "Test handler".into());
let rendered = template.render(&vars).unwrap();
let input_struct = format!("pub struct {}Input", handler_name);
let output_struct = format!("pub struct {}Output", handler_name);
prop_assert!(rendered.contains(&input_struct));
prop_assert!(rendered.contains(&output_struct));
prop_assert!(rendered.contains("pub async fn execute"));
prop_assert!(rendered.contains("#[cfg(test)]"));
prop_assert!(rendered.contains("#[tokio::test]"));
}
#[test]
fn prop_template_never_panics(content in ".*", key in "[a-z]{1,10}", value in ".*") {
let template = Template::from_string(content).unwrap();
let mut vars = HashMap::new();
vars.insert(key, value);
let _result = template.render(&vars);
}
#[test]
fn prop_registry_idempotent(name in valid_project_name()) {
let mut registry = TemplateRegistry::new();
let template1 = Template::from_string("content").unwrap();
let template2 = Template::from_string("content").unwrap();
registry.register(name.clone(), template1);
registry.register(name.clone(), template2);
let retrieved = registry.get(&name);
prop_assert!(retrieved.is_ok());
}
#[test]
fn prop_wasm_cargo_has_cdylib(name in valid_project_name(), author in valid_author()) {
let template = Template::wasm_cargo_toml();
let mut vars = HashMap::new();
vars.insert("project_name".into(), name);
vars.insert("author".into(), author);
let rendered = template.render(&vars).unwrap();
prop_assert!(rendered.contains("cdylib"));
prop_assert!(rendered.contains("wasm-bindgen"));
}
#[test]
fn prop_wasm_makefile_has_targets(name in valid_project_name()) {
let template = Template::wasm_makefile();
let mut vars = HashMap::new();
vars.insert("project_name".into(), name);
let rendered = template.render(&vars).unwrap();
prop_assert!(rendered.contains("wasm-full"));
prop_assert!(rendered.contains("quality"));
prop_assert!(rendered.contains("wasm32-unknown-unknown"));
}
#[test]
fn prop_wasm_lib_valid_rust(name in valid_project_name()) {
let template = Template::wasm_lib_rs();
let mut vars = HashMap::new();
vars.insert("project_name".into(), name);
vars.insert("description".into(), "Test".into());
let rendered = template.render(&vars).unwrap();
prop_assert!(rendered.contains("#[wasm_bindgen]"));
prop_assert!(rendered.contains("use wasm_bindgen::prelude::*;"));
prop_assert!(rendered.contains("pub fn process"));
}
}