From 7a82ab43a060b334d19c51a353a8924857dd39bb Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Thu, 7 Feb 2019 21:05:38 +1100 Subject: [PATCH] Test for #487 --- codegen/testserver/generated.go | 100 ++++++++++++++++++++++++++++++ codegen/testserver/input_test.go | 34 ++++++++++ codegen/testserver/resolver.go | 3 + codegen/testserver/schema.graphql | 1 + codegen/testserver/stub.go | 4 ++ 5 files changed, 142 insertions(+) create mode 100644 codegen/testserver/input_test.go diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 01e4719d104..44b59803780 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -112,6 +112,7 @@ type ComplexityRoot struct { DirectiveNullableArg func(childComplexity int, arg *int, arg2 *int) int DirectiveInputNullable func(childComplexity int, arg *InputDirectives) int DirectiveInput func(childComplexity int, arg InputDirectives) int + InputSlice func(childComplexity int, arg []string) int KeywordArgs func(childComplexity int, breakArg string, defaultArg string, funcArg string, interfaceArg string, selectArg string, caseArg string, deferArg string, goArg string, mapArg string, structArg string, chanArg string, elseArg string, gotoArg string, packageArg string, switchArg string, constArg string, fallthroughArg string, ifArg string, rangeArg string, typeArg string, continueArg string, forArg string, importArg string, returnArg string, varArg string) int } @@ -156,6 +157,7 @@ type QueryResolver interface { DirectiveNullableArg(ctx context.Context, arg *int, arg2 *int) (*string, error) DirectiveInputNullable(ctx context.Context, arg *InputDirectives) (*string, error) DirectiveInput(ctx context.Context, arg InputDirectives) (*string, error) + InputSlice(ctx context.Context, arg []string) (bool, error) KeywordArgs(ctx context.Context, breakArg string, defaultArg string, funcArg string, interfaceArg string, selectArg string, caseArg string, deferArg string, goArg string, mapArg string, structArg string, chanArg string, elseArg string, gotoArg string, packageArg string, switchArg string, constArg string, fallthroughArg string, ifArg string, rangeArg string, typeArg string, continueArg string, forArg string, importArg string, returnArg string, varArg string) (bool, error) } type SubscriptionResolver interface { @@ -462,6 +464,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.DirectiveInput(childComplexity, args["arg"].(InputDirectives)), true + case "Query.inputSlice": + if e.complexity.Query.InputSlice == nil { + break + } + + args, err := ec.field_Query_inputSlice_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.InputSlice(childComplexity, args["arg"].([]string)), true + case "Query.keywordArgs": if e.complexity.Query.KeywordArgs == nil { break @@ -665,6 +679,7 @@ var parsedSchema = gqlparser.MustLoadSchema( directiveNullableArg(arg: Int @range(min:0), arg2: Int @range): String directiveInputNullable(arg: InputDirectives): String directiveInput(arg: InputDirectives!): String + inputSlice(arg: [String!]!): Boolean! } type Subscription { @@ -986,6 +1001,20 @@ func (ec *executionContext) field_Query_directiveNullableArg_args(ctx context.Co return args, nil } +func (ec *executionContext) field_Query_inputSlice_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 []string + if tmp, ok := rawArgs["arg"]; ok { + arg0, err = ec.unmarshalNString2ᚕstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["arg"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_keywordArgs_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2176,6 +2205,39 @@ func (ec *executionContext) _Query_directiveInput(ctx context.Context, field gra return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } +func (ec *executionContext) _Query_inputSlice(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "Query", + Field: field, + Args: nil, + } + ctx = graphql.WithResolverContext(ctx, rctx) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_inputSlice_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + rctx.Args = args + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().InputSlice(rctx, args["arg"].([]string)) + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_keywordArgs(ctx context.Context, field graphql.CollectedField) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -3957,6 +4019,15 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr res = ec._Query_directiveInput(ctx, field) return res }) + case "inputSlice": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_inputSlice(ctx, field) + if res == graphql.Null { + invalid = true + } + return res + }) case "keywordArgs": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -4364,6 +4435,35 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S return graphql.MarshalString(v) } +func (ec *executionContext) unmarshalNString2ᚕstring(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNString2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNString2string(ctx, sel, v[i]) + } + + return ret +} + func (ec *executionContext) unmarshalNString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil diff --git a/codegen/testserver/input_test.go b/codegen/testserver/input_test.go new file mode 100644 index 00000000000..7e8f1f3b779 --- /dev/null +++ b/codegen/testserver/input_test.go @@ -0,0 +1,34 @@ +package testserver + +import ( + "context" + "net/http/httptest" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/handler" + "github.com/stretchr/testify/require" +) + +func TestInput(t *testing.T) { + resolvers := &Stub{} + + srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(Config{Resolvers: resolvers}))) + + c := client.New(srv.URL) + + t.Run("when function errors on directives", func(t *testing.T) { + resolvers.QueryResolver.InputSlice = func(ctx context.Context, arg []string) (b bool, e error) { + return true, nil + } + + var resp struct { + DirectiveArg *string + } + + err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp) + + require.EqualError(t, err, `http 422: {"errors":[{"message":"Expected type String!, found 1.","locations":[{"line":1,"column":32}]},{"message":"Expected type String!, found 2.","locations":[{"line":1,"column":35}]}],"data":null}`) + require.Nil(t, resp.DirectiveArg) + }) +} diff --git a/codegen/testserver/resolver.go b/codegen/testserver/resolver.go index 3aecb553fa2..d58c00725fd 100644 --- a/codegen/testserver/resolver.go +++ b/codegen/testserver/resolver.go @@ -92,6 +92,9 @@ func (r *queryResolver) DirectiveInputNullable(ctx context.Context, arg *InputDi func (r *queryResolver) DirectiveInput(ctx context.Context, arg InputDirectives) (*string, error) { panic("not implemented") } +func (r *queryResolver) InputSlice(ctx context.Context, arg []string) (bool, error) { + panic("not implemented") +} func (r *queryResolver) KeywordArgs(ctx context.Context, breakArg string, defaultArg string, funcArg string, interfaceArg string, selectArg string, caseArg string, deferArg string, goArg string, mapArg string, structArg string, chanArg string, elseArg string, gotoArg string, packageArg string, switchArg string, constArg string, fallthroughArg string, ifArg string, rangeArg string, typeArg string, continueArg string, forArg string, importArg string, returnArg string, varArg string) (bool, error) { panic("not implemented") } diff --git a/codegen/testserver/schema.graphql b/codegen/testserver/schema.graphql index da8e967569b..956c6c4461d 100644 --- a/codegen/testserver/schema.graphql +++ b/codegen/testserver/schema.graphql @@ -16,6 +16,7 @@ type Query { directiveNullableArg(arg: Int @range(min:0), arg2: Int @range): String directiveInputNullable(arg: InputDirectives): String directiveInput(arg: InputDirectives!): String + inputSlice(arg: [String!]!): Boolean! } type Subscription { diff --git a/codegen/testserver/stub.go b/codegen/testserver/stub.go index 09712806267..dfef6457b35 100644 --- a/codegen/testserver/stub.go +++ b/codegen/testserver/stub.go @@ -34,6 +34,7 @@ type Stub struct { DirectiveNullableArg func(ctx context.Context, arg *int, arg2 *int) (*string, error) DirectiveInputNullable func(ctx context.Context, arg *InputDirectives) (*string, error) DirectiveInput func(ctx context.Context, arg InputDirectives) (*string, error) + InputSlice func(ctx context.Context, arg []string) (bool, error) KeywordArgs func(ctx context.Context, breakArg string, defaultArg string, funcArg string, interfaceArg string, selectArg string, caseArg string, deferArg string, goArg string, mapArg string, structArg string, chanArg string, elseArg string, gotoArg string, packageArg string, switchArg string, constArg string, fallthroughArg string, ifArg string, rangeArg string, typeArg string, continueArg string, forArg string, importArg string, returnArg string, varArg string) (bool, error) } SubscriptionResolver struct { @@ -126,6 +127,9 @@ func (r *stubQuery) DirectiveInputNullable(ctx context.Context, arg *InputDirect func (r *stubQuery) DirectiveInput(ctx context.Context, arg InputDirectives) (*string, error) { return r.QueryResolver.DirectiveInput(ctx, arg) } +func (r *stubQuery) InputSlice(ctx context.Context, arg []string) (bool, error) { + return r.QueryResolver.InputSlice(ctx, arg) +} func (r *stubQuery) KeywordArgs(ctx context.Context, breakArg string, defaultArg string, funcArg string, interfaceArg string, selectArg string, caseArg string, deferArg string, goArg string, mapArg string, structArg string, chanArg string, elseArg string, gotoArg string, packageArg string, switchArg string, constArg string, fallthroughArg string, ifArg string, rangeArg string, typeArg string, continueArg string, forArg string, importArg string, returnArg string, varArg string) (bool, error) { return r.QueryResolver.KeywordArgs(ctx, breakArg, defaultArg, funcArg, interfaceArg, selectArg, caseArg, deferArg, goArg, mapArg, structArg, chanArg, elseArg, gotoArg, packageArg, switchArg, constArg, fallthroughArg, ifArg, rangeArg, typeArg, continueArg, forArg, importArg, returnArg, varArg) }