Skip to content

Commit

Permalink
Merge pull request 99designs#728 from fgallina/make-generated-resolve…
Browse files Browse the repository at this point in the history
…r-dependent-types-follow-configured-type

resolvergen: use the resolver type as base name for dependent types
  • Loading branch information
vektah authored Jun 24, 2019
2 parents 10dc564 + 892a692 commit c492797
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 3 deletions.
1 change: 1 addition & 0 deletions plugin/resolvergen/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Plugin struct{}
var _ plugin.CodeGenerator = &Plugin{}

func (m *Plugin) Name() string {
// TODO: typo, should be resolvergen
return "resovlergen"
}
func (m *Plugin) GenerateCode(data *codegen.Data) error {
Expand Down
6 changes: 3 additions & 3 deletions plugin/resolvergen/resolver.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ type {{.ResolverType}} struct {}
{{ range $object := .Objects -}}
{{- if $object.HasResolvers -}}
func (r *{{$.ResolverType}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} {
return &{{lcFirst $object.Name}}Resolver{r}
return &{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}{r}
}
{{ end -}}
{{ end }}

{{ range $object := .Objects -}}
{{- if $object.HasResolvers -}}
type {{lcFirst $object.Name}}Resolver struct { *Resolver }
type {{lcFirst $object.Name}}{{ucFirst $.ResolverType}} struct { *{{$.ResolverType}} }

{{ range $field := $object.Fields -}}
{{- if $field.IsResolver -}}
func (r *{{lcFirst $object.Name}}Resolver) {{$field.GoFieldName}}{{ $field.ShortResolverDeclaration }} {
func (r *{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}) {{$field.GoFieldName}}{{ $field.ShortResolverDeclaration }} {
panic("not implemented")
}
{{ end -}}
Expand Down
163 changes: 163 additions & 0 deletions plugin/resolvergen/resolver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package resolvergen

import (
"fmt"
"go/types"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"unicode"

"github.com/99designs/gqlgen/codegen"
"github.com/99designs/gqlgen/codegen/config"
"github.com/vektah/gqlparser/ast"
)

func TestPlugin_Name(t *testing.T) {
t.Run("test plugin name", func(t *testing.T) {
m := &Plugin{}
if got, want := m.Name(), "resovlergen"; got != want {
t.Errorf("Plugin.Name() = %v, want %v", got, want)
}
})
}

// Types for testing code generation, both Mutation and
// MutationResolver must implement types.Type.
type Mutation struct{}

func (m *Mutation) Underlying() types.Type {
return m
}

func (m *Mutation) String() string {
return "Mutation"
}

type MutationResolver struct{}

func (m *MutationResolver) Underlying() types.Type {
return m
}

func (m *MutationResolver) String() string {
return "MutationResolver"
}

func TestPlugin_GenerateCode(t *testing.T) {
makeData := func(cfg config.PackageConfig) *codegen.Data {
m := &Mutation{}
obj := &codegen.Object{
Definition: &ast.Definition{
Name: fmt.Sprint(m),
},
Root: true,
Fields: []*codegen.Field{
&codegen.Field{
IsResolver: true,
GoFieldName: "Name",
TypeReference: &config.TypeReference{
GO: m,
},
},
},
ResolverInterface: &MutationResolver{},
}
obj.Fields[0].Object = obj
return &codegen.Data{
Config: &config.Config{
Resolver: cfg,
},
Objects: codegen.Objects{obj},
}
}

t.Run("renders expected contents", func(t *testing.T) {
m := &Plugin{}

// use a temp dir to ensure generated file uniqueness,
// since if a file already exists it won't be
// overwritten.
tempDir, err := ioutil.TempDir("", "resolvergen-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDir)
filename := filepath.Join(tempDir, "generated.go")

data := makeData(config.PackageConfig{
Filename: filename,
Package: "customresolver",
Type: "CustomResolverType",
})
if err := m.GenerateCode(data); err != nil {
t.Fatal(err)
}

byteContents, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatal(err)
}
contents := string(byteContents)

want := "package customresolver"
if !strings.Contains(contents, want) {
t.Fatalf("expected package name not found: want = %q\n%s", want, contents)
}

// Skip all white-space chars after start and want
// length. Useful to jump to next non-white character
// contents for generated code assertions.
skipWhitespace := func(start int, want string) int {
return start + len(want) + strings.IndexFunc(
string(contents[start+len(want):]),
func(r rune) bool { return !unicode.IsSpace(r) },
)
}
// Check if want begins at the given start point.
lookingAt := func(start int, want string) bool {
return strings.Index(string(contents[start:]), want) == 0
}

// Assert Mutation method contents for *CustomResolverType
want = "func (r *CustomResolverType) Mutation() MutationResolver {"
start := strings.Index(contents, want)
if start == -1 {
t.Fatalf("mutation method for custom resolver not found: want = %q\n%s", want, contents)
}
start = skipWhitespace(start, want)
want = "return &mutationCustomResolverType{r}"
if !lookingAt(start, want) {
t.Fatalf("unexpected return on mutation method for custom resolver: want = %q\n%s", want, contents)
}
start = skipWhitespace(start, want)
want = "}"
if !lookingAt(start, want) {
t.Fatalf("unexpected contents on mutation method for custom resolver: want = %q\n%s", want, contents)
}

want = "type mutationCustomResolverType struct{ *CustomResolverType }"
if !strings.Contains(contents, want) {
t.Fatalf("expected embedded resolver type struct not found: want = %q\n%s", want, contents)
}

// Assert Name method contents for *mutationCustomResolverType
want = "func (r *mutationCustomResolverType) Name(ctx context.Context) (Mutation, error) {"
start = strings.Index(contents, want)
if start == -1 {
t.Fatalf("Name method for mutation custom resolver type not found: want = %q\n%s", want, contents)
}
start = skipWhitespace(start, want)
want = `panic("not implemented")`
if !lookingAt(start, want) {
t.Fatalf("unexpected Name method contents for mutation custom resolver type: want = %q\n%s", want, contents)
}
start = skipWhitespace(start, want)
want = "}"
if !lookingAt(start, want) {
t.Fatalf("unexpected Name method contents for mutation custom resolver type: want = %q\n%s", want, contents)
}
})
}

0 comments on commit c492797

Please sign in to comment.