1 package formatter_test
2
3 import (
4 "bytes"
5 "flag"
6 "os"
7 "path"
8 "path/filepath"
9 "testing"
10 "unicode/utf8"
11
12 "github.com/stretchr/testify/assert"
13 "github.com/vektah/gqlparser/v2"
14 "github.com/vektah/gqlparser/v2/ast"
15 "github.com/vektah/gqlparser/v2/formatter"
16 "github.com/vektah/gqlparser/v2/parser"
17 )
18
19 var update = flag.Bool("u", false, "update golden files")
20
21 var optionSets = []struct {
22 name string
23 opts []formatter.FormatterOption
24 }{
25 {"default", nil},
26 {"spaceIndent", []formatter.FormatterOption{formatter.WithIndent(" ")}},
27 {"comments", []formatter.FormatterOption{formatter.WithComments()}},
28 }
29
30 func TestFormatter_FormatSchema(t *testing.T) {
31 const testSourceDir = "./testdata/source/schema"
32 const testBaselineDir = "./testdata/baseline/FormatSchema"
33
34 for _, optionSet := range optionSets {
35 testBaselineDir := filepath.Join(testBaselineDir, optionSet.name)
36 opts := optionSet.opts
37 t.Run(optionSet.name, func(t *testing.T) {
38 executeGoldenTesting(t, &goldenConfig{
39 SourceDir: testSourceDir,
40 BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string {
41 return path.Join(testBaselineDir, f.Name())
42 },
43 Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte {
44
45 schema, gqlErr := gqlparser.LoadSchema(&ast.Source{
46 Name: f.Name(),
47 Input: mustReadFile(path.Join(testSourceDir, f.Name())),
48 })
49 if gqlErr != nil {
50 t.Fatal(gqlErr)
51 }
52
53
54 var buf bytes.Buffer
55 formatter.NewFormatter(&buf, opts...).FormatSchema(schema)
56
57
58 _, gqlErr = gqlparser.LoadSchema(&ast.Source{
59 Name: f.Name(),
60 Input: buf.String(),
61 })
62 if gqlErr != nil {
63 t.Log(buf.String())
64 t.Fatal(gqlErr)
65 }
66
67 return buf.Bytes()
68 },
69 })
70 })
71 }
72 }
73
74 func TestFormatter_FormatSchemaDocument(t *testing.T) {
75 const testSourceDir = "./testdata/source/schema"
76 const testBaselineDir = "./testdata/baseline/FormatSchemaDocument"
77
78 for _, optionSet := range optionSets {
79 testBaselineDir := filepath.Join(testBaselineDir, optionSet.name)
80 opts := optionSet.opts
81 t.Run(optionSet.name, func(t *testing.T) {
82 executeGoldenTesting(t, &goldenConfig{
83 SourceDir: testSourceDir,
84 BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string {
85 return path.Join(testBaselineDir, f.Name())
86 },
87 Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte {
88
89 doc, gqlErr := parser.ParseSchema(&ast.Source{
90 Name: f.Name(),
91 Input: mustReadFile(path.Join(testSourceDir, f.Name())),
92 })
93 if gqlErr != nil {
94 t.Fatal(gqlErr)
95 }
96
97
98 var buf bytes.Buffer
99 formatter.NewFormatter(&buf, opts...).FormatSchemaDocument(doc)
100
101
102 _, gqlErr = parser.ParseSchema(&ast.Source{
103 Name: f.Name(),
104 Input: buf.String(),
105 })
106 if gqlErr != nil {
107 t.Log(buf.String())
108 t.Fatal(gqlErr)
109 }
110
111 return buf.Bytes()
112 },
113 })
114 })
115 }
116 }
117
118 func TestFormatter_FormatQueryDocument(t *testing.T) {
119 const testSourceDir = "./testdata/source/query"
120 const testBaselineDir = "./testdata/baseline/FormatQueryDocument"
121
122 for _, optionSet := range optionSets {
123 testBaselineDir := filepath.Join(testBaselineDir, optionSet.name)
124 opts := optionSet.opts
125 t.Run(optionSet.name, func(t *testing.T) {
126 executeGoldenTesting(t, &goldenConfig{
127 SourceDir: testSourceDir,
128 BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string {
129 return path.Join(testBaselineDir, f.Name())
130 },
131 Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte {
132
133 doc, gqlErr := parser.ParseQuery(&ast.Source{
134 Name: f.Name(),
135 Input: mustReadFile(path.Join(testSourceDir, f.Name())),
136 })
137 if gqlErr != nil {
138 t.Fatal(gqlErr)
139 }
140
141
142 var buf bytes.Buffer
143 formatter.NewFormatter(&buf, opts...).FormatQueryDocument(doc)
144
145
146 _, gqlErr = parser.ParseQuery(&ast.Source{
147 Name: f.Name(),
148 Input: buf.String(),
149 })
150 if gqlErr != nil {
151 t.Log(buf.String())
152 t.Fatal(gqlErr)
153 }
154
155 return buf.Bytes()
156 },
157 })
158 })
159 }
160 }
161
162 type goldenConfig struct {
163 SourceDir string
164 IsTarget func(f os.FileInfo) bool
165 BaselineFileName func(cfg *goldenConfig, f os.DirEntry) string
166 Run func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte
167 }
168
169 func executeGoldenTesting(t *testing.T, cfg *goldenConfig) {
170 t.Helper()
171
172 if cfg.IsTarget == nil {
173 cfg.IsTarget = func(f os.FileInfo) bool {
174 return !f.IsDir()
175 }
176 }
177 if cfg.BaselineFileName == nil {
178 t.Fatal("BaselineFileName function is required")
179 }
180 if cfg.Run == nil {
181 t.Fatal("Run function is required")
182 }
183
184 fs, err := os.ReadDir(cfg.SourceDir)
185 if err != nil {
186 t.Fatal(fs)
187 }
188
189 for _, f := range fs {
190 if f.IsDir() {
191 continue
192 }
193 f := f
194
195 t.Run(f.Name(), func(t *testing.T) {
196 result := cfg.Run(t, cfg, f)
197
198 expectedFilePath := cfg.BaselineFileName(cfg, f)
199
200 if *update {
201 err := os.Remove(expectedFilePath)
202 if err != nil && !os.IsNotExist(err) {
203 t.Fatal(err)
204 }
205 }
206
207 expected, err := os.ReadFile(expectedFilePath)
208 if os.IsNotExist(err) {
209 err = os.MkdirAll(path.Dir(expectedFilePath), 0o755)
210 if err != nil {
211 t.Fatal(err)
212 }
213 err = os.WriteFile(expectedFilePath, result, 0o444)
214 if err != nil {
215 t.Fatal(err)
216 }
217 return
218
219 } else if err != nil {
220 t.Fatal(err)
221 }
222
223 if bytes.Equal(expected, result) {
224 return
225 }
226
227 if utf8.Valid(expected) {
228 assert.Equalf(t, string(expected), string(result), "if you want to accept new result. use -u option")
229 }
230 })
231 }
232 }
233
234 func mustReadFile(name string) string {
235 src, err := os.ReadFile(name)
236 if err != nil {
237 panic(err)
238 }
239
240 return string(src)
241 }
242
View as plain text