summaryrefslogtreecommitdiff
path: root/deepcrow/tests
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2026-08-19 13:05:01 -0700
committerMike Buland <mike@xagasoft.com>2026-08-19 13:05:01 -0700
commitd1e78b4a3454984db74ebf2a302a64b985ce6de4 (patch)
treed3953cd8aad144a1be131ff3c38688f93cbccbb5 /deepcrow/tests
parent5602585e7afe431f25e68f30ac54761db2a710e5 (diff)
downloaddeepcrow-d1e78b4a3454984db74ebf2a302a64b985ce6de4.tar.gz
deepcrow-d1e78b4a3454984db74ebf2a302a64b985ce6de4.tar.bz2
deepcrow-d1e78b4a3454984db74ebf2a302a64b985ce6de4.tar.xz
deepcrow-d1e78b4a3454984db74ebf2a302a64b985ce6de4.zip
Rearranged and renamed some bits.
Diffstat (limited to '')
-rw-r--r--deepcrow/tests/basic.rs246
1 files changed, 246 insertions, 0 deletions
diff --git a/deepcrow/tests/basic.rs b/deepcrow/tests/basic.rs
new file mode 100644
index 0000000..37cc21f
--- /dev/null
+++ b/deepcrow/tests/basic.rs
@@ -0,0 +1,246 @@
1use std::collections::HashMap;
2
3use deepcrow::*;
4
5/*
6#[test]
7fn lexing() {
8 let data = r#"Leading comment: [|view "basic" something="yeup"|>Hello there <|view|] Trailing text"#;
9 let ll = Lexer::new( &data );
10 for sym in ll {
11 if let SymbolType::Error{what} = sym.symbol() {
12 println!("Error {}:{}: {:?}", sym.start().line, sym.start().column, what );
13 break;
14 } else {
15 println!("Symbol: {:?}", sym );
16 }
17 }
18}
19*/
20
21#[test]
22fn parsing() {
23 let mut ct = DeepCrow::new();
24 if let Err(e) = ct.load_static(r#"Here is a sample
25[|view "index" theme="standard"|><html><body>Hi</body></html><|view|]
26That was fun! now a placeholder: [|view "placeholder"|] and now one with an implicit [|view "simple"|>Body -> [|show content|] <- and end<|view|] aoeu
27
28[|view "person" layout="simple"|>Welcome [|show person.last_name|], [|show person.first_name|]! It's lovely to see you again.<|view|]
29
30Now with explicit outputs:
31[|view "complex"|>
32[|output "content"|>
33 Here's a [|show name|].
34<|output|]
35[|output "sidebar"|>
36 What's up world?
37<|output|]
38[|output "footer"|>
39 Same, I guess!
40<|output|]
41<|view|]"#) {
42 println!("Error: {:?}", e );
43 } else {
44 println!("It finished");
45 if let Ok(v) = ct.render(
46 "person",
47 &Context::from([
48 ("hi".to_string(),Value::String("hi".to_string())),
49 ("person".to_string(),Value::Dictionary(HashMap::from([
50 ("first_name".to_string(), Value::String("Bob".to_string())),
51 ("last_name".to_string(), Value::String("Smith".to_string())),
52 ]))),
53 ])
54 ) {
55 println!("View result: {:?}", v );
56 } else {
57 println!("Error?");
58 }
59 }
60}
61
62#[test]
63fn loops() -> Result<()> {
64 let mut ct = DeepCrow::new();
65 ct.load_static(r#"Looping code:
66[|view "index"|>We will enumerate people here:[|loop people|>
67- [|show last_name|], [|show first_name|][|if show_title |>: [|show title|] <|else|> **title redacted** <|if|] ::>[|loop tags|> [|show tag|]<|loop|] <:: <|loop|]
68<|view|]
69"#)?;
70
71 let ctx = Context::from([
72 ("people".to_string(), vec![
73 [
74 ("first_name".into(), "Joe".into()),
75 ("last_name".into(), "Smith".into()),
76 ("show_title".into(), true.into()),
77 ("title".into(), "CEO".into()),
78 ("tags".into(), vec![
79 Context::from([("tag".into(), "jerk".into()),]).into(),
80 Context::from([("tag".into(), "ugly".into()),]).into(),
81 ].into()),
82 ].into(),
83 [
84 ("first_name".into(), "Chris".into()),
85 ("last_name".into(), "Perkens".into()),
86 ("show_title".into(), false.into()),
87 ("title".into(), "Baconeer".into()),
88 ("tags".into(), vec![
89 Context::from([("tag".into(), "jerk".into()),]).into(),
90 Context::from([("tag".into(), "ugly".into()),]).into(),
91 ].into()),
92 ].into(),
93 [
94 ("first_name".into(), "Will".into()),
95 ("last_name".into(), "Power".into()),
96 ("show_title".into(), false.into()),
97 ("title".into(), "CFO".into()),
98 ("tags".into(), vec![
99 Context::from([("tag".into(), "jerk".into()),]).into(),
100 Context::from([("tag".into(), "ugly".into()),]).into(),
101 ].into()),
102 ].into(),
103 [
104 ("first_name".into(), "Justin".into()),
105 ("last_name".into(), "Time".into()),
106 ("show_title".into(), true.into()),
107 ("title".into(), "CIO".into()),
108 ("tags".into(), vec![
109 Context::from([("tag".into(), "jerk".into()),]).into(),
110 Context::from([("tag".into(), "ugly".into()),]).into(),
111 ].into()),
112 ].into(),
113 ].into()),
114 ]);
115
116 println!("View result: {}", ct.render("index", &ctx)? );
117
118 Ok(())
119}
120
121#[test]
122fn conditional() -> Result<()> {
123 let mut ct = DeepCrow::new();
124 ct.load_static(r#"Hi there
125[|view "index"|>
126Color: [|if is_red|> red <|elif is_blue |> blue <|else|> green <|if|]
127<|view|]"#)?;
128
129 let ctx = Context::from([
130 ("is_red".into(), false.into()),
131 ("is_blue".into(), false.into()),
132 ("color".into(), "purple".into()),
133 ]);
134
135 println!("View result: {}", ct.render("index", &ctx)? );
136
137 Ok(())
138}
139
140struct Item {
141 pub id: i32,
142 pub title: String,
143 pub body: String,
144}
145
146struct Person {
147 pub id: i32,
148 pub username: String,
149 pub name: String,
150}
151
152struct Page {
153 pub user: Person,
154 pub total_items: i32,
155 pub total_pages: i32,
156 pub cur_page: i32,
157 pub items: Vec<Item>,
158}
159
160impl Page {
161 fn new() -> Page {
162 Page {
163 user: Person {
164 id: 443,
165 username: "eichlan".into(),
166 name: "Mike".into(),
167 },
168 total_items: 4000,
169 total_pages: 400,
170 cur_page: 35,
171 items: vec![
172 Item{
173 id: 123,
174 title: "hi".into(),
175 body: "body".into(),
176 },
177 Item{
178 id: 124,
179 title: "bye".into(),
180 body: "wooo".into(),
181 },
182 Item{
183 id: 125,
184 title: "ciao".into(),
185 body: "whatever".into(),
186 }
187 ],
188 }
189 }
190}
191
192impl<'a> MappedStructure<'a> for Page {
193 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
194 match id {
195 "user" => Some(MappedValue::Struct(&self.user)),
196 "total_items" => Some(MappedValue::Int32(self.total_items)),
197 "total_pages" => Some(MappedValue::Int32(self.total_pages)),
198 "cur_page" => Some(MappedValue::Int32(self.cur_page)),
199 "items" => Some(MappedValue::<'a>::List(&self.items)),
200 _ => None,
201 }
202 }
203}
204
205impl<'a> MappedStructure<'a> for Person {
206 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
207 match id {
208 "id" => Some(MappedValue::Int32(self.id)),
209 "username" => Some(MappedValue::String(&self.username)),
210 "name" => Some(MappedValue::String(&self.name)),
211 _ => None,
212 }
213 }
214}
215
216impl<'a> MappedStructure<'a> for Item {
217 fn get_value(&'a self, id: &str) -> Option<MappedValue<'a>> {
218 match id {
219 "id" => Some(MappedValue::Int32(self.id)),
220 "title" => Some(MappedValue::String(&self.title)),
221 "body" => Some(MappedValue::String(&self.body)),
222 _ => None,
223 }
224 }
225}
226
227#[test]
228fn custom() -> Result<()> {
229 let page = Page::new();
230
231 println!("{:?}",
232 page.get_value(&"total_pages")
233 );
234
235 if let Some(MappedValue::List(l)) = page.get_value(&"items") {
236 l.for_each(&|x: &MappedValue, buf: &mut String| {
237 if let MappedValue::Struct(s) = x {
238 println!(" - {:?}", s.get_value(&"title"));
239 buf.push_str(&format!("{:?}",s.get_value(&"title")));
240 }
241 Ok(())
242 }).expect("loop");
243 }
244 Ok(())
245}
246