github.com/apipluspower/gqlgen@v0.15.2/codegen/testserver/singlefile/nulls_test.go (about) 1 package singlefile 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/apipluspower/gqlgen/client" 8 "github.com/apipluspower/gqlgen/graphql/handler" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestNullBubbling(t *testing.T) { 13 resolvers := &Stub{} 14 resolvers.QueryResolver.Valid = func(ctx context.Context) (s string, e error) { 15 return "Ok", nil 16 } 17 resolvers.QueryResolver.Errors = func(ctx context.Context) (errors *Errors, e error) { 18 return &Errors{}, nil 19 } 20 resolvers.QueryResolver.ErrorBubble = func(ctx context.Context) (i *Error, e error) { 21 return &Error{ID: "E1234"}, nil 22 } 23 resolvers.QueryResolver.ErrorBubbleList = func(ctx context.Context) (i []*Error, e error) { 24 return []*Error{nil}, nil 25 } 26 resolvers.QueryResolver.ErrorList = func(ctx context.Context) (i []*Error, e error) { 27 return []*Error{nil}, nil 28 } 29 30 c := client.New(handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolvers}))) 31 32 t.Run("when function errors on non required field", func(t *testing.T) { 33 var resp struct { 34 Valid string 35 ErrorBubble *struct { 36 Id string 37 ErrorOnNonRequiredField *string 38 } 39 } 40 err := c.Post(`query { valid, errorBubble { id, errorOnNonRequiredField } }`, &resp) 41 42 require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnNonRequiredField"]}]`) 43 require.Equal(t, "E1234", resp.ErrorBubble.Id) 44 require.Nil(t, resp.ErrorBubble.ErrorOnNonRequiredField) 45 require.Equal(t, "Ok", resp.Valid) 46 }) 47 48 t.Run("when function errors", func(t *testing.T) { 49 var resp struct { 50 Valid string 51 ErrorBubble *struct { 52 NilOnRequiredField string 53 } 54 } 55 err := c.Post(`query { valid, errorBubble { id, errorOnRequiredField } }`, &resp) 56 57 require.EqualError(t, err, `[{"message":"boom","path":["errorBubble","errorOnRequiredField"]}]`) 58 require.Nil(t, resp.ErrorBubble) 59 require.Equal(t, "Ok", resp.Valid) 60 }) 61 62 t.Run("when user returns null on required field", func(t *testing.T) { 63 var resp struct { 64 Valid string 65 ErrorBubble *struct { 66 NilOnRequiredField string 67 } 68 } 69 err := c.Post(`query { valid, errorBubble { id, nilOnRequiredField } }`, &resp) 70 71 require.EqualError(t, err, `[{"message":"must not be null","path":["errorBubble","nilOnRequiredField"]}]`) 72 require.Nil(t, resp.ErrorBubble) 73 require.Equal(t, "Ok", resp.Valid) 74 }) 75 76 t.Run("when list element is null", func(t *testing.T) { 77 var resp struct { 78 Valid string 79 ErrorList []*struct{} 80 } 81 err := c.Post(`query { valid, errorList { id } }`, &resp) 82 83 require.Nil(t, err) 84 require.Equal(t, len(resp.ErrorList), 1) 85 require.Nil(t, resp.ErrorList[0]) 86 require.Equal(t, "Ok", resp.Valid) 87 }) 88 89 t.Run("when non-null list element is null", func(t *testing.T) { 90 var resp struct { 91 Valid string 92 ErrorBubbleList []*struct{} 93 } 94 err := c.Post(`query { valid, errorBubbleList { id } }`, &resp) 95 96 require.EqualError(t, err, `[{"message":"must not be null","path":["errorBubbleList",0]}]`) 97 require.Nil(t, resp.ErrorBubbleList) 98 require.Equal(t, "Ok", resp.Valid) 99 }) 100 101 t.Run("null args", func(t *testing.T) { 102 var resp struct { 103 NullableArg *string 104 } 105 resolvers.QueryResolver.NullableArg = func(ctx context.Context, arg *int) (i *string, e error) { 106 v := "Ok" 107 return &v, nil 108 } 109 110 err := c.Post(`query { nullableArg(arg: null) }`, &resp) 111 require.Nil(t, err) 112 require.Equal(t, "Ok", *resp.NullableArg) 113 }) 114 115 t.Run("concurrent null detection", func(t *testing.T) { 116 var resp interface{} 117 resolvers.ErrorsResolver.A = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 118 resolvers.ErrorsResolver.B = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 119 resolvers.ErrorsResolver.C = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 120 resolvers.ErrorsResolver.D = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 121 resolvers.ErrorsResolver.E = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 122 123 err := c.Post(`{ errors { 124 a { id }, 125 b { id }, 126 c { id }, 127 d { id }, 128 e { id }, 129 } }`, &resp) 130 131 require.Error(t, err) 132 require.Contains(t, err.Error(), "must not be null") 133 }) 134 }