1package graphql_test 2 3import ( 4 "reflect" 5 "testing" 6 7 "github.com/graphql-go/graphql" 8 "github.com/graphql-go/graphql/gqlerrors" 9 "github.com/graphql-go/graphql/language/location" 10 "github.com/graphql-go/graphql/testutil" 11) 12 13// testNumberHolder maps to numberHolderType 14type testNumberHolder struct { 15 TheNumber int `json:"theNumber"` // map field to `theNumber` so it can be resolve by the default ResolveFn 16} 17type testRoot struct { 18 NumberHolder *testNumberHolder 19} 20 21func newTestRoot(originalNumber int) *testRoot { 22 return &testRoot{ 23 NumberHolder: &testNumberHolder{originalNumber}, 24 } 25} 26func (r *testRoot) ImmediatelyChangeTheNumber(newNumber int) *testNumberHolder { 27 r.NumberHolder.TheNumber = newNumber 28 return r.NumberHolder 29} 30func (r *testRoot) PromiseToChangeTheNumber(newNumber int) *testNumberHolder { 31 return r.ImmediatelyChangeTheNumber(newNumber) 32} 33func (r *testRoot) FailToChangeTheNumber(newNumber int) *testNumberHolder { 34 panic("Cannot change the number") 35} 36func (r *testRoot) PromiseAndFailToChangeTheNumber(newNumber int) *testNumberHolder { 37 panic("Cannot change the number") 38} 39 40// numberHolderType creates a mapping to testNumberHolder 41var numberHolderType = graphql.NewObject(graphql.ObjectConfig{ 42 Name: "NumberHolder", 43 Fields: graphql.Fields{ 44 "theNumber": &graphql.Field{ 45 Type: graphql.Int, 46 }, 47 }, 48}) 49 50var mutationsTestSchema, _ = graphql.NewSchema(graphql.SchemaConfig{ 51 Query: graphql.NewObject(graphql.ObjectConfig{ 52 Name: "Query", 53 Fields: graphql.Fields{ 54 "numberHolder": &graphql.Field{ 55 Type: numberHolderType, 56 }, 57 }, 58 }), 59 Mutation: graphql.NewObject(graphql.ObjectConfig{ 60 Name: "Mutation", 61 Fields: graphql.Fields{ 62 "immediatelyChangeTheNumber": &graphql.Field{ 63 Type: numberHolderType, 64 Args: graphql.FieldConfigArgument{ 65 "newNumber": &graphql.ArgumentConfig{ 66 Type: graphql.Int, 67 }, 68 }, 69 Resolve: func(p graphql.ResolveParams) (interface{}, error) { 70 newNumber := 0 71 obj, _ := p.Source.(*testRoot) 72 newNumber, _ = p.Args["newNumber"].(int) 73 return obj.ImmediatelyChangeTheNumber(newNumber), nil 74 }, 75 }, 76 "promiseToChangeTheNumber": &graphql.Field{ 77 Type: numberHolderType, 78 Args: graphql.FieldConfigArgument{ 79 "newNumber": &graphql.ArgumentConfig{ 80 Type: graphql.Int, 81 }, 82 }, 83 Resolve: func(p graphql.ResolveParams) (interface{}, error) { 84 newNumber := 0 85 obj, _ := p.Source.(*testRoot) 86 newNumber, _ = p.Args["newNumber"].(int) 87 return obj.PromiseToChangeTheNumber(newNumber), nil 88 }, 89 }, 90 "failToChangeTheNumber": &graphql.Field{ 91 Type: numberHolderType, 92 Args: graphql.FieldConfigArgument{ 93 "newNumber": &graphql.ArgumentConfig{ 94 Type: graphql.Int, 95 }, 96 }, 97 Resolve: func(p graphql.ResolveParams) (interface{}, error) { 98 newNumber := 0 99 obj, _ := p.Source.(*testRoot) 100 newNumber, _ = p.Args["newNumber"].(int) 101 return obj.FailToChangeTheNumber(newNumber), nil 102 }, 103 }, 104 "promiseAndFailToChangeTheNumber": &graphql.Field{ 105 Type: numberHolderType, 106 Args: graphql.FieldConfigArgument{ 107 "newNumber": &graphql.ArgumentConfig{ 108 Type: graphql.Int, 109 }, 110 }, 111 Resolve: func(p graphql.ResolveParams) (interface{}, error) { 112 newNumber := 0 113 obj, _ := p.Source.(*testRoot) 114 newNumber, _ = p.Args["newNumber"].(int) 115 return obj.PromiseAndFailToChangeTheNumber(newNumber), nil 116 }, 117 }, 118 }, 119 }), 120}) 121 122func TestMutations_ExecutionOrdering_EvaluatesMutationsSerially(t *testing.T) { 123 124 root := newTestRoot(6) 125 doc := `mutation M { 126 first: immediatelyChangeTheNumber(newNumber: 1) { 127 theNumber 128 }, 129 second: promiseToChangeTheNumber(newNumber: 2) { 130 theNumber 131 }, 132 third: immediatelyChangeTheNumber(newNumber: 3) { 133 theNumber 134 } 135 fourth: promiseToChangeTheNumber(newNumber: 4) { 136 theNumber 137 }, 138 fifth: immediatelyChangeTheNumber(newNumber: 5) { 139 theNumber 140 } 141 }` 142 143 expected := &graphql.Result{ 144 Data: map[string]interface{}{ 145 "first": map[string]interface{}{ 146 "theNumber": 1, 147 }, 148 "second": map[string]interface{}{ 149 "theNumber": 2, 150 }, 151 "third": map[string]interface{}{ 152 "theNumber": 3, 153 }, 154 "fourth": map[string]interface{}{ 155 "theNumber": 4, 156 }, 157 "fifth": map[string]interface{}{ 158 "theNumber": 5, 159 }, 160 }, 161 } 162 // parse query 163 ast := testutil.TestParse(t, doc) 164 165 // execute 166 ep := graphql.ExecuteParams{ 167 Schema: mutationsTestSchema, 168 AST: ast, 169 Root: root, 170 } 171 result := testutil.TestExecute(t, ep) 172 if len(result.Errors) != len(expected.Errors) { 173 t.Fatalf("Unexpected errors, Diff: %v", testutil.Diff(expected.Errors, result.Errors)) 174 } 175 if !reflect.DeepEqual(expected, result) { 176 t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) 177 } 178} 179func TestMutations_EvaluatesMutationsCorrectlyInThePresenceOfAFailedMutation(t *testing.T) { 180 181 root := newTestRoot(6) 182 doc := `mutation M { 183 first: immediatelyChangeTheNumber(newNumber: 1) { 184 theNumber 185 }, 186 second: promiseToChangeTheNumber(newNumber: 2) { 187 theNumber 188 }, 189 third: failToChangeTheNumber(newNumber: 3) { 190 theNumber 191 } 192 fourth: promiseToChangeTheNumber(newNumber: 4) { 193 theNumber 194 }, 195 fifth: immediatelyChangeTheNumber(newNumber: 5) { 196 theNumber 197 } 198 sixth: promiseAndFailToChangeTheNumber(newNumber: 6) { 199 theNumber 200 } 201 }` 202 203 expected := &graphql.Result{ 204 Data: map[string]interface{}{ 205 "first": map[string]interface{}{ 206 "theNumber": 1, 207 }, 208 "second": map[string]interface{}{ 209 "theNumber": 2, 210 }, 211 "third": nil, 212 "fourth": map[string]interface{}{ 213 "theNumber": 4, 214 }, 215 "fifth": map[string]interface{}{ 216 "theNumber": 5, 217 }, 218 "sixth": nil, 219 }, 220 Errors: []gqlerrors.FormattedError{ 221 { 222 Message: `Cannot change the number`, 223 Locations: []location.SourceLocation{ 224 {Line: 8, Column: 7}, 225 }, 226 }, 227 { 228 Message: `Cannot change the number`, 229 Locations: []location.SourceLocation{ 230 {Line: 17, Column: 7}, 231 }, 232 }, 233 }, 234 } 235 // parse query 236 ast := testutil.TestParse(t, doc) 237 238 // execute 239 ep := graphql.ExecuteParams{ 240 Schema: mutationsTestSchema, 241 AST: ast, 242 Root: root, 243 } 244 result := testutil.TestExecute(t, ep) 245 if len(result.Errors) != len(expected.Errors) { 246 t.Fatalf("Unexpected errors, Diff: %v", testutil.Diff(expected.Errors, result.Errors)) 247 } 248 t.Skipf("Testing equality for slice of errors in results") 249 if !reflect.DeepEqual(expected, result) { 250 t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result)) 251 } 252} 253