Skip to content

Commit

Permalink
Merge pull request #537 from 99designs/stub-generation
Browse files Browse the repository at this point in the history
Stub generation
  • Loading branch information
vektah committed Feb 7, 2019
2 parents 43db679 + 787b38d commit 48a7e07
Show file tree
Hide file tree
Showing 17 changed files with 1,302 additions and 951 deletions.
5 changes: 1 addition & 4 deletions codegen/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,7 @@ func (f *Field) ResolverType() string {
}

func (f *Field) ShortResolverDeclaration() string {
if !f.IsResolver {
return ""
}
res := fmt.Sprintf("%s(ctx context.Context", f.GoFieldName)
res := "(ctx context.Context"

if !f.Object.Root {
res += fmt.Sprintf(", obj *%s", templates.CurrentImports.LookupType(f.Object.Type))
Expand Down
4 changes: 3 additions & 1 deletion codegen/generated!.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ type ComplexityRoot struct {
{{ if $object.HasResolvers }}
type {{$object.Name}}Resolver interface {
{{ range $field := $object.Fields -}}
{{ $field.ShortResolverDeclaration }}
{{- if $field.IsResolver }}
{{- $field.GoFieldName}}{{ $field.ShortResolverDeclaration }}
{{- end }}
{{ end }}
}
{{- end }}
Expand Down
210 changes: 210 additions & 0 deletions codegen/testserver/directive_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package testserver

import (
"context"
"fmt"
"net/http/httptest"
"testing"

"github.com/99designs/gqlgen/client"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/handler"
"github.com/stretchr/testify/require"
)

func TestDirectives(t *testing.T) {
resolvers := &Stub{}
resolvers.QueryResolver.DirectiveArg = func(ctx context.Context, arg string) (i *string, e error) {
s := "Ok"
return &s, nil
}

resolvers.QueryResolver.DirectiveInput = func(ctx context.Context, arg InputDirectives) (i *string, e error) {
s := "Ok"
return &s, nil
}

resolvers.QueryResolver.DirectiveInputNullable = func(ctx context.Context, arg *InputDirectives) (i *string, e error) {
s := "Ok"
return &s, nil
}

resolvers.QueryResolver.DirectiveNullableArg = func(ctx context.Context, arg *int, arg2 *int) (i *string, e error) {
s := "Ok"
return &s, nil
}

srv := httptest.NewServer(
handler.GraphQL(
NewExecutableSchema(Config{
Resolvers: resolvers,
Directives: DirectiveRoot{
Length: func(ctx context.Context, obj interface{}, next graphql.Resolver, min int, max *int) (interface{}, error) {
res, err := next(ctx)
if err != nil {
return nil, err
}

s := res.(string)
if len(s) < min {
return nil, fmt.Errorf("too short")
}
if max != nil && len(s) > *max {
return nil, fmt.Errorf("too long")
}
return res, nil
},
Range: func(ctx context.Context, obj interface{}, next graphql.Resolver, min *int, max *int) (interface{}, error) {
res, err := next(ctx)
if err != nil {
return nil, err
}

switch res := res.(type) {
case int:
if min != nil && res < *min {
return nil, fmt.Errorf("too small")
}
if max != nil && res > *max {
return nil, fmt.Errorf("too large")
}
return next(ctx)

case int64:
if min != nil && int(res) < *min {
return nil, fmt.Errorf("too small")
}
if max != nil && int(res) > *max {
return nil, fmt.Errorf("too large")
}
return next(ctx)

case *int:
if min != nil && *res < *min {
return nil, fmt.Errorf("too small")
}
if max != nil && *res > *max {
return nil, fmt.Errorf("too large")
}
return next(ctx)
}
return nil, fmt.Errorf("unsupported type %T", res)
},
},
}),
handler.ResolverMiddleware(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
path, _ := ctx.Value("path").([]int)
return next(context.WithValue(ctx, "path", append(path, 1)))
}),
handler.ResolverMiddleware(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
path, _ := ctx.Value("path").([]int)
return next(context.WithValue(ctx, "path", append(path, 2)))
}),
))
c := client.New(srv.URL)

t.Run("arg directives", func(t *testing.T) {
t.Run("when function errors on directives", func(t *testing.T) {
var resp struct {
DirectiveArg *string
}

err := c.Post(`query { directiveArg(arg: "") }`, &resp)

require.EqualError(t, err, `[{"message":"too short","path":["directiveArg"]}]`)
require.Nil(t, resp.DirectiveArg)
})
t.Run("when function errors on nullable arg directives", func(t *testing.T) {
var resp struct {
DirectiveNullableArg *string
}

err := c.Post(`query { directiveNullableArg(arg: -100) }`, &resp)

require.EqualError(t, err, `[{"message":"too small","path":["directiveNullableArg"]}]`)
require.Nil(t, resp.DirectiveNullableArg)
})
t.Run("when function success on nullable arg directives", func(t *testing.T) {
var resp struct {
DirectiveNullableArg *string
}

err := c.Post(`query { directiveNullableArg }`, &resp)

require.Nil(t, err)
require.Equal(t, "Ok", *resp.DirectiveNullableArg)
})
t.Run("when function success on valid nullable arg directives", func(t *testing.T) {
var resp struct {
DirectiveNullableArg *string
}

err := c.Post(`query { directiveNullableArg(arg: 1) }`, &resp)

require.Nil(t, err)
require.Equal(t, "Ok", *resp.DirectiveNullableArg)
})
t.Run("when function success", func(t *testing.T) {
var resp struct {
DirectiveArg *string
}

err := c.Post(`query { directiveArg(arg: "test") }`, &resp)

require.Nil(t, err)
require.Equal(t, "Ok", *resp.DirectiveArg)
})
})
t.Run("input field directives", func(t *testing.T) {
t.Run("when function errors on directives", func(t *testing.T) {
var resp struct {
DirectiveInputNullable *string
}

err := c.Post(`query { directiveInputNullable(arg: {text:"invalid text",inner:{message:"123"}}) }`, &resp)

require.EqualError(t, err, `[{"message":"too long","path":["directiveInputNullable"]}]`)
require.Nil(t, resp.DirectiveInputNullable)
})
t.Run("when function errors on inner directives", func(t *testing.T) {
var resp struct {
DirectiveInputNullable *string
}

err := c.Post(`query { directiveInputNullable(arg: {text:"2",inner:{message:""}}) }`, &resp)

require.EqualError(t, err, `[{"message":"too short","path":["directiveInputNullable"]}]`)
require.Nil(t, resp.DirectiveInputNullable)
})
t.Run("when function errors on nullable inner directives", func(t *testing.T) {
var resp struct {
DirectiveInputNullable *string
}

err := c.Post(`query { directiveInputNullable(arg: {text:"success",inner:{message:"1"},innerNullable:{message:""}}) }`, &resp)

require.EqualError(t, err, `[{"message":"too short","path":["directiveInputNullable"]}]`)
require.Nil(t, resp.DirectiveInputNullable)
})
t.Run("when function success", func(t *testing.T) {
var resp struct {
DirectiveInputNullable *string
}

err := c.Post(`query { directiveInputNullable(arg: {text:"23",inner:{message:"1"}}) }`, &resp)

require.Nil(t, err)
require.Equal(t, "Ok", *resp.DirectiveInputNullable)
})
t.Run("when function inner nullable success", func(t *testing.T) {
var resp struct {
DirectiveInputNullable *string
}

err := c.Post(`query { directiveInputNullable(arg: {text:"23",inner:{message:"1"},innerNullable:{message:"success"}}) }`, &resp)

require.Nil(t, err)
require.Equal(t, "Ok", *resp.DirectiveInputNullable)
})
})
}
Loading

0 comments on commit 48a7e07

Please sign in to comment.