From 279228f9a4c3bf4e5cd3fe3bb512f1ba4efd36fe Mon Sep 17 00:00:00 2001 From: Ben Kraft Date: Wed, 15 Jul 2020 11:46:32 -0700 Subject: [PATCH] Move tests to snapshots --- generate/testdata/QueryWithAlias.graphql | 1 + generate/testdata/QueryWithAlias.graphql.go | 5 + .../testdata/QueryWithDoubleAlias.graphql | 6 + .../testdata/QueryWithDoubleAlias.graphql.go | 6 + generate/testdata/QueryWithEnums.graphql | 5 + generate/testdata/QueryWithEnums.graphql.go | 12 ++ generate/testdata/QueryWithInput.graphql | 5 + generate/testdata/QueryWithInput.graphql.go | 19 ++ generate/testdata/QueryWithSlices.graphql | 8 + generate/testdata/QueryWithSlices.graphql.go | 8 + generate/testdata/QueryWithStructs.graphql | 8 + generate/testdata/QueryWithStructs.graphql.go | 8 + generate/testdata/SimpleQuery.graphql | 1 + generate/testdata/SimpleQuery.graphql.go | 5 + generate/testdata/UsesEnumTwice.graphql | 4 + generate/testdata/UsesEnumTwice.graphql.go | 15 ++ generate/testdata/schema.graphql | 31 +++ generate/types_test.go | 188 ++++++------------ 18 files changed, 204 insertions(+), 131 deletions(-) create mode 100644 generate/testdata/QueryWithAlias.graphql create mode 100644 generate/testdata/QueryWithAlias.graphql.go create mode 100644 generate/testdata/QueryWithDoubleAlias.graphql create mode 100644 generate/testdata/QueryWithDoubleAlias.graphql.go create mode 100644 generate/testdata/QueryWithEnums.graphql create mode 100644 generate/testdata/QueryWithEnums.graphql.go create mode 100644 generate/testdata/QueryWithInput.graphql create mode 100644 generate/testdata/QueryWithInput.graphql.go create mode 100644 generate/testdata/QueryWithSlices.graphql create mode 100644 generate/testdata/QueryWithSlices.graphql.go create mode 100644 generate/testdata/QueryWithStructs.graphql create mode 100644 generate/testdata/QueryWithStructs.graphql.go create mode 100644 generate/testdata/SimpleQuery.graphql create mode 100644 generate/testdata/SimpleQuery.graphql.go create mode 100644 generate/testdata/UsesEnumTwice.graphql create mode 100644 generate/testdata/UsesEnumTwice.graphql.go create mode 100644 generate/testdata/schema.graphql diff --git a/generate/testdata/QueryWithAlias.graphql b/generate/testdata/QueryWithAlias.graphql new file mode 100644 index 0000000..bd2598e --- /dev/null +++ b/generate/testdata/QueryWithAlias.graphql @@ -0,0 +1 @@ +{ User: user { ID: id } } diff --git a/generate/testdata/QueryWithAlias.graphql.go b/generate/testdata/QueryWithAlias.graphql.go new file mode 100644 index 0000000..74a9802 --- /dev/null +++ b/generate/testdata/QueryWithAlias.graphql.go @@ -0,0 +1,5 @@ +type Response struct { + User *struct { + ID string + } +} diff --git a/generate/testdata/QueryWithDoubleAlias.graphql b/generate/testdata/QueryWithDoubleAlias.graphql new file mode 100644 index 0000000..9a2c1b7 --- /dev/null +++ b/generate/testdata/QueryWithDoubleAlias.graphql @@ -0,0 +1,6 @@ +{ + user { + ID: id + AlsoID: id + } +} diff --git a/generate/testdata/QueryWithDoubleAlias.graphql.go b/generate/testdata/QueryWithDoubleAlias.graphql.go new file mode 100644 index 0000000..6a40da8 --- /dev/null +++ b/generate/testdata/QueryWithDoubleAlias.graphql.go @@ -0,0 +1,6 @@ +type Response struct { + User *struct { + ID string + AlsoID string + } `json:"user"` +} \ No newline at end of file diff --git a/generate/testdata/QueryWithEnums.graphql b/generate/testdata/QueryWithEnums.graphql new file mode 100644 index 0000000..34aea40 --- /dev/null +++ b/generate/testdata/QueryWithEnums.graphql @@ -0,0 +1,5 @@ +{ + user { + roles + } +} diff --git a/generate/testdata/QueryWithEnums.graphql.go b/generate/testdata/QueryWithEnums.graphql.go new file mode 100644 index 0000000..04446c9 --- /dev/null +++ b/generate/testdata/QueryWithEnums.graphql.go @@ -0,0 +1,12 @@ +type Response struct { + User *struct { + Roles []role `json:"roles"` + } `json:"user"` +} + +type role string + +const ( + studentRole role = "STUDENT" + teacherRole role = "TEACHER" +) \ No newline at end of file diff --git a/generate/testdata/QueryWithInput.graphql b/generate/testdata/QueryWithInput.graphql new file mode 100644 index 0000000..59febff --- /dev/null +++ b/generate/testdata/QueryWithInput.graphql @@ -0,0 +1,5 @@ +query ($query: UserQueryInput) { + user(query: $query) { + id + } +} diff --git a/generate/testdata/QueryWithInput.graphql.go b/generate/testdata/QueryWithInput.graphql.go new file mode 100644 index 0000000..b609231 --- /dev/null +++ b/generate/testdata/QueryWithInput.graphql.go @@ -0,0 +1,19 @@ +type Response struct { + User *struct { + Id string `json:"id"` + } `json:"user"` +} + +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"` +} \ No newline at end of file diff --git a/generate/testdata/QueryWithSlices.graphql b/generate/testdata/QueryWithSlices.graphql new file mode 100644 index 0000000..3640724 --- /dev/null +++ b/generate/testdata/QueryWithSlices.graphql @@ -0,0 +1,8 @@ +{ + user { + emails + emailsOrNull + emailsWithNulls + emailsWithNullsOrNull + } +} diff --git a/generate/testdata/QueryWithSlices.graphql.go b/generate/testdata/QueryWithSlices.graphql.go new file mode 100644 index 0000000..23b4ffc --- /dev/null +++ b/generate/testdata/QueryWithSlices.graphql.go @@ -0,0 +1,8 @@ +type Response struct { + User *struct { + Emails []string `json:"emails"` + EmailsOrNull []string `json:"emailsOrNull"` + EmailsWithNulls []*string `json:"emailsWithNulls"` + EmailsWithNullsOrNull []*string `json:"emailsWithNullsOrNull"` + } `json:"user"` +} \ No newline at end of file diff --git a/generate/testdata/QueryWithStructs.graphql b/generate/testdata/QueryWithStructs.graphql new file mode 100644 index 0000000..5850964 --- /dev/null +++ b/generate/testdata/QueryWithStructs.graphql @@ -0,0 +1,8 @@ +{ + user { + authMethods { + provider + email + } + } +} diff --git a/generate/testdata/QueryWithStructs.graphql.go b/generate/testdata/QueryWithStructs.graphql.go new file mode 100644 index 0000000..4460c3c --- /dev/null +++ b/generate/testdata/QueryWithStructs.graphql.go @@ -0,0 +1,8 @@ +type Response struct { + User *struct { + AuthMethods []struct { + Provider *string `json:"provider"` + Email *string `json:"email"` + } `json:"authMethods"` + } `json:"user"` +} \ No newline at end of file diff --git a/generate/testdata/SimpleQuery.graphql b/generate/testdata/SimpleQuery.graphql new file mode 100644 index 0000000..2e67e3f --- /dev/null +++ b/generate/testdata/SimpleQuery.graphql @@ -0,0 +1 @@ +{ user { id } } \ No newline at end of file diff --git a/generate/testdata/SimpleQuery.graphql.go b/generate/testdata/SimpleQuery.graphql.go new file mode 100644 index 0000000..e974001 --- /dev/null +++ b/generate/testdata/SimpleQuery.graphql.go @@ -0,0 +1,5 @@ +type Response struct { + User *struct { + Id string `json:"id"` + } `json:"user"` +} diff --git a/generate/testdata/UsesEnumTwice.graphql b/generate/testdata/UsesEnumTwice.graphql new file mode 100644 index 0000000..2350cd8 --- /dev/null +++ b/generate/testdata/UsesEnumTwice.graphql @@ -0,0 +1,4 @@ +{ + Me: user { roles } + OtherUser: user { roles } +} diff --git a/generate/testdata/UsesEnumTwice.graphql.go b/generate/testdata/UsesEnumTwice.graphql.go new file mode 100644 index 0000000..a24dbbd --- /dev/null +++ b/generate/testdata/UsesEnumTwice.graphql.go @@ -0,0 +1,15 @@ +type Response struct { + Me *struct { + Roles []role `json:"roles"` + } + OtherUser *struct { + Roles []role `json:"roles"` + } +} + +type role string + +const ( + studentRole role = "STUDENT" + teacherRole role = "TEACHER" +) \ No newline at end of file diff --git a/generate/testdata/schema.graphql b/generate/testdata/schema.graphql new file mode 100644 index 0000000..08846b3 --- /dev/null +++ b/generate/testdata/schema.graphql @@ -0,0 +1,31 @@ +enum Role { + STUDENT + TEACHER +} + +input UserQueryInput { + email: String + name: String + id: ID + role: Role +} + +type AuthMethod { + provider: String + email: String +} + +type User { + id: ID! + roles: [Role!] + name: String + emails: [String!]! + emailsOrNull: [String!] + emailsWithNulls: [String]! + emailsWithNullsOrNull: [String] + authMethods: [AuthMethod!]! +} + +type Query { + user(query: UserQueryInput): User +} diff --git a/generate/types_test.go b/generate/types_test.go index 798da8f..aa59f98 100644 --- a/generate/types_test.go +++ b/generate/types_test.go @@ -3,6 +3,8 @@ package generate import ( "fmt" "go/format" + "io/ioutil" + "path/filepath" "sort" "strings" "testing" @@ -11,146 +13,53 @@ import ( "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, err + return src, fmt.Errorf("go parse error: %w", err) } return string(formatted), nil } -var schemaText = ` - enum Role { - STUDENT - TEACHER - } - - input UserQueryInput { - email: String - name: String - id: ID - role: Role - } - - type AuthMethod { - provider: String - email: String - } - - type User { - id: ID! - roles: [Role!] - name: String - emails: [String!]! - emailsOrNull: [String!] - emailsWithNulls: [String]! - emailsWithNullsOrNull: [String] - authMethods: [AuthMethod!]! - } - - type Query { - user: User - } -` - func TestTypeForOperation(t *testing.T) { - tests := []struct { - name string - operation string - expectedGoType string - }{{ - "SimpleQuery", - `{ user { id } }`, - `type Response struct{ - User *struct { - Id string ` + "`json:\"id\"`" + ` - } ` + "`json:\"user\"`" + ` - }`, - }, { - "QueryWithAlias", - `{ User: user { ID: id } }`, - `type Response struct{ - User *struct { - ID string - } - }`, - // Here on out, we use aliases, just because aliases are a lot less - // annoying to write in Go strings than Go struct tags. - }, { - "QueryWithDoubleAlias", - `{ - User: user { - ID: id - AlsoID: id - } - }`, - `type Response struct{ - User *struct { - ID string - AlsoID string - } - }`, - }, { - "QueryWithSlices", - `{ - User: user { - Emails: emails - EmailsOrNull: emailsOrNull - EmailsWithNulls: emailsWithNulls - EmailsWithNullsOrNull: emailsWithNullsOrNull - } - }`, - `type Response struct{ - User *struct { - Emails []string - EmailsOrNull []string - EmailsWithNulls []*string - EmailsWithNullsOrNull []*string - } - }`, - }, { - "QueryWithStructs", - `{ - User: user { - AuthMethods: authMethods { - Provider: provider - Email: email - } - } - }`, - `type Response struct{ - User *struct { - AuthMethods []struct { - Provider *string - Email *string - } - } - }`, - }, { - "QueryWithEnums", - `{ - User: user { - Roles: roles - } - }`, - `type Response struct{ - User *struct { - Roles []role - } + // 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" - type role string - const ( - studentRole role = "STUDENT" - teacherRole role = "TEACHER" - )`, - }} - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - expectedGoType, err := gofmt(test.expectedGoType) + t.Run(graphqlFilename, func(t *testing.T) { + expectedGoType, err := gofmt(readFile(t, goFilename)) if err != nil { t.Fatal(err) } @@ -161,7 +70,8 @@ func TestTypeForOperation(t *testing.T) { t.Fatal(graphqlError) } - queryDoc, graphqlListError := gqlparser.LoadQuery(schema, test.operation) + queryDoc, graphqlListError := gqlparser.LoadQuery( + schema, readFile(t, graphqlFilename)) if graphqlListError != nil { t.Fatal(graphqlListError) } @@ -171,7 +81,7 @@ func TestTypeForOperation(t *testing.T) { } g := newGenerator(&Config{Package: "test_package"}, schema) - _, err = g.getTypeForOperation(queryDoc.Operations[0]) + err = g.addOperation(queryDoc.Operations[0]) if err != nil { t.Error(err) } @@ -184,11 +94,25 @@ func TestTypeForOperation(t *testing.T) { 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 @@ -224,6 +148,8 @@ func TestTypeForInputType(t *testing.T) { }, }} + schemaText := readFile(t, "schema.graphql") + for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) {