template_test.gno
7.12 Kb · 319 lines
1package template
2
3import (
4 "testing"
5)
6
7func TestTrimMarkers(t *testing.T) {
8 tests := []struct {
9 name string
10 template string
11 data map[string]interface{}
12 expected string
13 }{
14 {
15 name: "no_trim",
16 template: "{{23}} < {{45}}",
17 expected: "23 < 45",
18 },
19 {
20 name: "trim_both",
21 template: "{{23 -}} < {{- 45}}",
22 expected: "23<45",
23 },
24 {
25 name: "trim_left_only",
26 template: "{{23}} < {{- 45}}",
27 expected: "23 <45",
28 },
29 {
30 name: "trim_right_only",
31 template: "{{23 -}} < {{45}}",
32 expected: "23< 45",
33 },
34 {
35 name: "multiple_spaces",
36 template: "{{23 -}} < {{- 45}}",
37 expected: "23<45",
38 },
39 {
40 name: "newlines",
41 template: "{{23 -}}\n<\n{{- 45}}",
42 expected: "23<45",
43 },
44 {
45 name: "helper_with_trim",
46 template: "{{Bold \"hello\" -}} {{- Bold \"world\"}}",
47 expected: "**hello****world**",
48 },
49 {
50 name: "variable_with_trim",
51 template: "{{ .First -}} {{- .Second}}",
52 data: map[string]interface{}{
53 "First": "Hello",
54 "Second": "World",
55 },
56 expected: "HelloWorld",
57 },
58 }
59
60 for _, tt := range tests {
61 t.Run(tt.name, func(t *testing.T) {
62 r := NewRenderer()
63 got := r.Render(tt.template, tt.data)
64 if got != tt.expected {
65 t.Errorf("\nTemplate: %s\nExpected: %q\nGot: %q", tt.template, tt.expected, got)
66 }
67 })
68 }
69}
70
71func TestNestedPlaceholders(t *testing.T) {
72 template := `# Welcome, {{ .Name }}!
73[Your Profile]({{ .ProfileURL }})`
74
75 data := map[string]interface{}{
76 "Name": "Alice",
77 "ProfileURL": "https://example.com/profile/Alice",
78 }
79
80 expected := `# Welcome, Alice!
81[Your Profile](https://example.com/profile/Alice)`
82
83 r := NewRenderer()
84 got := r.Render(template, data)
85 if got != expected {
86 t.Errorf("\nExpected:\n%s\nGot:\n%s", expected, got)
87 }
88}
89
90func TestHelpers(t *testing.T) {
91 tests := []struct {
92 name string
93 template string
94 data map[string]interface{}
95 expected string
96 }{
97 {
98 name: "bold_helper",
99 template: `{{ Bold "hello" }}`,
100 expected: "**hello**",
101 },
102 {
103 name: "multiple_helpers",
104 template: `{{ H1 "Section" }}
105{{ Bold "Important" }}
106{{ BulletItem "First" }}
107{{ BulletItem "Second" }}`,
108 expected: "# Section\n\n**Important**\n- First\n\n- Second\n",
109 },
110 {
111 name: "helper_with_quotes",
112 template: `{{ Bold "\"quoted text\"" }}`,
113 expected: `**\"quoted text\"**`,
114 },
115 {
116 name: "helper_with_spaces",
117 template: `{{ Bold " spaced " }}`,
118 expected: "** spaced **",
119 },
120 {
121 name: "concat_two_strings",
122 template: `{{ concat "Hello" " World" }}`,
123 expected: "Hello World",
124 },
125 {
126 name: "concat_multiple_strings",
127 template: `{{ concat "Hello" " " "wonderful" " " "World" "!" }}`,
128 expected: "Hello wonderful World!",
129 },
130 {
131 name: "concat_with_vars",
132 template: `{{ concat .Greeting " " .Name "!" }}`,
133 data: map[string]interface{}{
134 "Greeting": "Hello",
135 "Name": "Alice",
136 },
137 expected: "Hello Alice!",
138 },
139 {
140 name: "concat_empty",
141 template: `{{ concat }}`,
142 expected: "",
143 },
144 {
145 name: "printf_basic",
146 template: `{{ printf "Hello %s!" "World" }}`,
147 expected: "Hello World!",
148 },
149 {
150 name: "printf_multiple_args",
151 template: `{{ printf "%s has %s items" "Cart" "5" }}`,
152 expected: "Cart has 5 items",
153 },
154 {
155 name: "string_helper",
156 template: `{{ string "test" }}`,
157 expected: "test",
158 },
159 {
160 name: "trim_helper",
161 template: `{{ trim " spaced " }}`,
162 expected: "spaced",
163 },
164 {
165 name: "index_numeric",
166 template: `{{ index "array" "0" }}`,
167 expected: "[0]",
168 },
169 {
170 name: "index_string",
171 template: `{{ index "map" "key" }}`,
172 expected: "[key]",
173 },
174 }
175
176 for _, tt := range tests {
177 t.Run(tt.name, func(t *testing.T) {
178 r := NewRenderer()
179 got := r.Render(tt.template, tt.data)
180 if got != tt.expected {
181 t.Errorf("\nTemplate: %s\nExpected: %q\nGot: %q", tt.template, tt.expected, got)
182 }
183 })
184 }
185}
186
187func TestHelperErrors(t *testing.T) {
188 tests := []struct {
189 name string
190 template string
191 }{
192 {
193 name: "unknown_helper",
194 template: `{{ Unknown "test" }}`,
195 },
196 {
197 name: "missing_argument",
198 template: `{{ Bold }}`,
199 },
200 }
201
202 for _, tt := range tests {
203 t.Run(tt.name, func(t *testing.T) {
204 r := NewRenderer()
205 got := r.Render(tt.template, nil)
206 // Should not panic and should return some result
207 if got == "" {
208 t.Error("Expected non-empty result even with errors")
209 }
210 })
211 }
212}
213
214func TestControlFlow(t *testing.T) {
215 tests := []struct {
216 name string
217 template string
218 data map[string]interface{}
219 expected string
220 }{
221 {
222 name: "simple_range",
223 template: `{{ range .Items }}{{ . }}{{ end }}`,
224 data: map[string]interface{}{
225 "Items": []string{"a", "b", "c"},
226 },
227 expected: "abc",
228 },
229 {
230 name: "range_with_index",
231 template: `{{ range .Items }}[{{ . }}]{{ end }}`,
232 data: map[string]interface{}{
233 "Items": []int{1, 2, 3},
234 },
235 expected: "[1][2][3]",
236 },
237 {
238 name: "range_with_field",
239 template: "{{ range .Objects }}[{{ .Name }}]{{ end }}",
240 data: map[string]interface{}{
241 "Objects": []map[string]interface{}{
242 {"Name": "obj1"},
243 {"Name": "obj2"},
244 },
245 },
246 expected: "[obj1][obj2]",
247 },
248 {
249 name: "range_with_helpers",
250 template: `{{ range .Items }}{{ Bold . }}{{ end }}`,
251 data: map[string]interface{}{
252 "Items": []string{"a", "b", "c"},
253 },
254 expected: "**a****b****c**",
255 },
256 {
257 name: "Nested Range",
258 template: "{{ range .Outer }}{{ range .Inner }}{{ . }}{{ end }}{{ end }}",
259 data: map[string]interface{}{
260 "Outer": []interface{}{
261 map[string]interface{}{"Inner": []interface{}{"a", "b"}},
262 map[string]interface{}{"Inner": []interface{}{"c", "d"}},
263 },
264 },
265 expected: "abcd",
266 },
267 {
268 name: "Range in If",
269 template: "{{ if .Show }}{{ range .Items }}{{ . }}{{ end }}{{ end }}",
270 data: map[string]interface{}{
271 "Show": true,
272 "Items": []interface{}{"1", "2", "3"},
273 },
274 expected: "123",
275 },
276 {
277 name: "If in Range",
278 template: "{{ range .Items }}{{ if .Show }}{{ .Value }}{{ end }}{{ end }}",
279 data: map[string]interface{}{
280 "Items": []interface{}{
281 map[string]interface{}{"Show": true, "Value": "x"},
282 map[string]interface{}{"Show": false, "Value": "y"},
283 map[string]interface{}{"Show": true, "Value": "z"},
284 },
285 },
286 expected: "xz",
287 },
288 {
289 name: "If in If",
290 template: "{{ if .Outer }}{{ if .Inner }}Yes{{ else }}No{{ end }}{{ else }}No{{ end }}",
291 data: map[string]interface{}{
292 "Outer": true,
293 "Inner": true,
294 },
295 expected: "Yes",
296 },
297 {
298 name: "If in If in If",
299 template: "{{ if .First }}{{ if .Second }}{{ if .Third }}All True{{ else }}Third False{{ end }}{{ else }}Second False{{ end }}{{ else }}First False{{ end }}",
300 data: map[string]interface{}{
301 "First": true,
302 "Second": true,
303 "Third": false,
304 },
305 expected: "Third False",
306 },
307 }
308
309 for _, tt := range tests {
310 t.Run(tt.name, func(t *testing.T) {
311 r := NewRenderer()
312 got := r.Render(tt.template, tt.data)
313 if got != tt.expected {
314 t.Errorf("\nTemplate: %s\nData: %v\nExpected: %q\nGot: %q", tt.template, tt.data, tt.expected, got)
315 }
316 })
317 }
318}
319