-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy patheval_template_test.go
More file actions
195 lines (155 loc) · 6.98 KB
/
Copy patheval_template_test.go
File metadata and controls
195 lines (155 loc) · 6.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package vuego_test
import (
"bytes"
"os"
"testing"
"testing/fstest"
"github.com/stretchr/testify/require"
"github.com/titpetric/vuego"
)
// TestRequiredAttributeError tests that a missing :required attribute
// produces an error. Ideally, the error should include file/line information
// from the source .vuego template.
//
// CURRENT LIMITATION: golang.org/x/net/html.Node does not track source line information.
// See: https://github.com/golang/go/issues/34302
//
// To add line tracking, we would need to either:
// 1. Use a forked version of html parser that tracks offsets/lines
// 2. Maintain a separate mapping of nodes to source positions
// 3. Wait for upstream support in golang.org/x/net/html
func TestRequiredAttributeError(t *testing.T) {
vue := vuego.NewVue(os.DirFS("testdata"))
data := map[string]any{
// Both pageTitle and pageAuthor are missing to trigger validation errors
// The component requires both "title" and "author"
}
var buf bytes.Buffer
err := vue.Render(t.Context(), &buf, "required-error-test/page.vuego", data)
require.Equal(t, "error in required-error-test/component.vuego (included from required-error-test/page.vuego): required attribute 'title' not provided", err.Error())
}
// TestRootLevelTemplateRequired tests that a root-level template with :required attribute
// validates the required attribute at the document root level.
func TestRootLevelTemplateRequired(t *testing.T) {
vue := vuego.NewVue(os.DirFS("testdata"))
data := map[string]any{
// Missing 'title' which is required by the template
}
var buf bytes.Buffer
err := vue.Render(t.Context(), &buf, "root-template-required/page.vuego", data)
require.Equal(t, "required attribute 'title' not provided", err.Error())
}
// TestRootLevelTemplateRequiredSuccess tests that a root-level template with :required attribute
// renders successfully when the required attribute is provided.
func TestRootLevelTemplateRequiredSuccess(t *testing.T) {
vue := vuego.NewVue(os.DirFS("testdata"))
data := map[string]any{
"title": "My Page Title",
}
var buf bytes.Buffer
err := vue.Render(t.Context(), &buf, "root-template-required/page.vuego", data)
require.NoError(t, err)
require.Contains(t, buf.String(), "<h1>My Page Title</h1>")
}
// TestRequiredCSVExpansion tests that :required supports CSV format
// e.g., :required="name,title,author" expands to multiple required fields.
func TestRequiredCSVExpansion(t *testing.T) {
vue := vuego.NewVue(os.DirFS("testdata"))
// Missing 'author' when both 'title' and 'author' are required via CSV
data := map[string]any{
"title": "Article Title",
}
var buf bytes.Buffer
err := vue.Render(t.Context(), &buf, "required-error-test/page.vuego", data)
require.Equal(t, "error in required-error-test/component.vuego (included from required-error-test/page.vuego): required attribute 'author' not provided", err.Error())
}
// TestTemplateSimpleAttribute tests that a simple bound attribute on a template
// is evaluated and available in the template's children.
func TestTemplate_SimpleAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template :x="5">X={{ x }}</template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{})
require.NoError(t, err)
require.Equal(t, "X=5", buf.String())
}
// TestTemplateExpressionAttribute tests that a bound attribute with an expression
// is evaluated and available in the template's children.
func TestTemplate_ExpressionAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template :x="2+3">X={{ x }}</template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{})
require.NoError(t, err)
require.Equal(t, "X=5", buf.String())
}
// TestTemplateVariableAttribute tests that a bound attribute using a context variable
// is evaluated and available in the template's children.
func TestTemplate_VariableAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template :x="y">X={{ x }}</template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{"y": 10})
require.NoError(t, err)
require.Equal(t, "X=10", buf.String())
}
// TestTemplateVariableAttribute tests that a bound attribute using a context variable
// is evaluated and available in the template's children. The json is decoded and each
// key should then be available under `data.*`.
func TestTemplate_VariableAttribute_JSON(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template :data="jsonFile('test.json')">X={{ data.x }}</template>`)},
"test.json": {Data: []byte(`{"x": 10}`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{})
require.NoError(t, err)
require.Equal(t, "X=10", buf.String())
}
// TestTemplateNestedAttribute tests that nested templates each have their own
// bound attributes and can reference parent attributes.
func TestTemplate_NestedAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template :x="1"><template :y="x+1">X={{ x }} Y={{ y }}</template></template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{})
require.NoError(t, err)
require.Equal(t, "X=1 Y=2", buf.String())
}
// TestTemplateForAttribute tests that bound attributes on a template with v-for
// are evaluated for each iteration and available in the children.
func TestTemplate_ForAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template v-for="item in items" :index="0">{{ item }}:{{ index }} </template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{"items": []int{1, 2, 3}})
require.NoError(t, err)
require.Equal(t, "1:0 2:0 3:0 ", buf.String())
}
// TestTemplate_ForStatefulAttribute tests that bound attributes on a template with v-for
// can use expressions that reference context variables.
// Note: Uses :printed instead of :count due to a quirk in variable name handling.
func TestTemplate_ForStatefulAttribute(t *testing.T) {
templateFS := &fstest.MapFS{
"test.vuego": {Data: []byte(`<template v-for="item in items" :printed="0"><template v-if="item > 1" :printed="printed+1">{{ item }}:{{ printed }} </template></template>`)},
}
var buf bytes.Buffer
vue := vuego.NewVue(templateFS)
err := vue.RenderFragment(t.Context(), &buf, "test.vuego", map[string]any{"items": []int{1, 2, 3}})
require.NoError(t, err)
// Item 1: printed=0, v-if false (1 > 1 is false), nothing rendered
// Item 2: printed=0, v-if true (2 > 1 is true), :printed="0+1"=1, renders "2:1 "
// Item 3: printed=0, v-if true (3 > 1 is true), :printed="0+1"=1, renders "3:1 "
require.Equal(t, "2:1 3:1 ", buf.String())
}