203 lines
4.9 KiB
Go
203 lines
4.9 KiB
Go
package generate
|
|
|
|
import (
|
|
"fmt"
|
|
"go/format"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/vektah/gqlparser"
|
|
"github.com/vektah/gqlparser/ast"
|
|
)
|
|
|
|
const dataDir = "testdata"
|
|
|
|
func readFile(t *testing.T, filename string) string {
|
|
data, err := ioutil.ReadFile(filepath.Join(dataDir, filename))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return string(data)
|
|
}
|
|
|
|
func gofmt(src string) (string, error) {
|
|
src = strings.TrimSpace(src)
|
|
formatted, err := format.Source([]byte(src))
|
|
if err != nil {
|
|
return src, fmt.Errorf("go parse error: %w", err)
|
|
}
|
|
return string(formatted), nil
|
|
}
|
|
|
|
func TestTypeForOperation(t *testing.T) {
|
|
// This test uses the schema, queries, and expected-output in ./testdata.
|
|
// The schema is in schema.graphql. The queries are in TestName.graphql;
|
|
// the test asserts that such queries, when run through the type-generator,
|
|
// produce the types in TestName.go (the name of the overall response type
|
|
// will be Response).
|
|
//
|
|
// Change update on the next line to true to update all the expected output
|
|
// files to match current output.
|
|
// TODO(benkraft): Make this a flag or something.
|
|
update := false
|
|
|
|
files, err := ioutil.ReadDir(dataDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
schemaText := readFile(t, "schema.graphql")
|
|
|
|
for _, file := range files {
|
|
graphqlFilename := file.Name()
|
|
if graphqlFilename == "schema.graphql" || !strings.HasSuffix(graphqlFilename, ".graphql") {
|
|
continue
|
|
}
|
|
goFilename := graphqlFilename + ".go"
|
|
|
|
t.Run(graphqlFilename, func(t *testing.T) {
|
|
expectedGoType, err := gofmt(readFile(t, goFilename))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
schema, graphqlError := gqlparser.LoadSchema(
|
|
&ast.Source{Name: "test schema", Input: schemaText})
|
|
if graphqlError != nil {
|
|
t.Fatal(graphqlError)
|
|
}
|
|
|
|
queryDoc, graphqlListError := gqlparser.LoadQuery(
|
|
schema, readFile(t, graphqlFilename))
|
|
if graphqlListError != nil {
|
|
t.Fatal(graphqlListError)
|
|
}
|
|
|
|
if len(queryDoc.Operations) != 1 {
|
|
t.Fatalf("got %v operations, want 1", len(queryDoc.Operations))
|
|
}
|
|
|
|
g := newGenerator(&Config{Package: "test_package"}, schema)
|
|
err = g.addOperation(queryDoc.Operations[0])
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
// gofmt before comparing.
|
|
goType, err := gofmt(g.Types())
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if goType != expectedGoType {
|
|
t.Errorf("got:\n%v\nwant:\n%v\n", goType, expectedGoType)
|
|
if update {
|
|
t.Log("Updating testdata dir to match")
|
|
err = ioutil.WriteFile(
|
|
filepath.Join(dataDir, goFilename), []byte(goType), 0644)
|
|
if err != nil {
|
|
t.Errorf("Unable to update testdata dir: %v", err)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
if update {
|
|
// This is an error to ensure we don't commit update := true
|
|
t.Error("Updated testdata dir")
|
|
}
|
|
}
|
|
|
|
// TODO(benkraft): Figure out how to do this with testdata-files
|
|
func TestTypeForInputType(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
graphQLType string
|
|
expectedGoType string
|
|
otherTypes []string
|
|
}{{
|
|
`RequiredBuiltin`,
|
|
`String!`,
|
|
`string`,
|
|
nil,
|
|
}, {
|
|
`ListOfBuiltin`,
|
|
`[String]`,
|
|
`[]*string`,
|
|
nil,
|
|
}, {
|
|
`DefinedType`,
|
|
`UserQueryInput`,
|
|
`*userQueryInput`,
|
|
[]string{
|
|
`type role string
|
|
const (
|
|
studentRole role = "STUDENT"
|
|
teacherRole role = "TEACHER"
|
|
)`,
|
|
`type userQueryInput struct {
|
|
Email *string ` + "`json:\"email\"`" + `
|
|
Name *string ` + "`json:\"name\"`" + `
|
|
Id *string ` + "`json:\"id\"`" + `
|
|
Role *role ` + "`json:\"role\"`" + `
|
|
}`,
|
|
},
|
|
}}
|
|
|
|
schemaText := readFile(t, "schema.graphql")
|
|
|
|
for _, test := range tests {
|
|
test := test
|
|
t.Run(test.name, func(t *testing.T) {
|
|
sort.Strings(test.otherTypes) // To match generator.Types()
|
|
expectedGoCode := fmt.Sprintf(
|
|
"type Input %s\n\n%s", test.expectedGoType,
|
|
strings.Join(test.otherTypes, "\n\n"))
|
|
expectedGoCode, err := gofmt(expectedGoCode)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
extraSchemaText := fmt.Sprintf(
|
|
"extend type Query { testQuery(var: %s): User }", test.graphQLType)
|
|
schema, graphqlError := gqlparser.LoadSchema(
|
|
&ast.Source{Name: "test schema", Input: schemaText},
|
|
&ast.Source{Name: "test schema extension", Input: extraSchemaText},
|
|
)
|
|
if graphqlError != nil {
|
|
t.Fatal(graphqlError)
|
|
}
|
|
|
|
operation := fmt.Sprintf(
|
|
"query($var: %s) { testQuery(var: $var) { id } }", test.graphQLType)
|
|
queryDoc, graphqlListError := gqlparser.LoadQuery(schema, operation)
|
|
if graphqlListError != nil {
|
|
t.Fatal(graphqlListError)
|
|
}
|
|
|
|
g := newGenerator(&Config{Package: "test_package"}, schema)
|
|
goType, err := g.getTypeForInputType(
|
|
queryDoc.Operations[0].VariableDefinitions[0].Type)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
goCode := fmt.Sprintf("type Input %s\n\n%s", goType, g.Types())
|
|
|
|
// gofmt before comparing.
|
|
goCode, err = gofmt(goCode)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if goCode != expectedGoCode {
|
|
t.Errorf("got:\n%v\nwant:\n%v\n", goCode, expectedGoCode)
|
|
}
|
|
})
|
|
}
|
|
}
|