prosaic_project/
template.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct TemplateFile {
7 pub key: String,
8 #[serde(default)]
9 pub description: String,
10 #[serde(default)]
11 pub slots_required: Vec<String>,
12 #[serde(default)]
13 pub slots_optional: Vec<String>,
14 pub variants: Vec<Variant>,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Variant {
19 #[serde(default = "default_salience")]
21 pub salience: String,
22 #[serde(default)]
24 pub language: Option<String>,
25 #[serde(default)]
27 pub style: Option<String>,
28 #[serde(default)]
29 pub description: String,
30 pub body: String,
31}
32
33fn default_salience() -> String {
34 "medium".to_string()
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn parse_minimal_template() {
43 let toml_str = r#"
44 key = "code.modified"
45 variants = [
46 { body = "{name|refer} was modified" },
47 ]
48 "#;
49 let t: TemplateFile = toml::from_str(toml_str).unwrap();
50 assert_eq!(t.key, "code.modified");
51 assert_eq!(t.variants.len(), 1);
52 assert_eq!(t.variants[0].salience, "medium");
53 assert_eq!(t.variants[0].body, "{name|refer} was modified");
54 assert!(t.variants[0].language.is_none());
55 assert!(t.variants[0].style.is_none());
56 }
57
58 #[test]
59 fn parse_multi_variant_with_salience() {
60 let toml_str = r#"
61 key = "code.modified"
62 description = "Render a 'class X was modified' event."
63 slots_required = ["name"]
64 slots_optional = ["consumer_count"]
65
66 [[variants]]
67 salience = "low"
68 body = "{name|refer} was modified"
69
70 [[variants]]
71 salience = "medium"
72 body = """{name|refer} was modified, affecting {consumer_count}"""
73
74 [[variants]]
75 salience = "high"
76 language = "en"
77 style = "executive"
78 body = "{name|refer} has been substantially modified"
79 "#;
80 let t: TemplateFile = toml::from_str(toml_str).unwrap();
81 assert_eq!(t.variants.len(), 3);
82 assert_eq!(t.variants[0].salience, "low");
83 assert_eq!(t.variants[1].salience, "medium");
84 assert_eq!(t.variants[2].salience, "high");
85 assert_eq!(t.variants[2].language.as_deref(), Some("en"));
86 assert_eq!(t.variants[2].style.as_deref(), Some("executive"));
87 assert_eq!(t.slots_required, vec!["name"]);
88 assert_eq!(t.slots_optional, vec!["consumer_count"]);
89 }
90
91 #[test]
92 fn parse_multi_language_variants() {
93 let toml_str = r#"
94 key = "code.modified"
95
96 [[variants]]
97 salience = "medium"
98 language = "en"
99 body = "{name} was modified"
100
101 [[variants]]
102 salience = "medium"
103 language = "es"
104 body = "{name} fue modificado"
105 "#;
106 let t: TemplateFile = toml::from_str(toml_str).unwrap();
107 assert_eq!(t.variants.len(), 2);
108 assert_eq!(t.variants[0].language.as_deref(), Some("en"));
109 assert_eq!(t.variants[1].language.as_deref(), Some("es"));
110 }
111
112 #[test]
113 fn parse_style_variants() {
114 let toml_str = r#"
115 key = "code.modified"
116
117 [[variants]]
118 salience = "medium"
119 style = "executive"
120 body = "{name} changed"
121 "#;
122 let t: TemplateFile = toml::from_str(toml_str).unwrap();
123 assert_eq!(t.variants[0].style.as_deref(), Some("executive"));
124 }
125
126 #[test]
127 fn missing_key_errors() {
128 let toml_str = r#"
129 variants = [{ body = "x" }]
130 "#;
131 let res = toml::from_str::<TemplateFile>(toml_str);
132 assert!(res.is_err(), "expected error for missing `key` field");
133 }
134
135 #[test]
136 fn missing_variant_body_errors() {
137 let toml_str = r#"
138 key = "x"
139 [[variants]]
140 salience = "medium"
141 "#;
142 let res = toml::from_str::<TemplateFile>(toml_str);
143 assert!(
144 res.is_err(),
145 "expected error for missing variant `body` field"
146 );
147 }
148
149 #[test]
150 fn round_trip_serialize() {
151 let original: TemplateFile = toml::from_str(
152 r#"
153 key = "code.added"
154 description = "Add event."
155 variants = [
156 { salience = "medium", body = "{name|refer} was added" },
157 ]
158 "#,
159 )
160 .unwrap();
161 let serialized = toml::to_string(&original).unwrap();
162 let reparsed: TemplateFile = toml::from_str(&serialized).unwrap();
163 assert_eq!(reparsed.key, "code.added");
164 assert_eq!(reparsed.variants.len(), 1);
165 assert_eq!(reparsed.variants[0].body, "{name|refer} was added");
166 }
167}