github.com/luciferinlove/gqlgen@v0.17.16-bzc.1/codegen/testserver/followschema/nulls_test.go (about) 1 package followschema 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/luciferinlove/gqlgen/client" 8 "github.com/luciferinlove/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{{ID: "1"}, nil, 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":"the requested element is null which the schema does not allow","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.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",2]}`) 97 require.Contains(t, err.Error(), `{"message":"the requested element is null which the schema does not allow","path":["errorBubbleList",1]}`) 98 require.Nil(t, resp.ErrorBubbleList) 99 require.Equal(t, "Ok", resp.Valid) 100 }) 101 102 t.Run("null args", func(t *testing.T) { 103 var resp struct { 104 NullableArg *string 105 } 106 resolvers.QueryResolver.NullableArg = func(ctx context.Context, arg *int) (i *string, e error) { 107 v := "Ok" 108 return &v, nil 109 } 110 111 err := c.Post(`query { nullableArg(arg: null) }`, &resp) 112 require.Nil(t, err) 113 require.Equal(t, "Ok", *resp.NullableArg) 114 }) 115 116 t.Run("concurrent null detection", func(t *testing.T) { 117 var resp interface{} 118 resolvers.ErrorsResolver.A = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 119 resolvers.ErrorsResolver.B = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 120 resolvers.ErrorsResolver.C = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 121 resolvers.ErrorsResolver.D = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 122 resolvers.ErrorsResolver.E = func(ctx context.Context, obj *Errors) (i *Error, e error) { return nil, nil } 123 124 err := c.Post(`{ errors { 125 a { id }, 126 b { id }, 127 c { id }, 128 d { id }, 129 e { id }, 130 } }`, &resp) 131 132 require.Error(t, err) 133 require.Contains(t, err.Error(), "the requested element is null which the schema does not allow") 134 }) 135 }