1package tmpl
2
3import (
4	"encoding/json"
5	"fmt"
6	"github.com/google/go-cmp/cmp"
7	"path/filepath"
8	"reflect"
9	"testing"
10)
11
12func TestReadFile(t *testing.T) {
13	expected := `foo:
14  bar: BAR
15`
16	expectedFilename := "values.yaml"
17	ctx := &Context{basePath: ".", readFile: func(filename string) ([]byte, error) {
18		if filename != expectedFilename {
19			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename)
20		}
21		return []byte(expected), nil
22	}}
23	actual, err := ctx.ReadFile(expectedFilename)
24	if err != nil {
25		t.Errorf("unexpected error: %v", err)
26	}
27	if !reflect.DeepEqual(actual, expected) {
28		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
29	}
30}
31
32func TestReadFile_PassAbsPath(t *testing.T) {
33	expected := `foo:
34  bar: BAR
35`
36	expectedFilename, _ := filepath.Abs("values.yaml")
37	ctx := &Context{basePath: ".", readFile: func(filename string) ([]byte, error) {
38		if filename != expectedFilename {
39			return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedFilename, filename)
40		}
41		return []byte(expected), nil
42	}}
43	actual, err := ctx.ReadFile(expectedFilename)
44	if err != nil {
45		t.Errorf("unexpected error: %v", err)
46	}
47	if !reflect.DeepEqual(actual, expected) {
48		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
49	}
50}
51
52func TestToYaml_UnsupportedNestedMapKey(t *testing.T) {
53	expected := ``
54	vals := Values(map[string]interface{}{
55		"foo": map[interface{}]interface{}{
56			"bar": "BAR",
57		},
58	})
59	actual, err := ToYaml(vals)
60	if err == nil {
61		t.Fatalf("expected error but got none")
62	} else if err.Error() != "error marshaling into JSON: json: unsupported type: map[interface {}]interface {}" {
63		t.Fatalf("unexpected error: %v", err)
64	}
65
66	if !reflect.DeepEqual(actual, expected) {
67		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
68	}
69}
70
71func TestToYaml(t *testing.T) {
72	expected := `foo:
73  bar: BAR
74`
75	vals := Values(map[string]interface{}{
76		"foo": map[string]interface{}{
77			"bar": "BAR",
78		},
79	})
80	actual, err := ToYaml(vals)
81	if err != nil {
82		t.Errorf("unexpected error: %v", err)
83	}
84	if !reflect.DeepEqual(actual, expected) {
85		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
86	}
87}
88
89func TestFromYaml(t *testing.T) {
90	raw := `foo:
91  bar: BAR
92`
93	expected := Values(map[string]interface{}{
94		"foo": map[string]interface{}{
95			"bar": "BAR",
96		},
97	})
98	actual, err := FromYaml(raw)
99	if err != nil {
100		t.Errorf("unexpected error: %v", err)
101	}
102	if !reflect.DeepEqual(actual, expected) {
103		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
104	}
105}
106
107func TestFromYamlToJson(t *testing.T) {
108	input := `foo:
109  bar: BAR
110`
111	want := `{"foo":{"bar":"BAR"}}`
112
113	m, err := FromYaml(input)
114	if err != nil {
115		t.Fatalf("unexpected error: %v", err)
116	}
117
118	got, err := json.Marshal(m)
119	if err != nil {
120		t.Errorf("unexpected error: %v", err)
121	}
122
123	if d := cmp.Diff(want, string(got)); d != "" {
124		t.Errorf("unexpected result: want (-), got (+):\n%s", d)
125	}
126}
127
128func TestSetValueAtPath_OneComponent(t *testing.T) {
129	input := map[string]interface{}{
130		"foo": "",
131	}
132	expected := map[string]interface{}{
133		"foo": "FOO",
134	}
135	actual, err := SetValueAtPath("foo", "FOO", input)
136	if err != nil {
137		t.Errorf("unexpected error: %v", err)
138	}
139	if !reflect.DeepEqual(actual, expected) {
140		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
141	}
142}
143
144func TestSetValueAtPath_TwoComponents(t *testing.T) {
145	input := map[string]interface{}{
146		"foo": map[interface{}]interface{}{
147			"bar": "",
148		},
149	}
150	expected := map[string]interface{}{
151		"foo": map[interface{}]interface{}{
152			"bar": "FOO_BAR",
153		},
154	}
155	actual, err := SetValueAtPath("foo.bar", "FOO_BAR", input)
156	if err != nil {
157		t.Errorf("unexpected error: %v", err)
158	}
159	if !reflect.DeepEqual(actual, expected) {
160		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
161	}
162}
163
164func TestTpl(t *testing.T) {
165	text := `foo: {{ .foo }}
166`
167	expected := `foo: FOO
168`
169	ctx := &Context{basePath: "."}
170	actual, err := ctx.Tpl(text, map[string]interface{}{"foo": "FOO"})
171	if err != nil {
172		t.Errorf("unexpected error: %v", err)
173	}
174	if !reflect.DeepEqual(actual, expected) {
175		t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
176	}
177}
178
179func TestRequired(t *testing.T) {
180	type args struct {
181		warn string
182		val  interface{}
183	}
184	tests := []struct {
185		name    string
186		args    args
187		want    interface{}
188		wantErr bool
189	}{
190		{
191			name:    "required val is nil",
192			args:    args{warn: "This value is required", val: nil},
193			want:    nil,
194			wantErr: true,
195		},
196		{
197			name:    "required val is empty string",
198			args:    args{warn: "This value is required", val: ""},
199			want:    nil,
200			wantErr: true,
201		},
202		{
203			name:    "required val is existed",
204			args:    args{warn: "This value is required", val: "foo"},
205			want:    "foo",
206			wantErr: false,
207		},
208	}
209	for _, tt := range tests {
210		t.Run(tt.name, func(t *testing.T) {
211			got, err := Required(tt.args.warn, tt.args.val)
212			if (err != nil) != tt.wantErr {
213				t.Errorf("Required() error = %v, wantErr %v", err, tt.wantErr)
214				return
215			}
216			if !reflect.DeepEqual(got, tt.want) {
217				t.Errorf("Required() got = %v, want %v", got, tt.want)
218			}
219		})
220	}
221}
222