Skip to content

Commit

Permalink
simplify resolver test
Browse files Browse the repository at this point in the history
  • Loading branch information
vektah committed Jun 24, 2019
1 parent 7fed71b commit dbd2cc6
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 144 deletions.
16 changes: 16 additions & 0 deletions cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/99designs/gqlgen/api"
"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/plugin/modelgen"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
Expand Down Expand Up @@ -42,3 +43,18 @@ var genCmd = cli.Command{
}
},
}

func main() {
cfg, err := config.LoadConfigFromDefaultLocations()
if os.IsNotExist(errors.Cause(err)) {
cfg = config.DefaultConfig()
} else if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(2)
}

err = modelgen.New().(*modelgen.Plugin).MutateConfig(cfg)
if err != nil {
panic(err)
}
}
14 changes: 14 additions & 0 deletions plugin/resolvergen/out/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package customresolver

import "context"

type Resolver struct {
}

type QueryResolver interface {
Resolver(ctx context.Context) (*Resolver, error)
}

type ResolverResolver interface {
Name(ctx context.Context, obj *Resolver) (string, error)
}
26 changes: 26 additions & 0 deletions plugin/resolvergen/out/resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package customresolver

import (
"context"
) // THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.

type CustomResolverType struct{}

func (r *CustomResolverType) Query() QueryResolver {
return &queryCustomResolverType{r}
}
func (r *CustomResolverType) Resolver() ResolverResolver {
return &resolverCustomResolverType{r}
}

type queryCustomResolverType struct{ *CustomResolverType }

func (r *queryCustomResolverType) Resolver(ctx context.Context) (*Resolver, error) {
panic("not implemented")
}

type resolverCustomResolverType struct{ *CustomResolverType }

func (r *resolverCustomResolverType) Name(ctx context.Context, obj *Resolver) (string, error) {
panic("not implemented")
}
173 changes: 29 additions & 144 deletions plugin/resolvergen/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,162 +2,47 @@ package resolvergen

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

"github.com/99designs/gqlgen/codegen"
"github.com/99designs/gqlgen/codegen/config"
"github.com/vektah/gqlparser/ast"
"github.com/stretchr/testify/require"
"golang.org/x/tools/go/packages"
)

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)
}
})
}
func TestPlugin(t *testing.T) {
_ = syscall.Unlink("out/resolver.go")

// Types for testing code generation, both Mutation and
// MutationResolver must implement types.Type.
type Mutation struct{}
cfg, err := config.LoadConfig("testdata/gqlgen.yml")
require.NoError(t, err)
p := Plugin{}

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
}
data, err := codegen.BuildData(cfg)
if err != nil {
panic(err)
}

func (m *MutationResolver) String() string {
return "MutationResolver"
require.NoError(t, p.GenerateCode(data))
assertNoErrors(t, "github.com/99designs/gqlgen/plugin/resolvergen/out")
}

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},
}
func assertNoErrors(t *testing.T, pkg string) {
pkgs, err := packages.Load(&packages.Config{
Mode: packages.LoadTypes,
}, pkg)
if err != nil {
panic(err)
}

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)
hasErrors := false
for _, pkg := range pkgs {
for _, err := range pkg.Errors {
hasErrors = true
fmt.Println(err.Pos + ":" + err.Msg)
}
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)
}
})
}
if hasErrors {
t.Fatal("see compilation errors above")
}
}
14 changes: 14 additions & 0 deletions plugin/resolvergen/testdata/gqlgen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
schema:
- "testdata/schema.graphql"

exec:
filename: out/ignored.go
model:
filename: out/generated.go
resolver:
filename: out/resolver.go
type: CustomResolverType

models:
Resolver:
model: github.com/99designs/gqlgen/plugin/resolvergen/out.Resolver
7 changes: 7 additions & 0 deletions plugin/resolvergen/testdata/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type Query {
resolver: Resolver!
}

type Resolver {
name: String!
}

0 comments on commit dbd2cc6

Please sign in to comment.