Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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