Skip to content

Commit 44c6e63

Browse files
committed
validation: arguments
1 parent 30dcc33 commit 44c6e63

File tree

7 files changed

+1158
-10
lines changed

7 files changed

+1158
-10
lines changed

graphql.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/neelance/graphql-go/internal/exec"
1313
"github.com/neelance/graphql-go/internal/query"
1414
"github.com/neelance/graphql-go/internal/schema"
15+
"github.com/neelance/graphql-go/internal/validation"
1516
"github.com/neelance/graphql-go/introspection"
1617
)
1718

@@ -116,11 +117,16 @@ func (s *Schema) Exec(ctx context.Context, queryString string, operationName str
116117
}
117118
defer span.Finish()
118119

119-
data, errs := exec.ExecuteRequest(subCtx, s.exec, document, operationName, variables, s.MaxParallelism)
120-
if len(errs) != 0 {
121-
ext.Error.Set(span, true)
122-
span.SetTag(OpenTracingTagError, errs)
120+
var data interface{}
121+
errs := validation.Validate(s.schema, document)
122+
if len(errs) == 0 {
123+
data, errs = exec.ExecuteRequest(subCtx, s.exec, document, operationName, variables, s.MaxParallelism)
124+
if len(errs) != 0 {
125+
ext.Error.Set(span, true)
126+
span.SetTag(OpenTracingTagError, errs)
127+
}
123128
}
129+
124130
return &Response{
125131
Data: data,
126132
Errors: errs,

graphql_test.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ func TestMutation(t *testing.T) {
842842
Schema: starwarsSchema,
843843
Query: `
844844
{
845-
reviews(episode: "JEDI") {
845+
reviews(episode: JEDI) {
846846
stars
847847
commentary
848848
}
@@ -912,7 +912,7 @@ func TestMutation(t *testing.T) {
912912
Schema: starwarsSchema,
913913
Query: `
914914
{
915-
reviews(episode: "JEDI") {
915+
reviews(episode: JEDI) {
916916
stars
917917
commentary
918918
}
@@ -1532,8 +1532,7 @@ func TestInput(t *testing.T) {
15321532
Schema: coercionSchema,
15331533
Query: `
15341534
{
1535-
int1: int(value: 42)
1536-
int2: int(value: 42.0)
1535+
int(value: 42)
15371536
float1: float(value: 42)
15381537
float2: float(value: 42.5)
15391538
string(value: "foo")
@@ -1552,8 +1551,7 @@ func TestInput(t *testing.T) {
15521551
`,
15531552
ExpectedResult: `
15541553
{
1555-
"int1": 42,
1556-
"int2": 42,
1554+
"int": 42,
15571555
"float1": 42,
15581556
"float2": 42.5,
15591557
"string": "foo",

internal/tests/all_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package tests
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"reflect"
7+
"testing"
8+
9+
"encoding/json"
10+
11+
"github.com/neelance/graphql-go/errors"
12+
"github.com/neelance/graphql-go/internal/query"
13+
"github.com/neelance/graphql-go/internal/schema"
14+
"github.com/neelance/graphql-go/internal/validation"
15+
)
16+
17+
type Test struct {
18+
Name string
19+
Query string
20+
Errors []*errors.QueryError
21+
}
22+
23+
func TestAll(t *testing.T) {
24+
d, err := ioutil.ReadFile("testdata/test.schema")
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
29+
s := schema.New()
30+
if err := s.Parse(string(d)); err != nil {
31+
t.Fatal(err)
32+
}
33+
34+
f, err := os.Open("testdata/tests.json")
35+
if err != nil {
36+
t.Fatal(err)
37+
}
38+
39+
var tests []*Test
40+
if err := json.NewDecoder(f).Decode(&tests); err != nil {
41+
t.Fatal(err)
42+
}
43+
44+
for _, test := range tests {
45+
t.Run(test.Name, func(t *testing.T) {
46+
d, err := query.Parse(test.Query)
47+
if err != nil {
48+
t.Error(err)
49+
}
50+
got := validation.Validate(s, d)
51+
if got == nil {
52+
got = []*errors.QueryError{}
53+
}
54+
if !reflect.DeepEqual(test.Errors, got) {
55+
t.Errorf("wrong errors\nexpected: %v\ngot: %v", test.Errors, got)
56+
}
57+
})
58+
}
59+
}

internal/tests/testdata/LICENSE

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
The files in this testdata directory are derived from the graphql-js project:
2+
https://github.com/graphql/graphql-js
3+
4+
BSD License
5+
6+
For GraphQL software
7+
8+
Copyright (c) 2015, Facebook, Inc. All rights reserved.
9+
10+
Redistribution and use in source and binary forms, with or without modification,
11+
are permitted provided that the following conditions are met:
12+
13+
* Redistributions of source code must retain the above copyright notice, this
14+
list of conditions and the following disclaimer.
15+
16+
* Redistributions in binary form must reproduce the above copyright notice,
17+
this list of conditions and the following disclaimer in the documentation
18+
and/or other materials provided with the distribution.
19+
20+
* Neither the name Facebook nor the names of its contributors may be used to
21+
endorse or promote products derived from this software without specific
22+
prior written permission.
23+
24+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

internal/tests/testdata/test.schema

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
schema {
2+
query: QueryRoot
3+
}
4+
5+
directive @onQuery on QUERY
6+
7+
directive @onMutation on MUTATION
8+
9+
directive @onSubscription on SUBSCRIPTION
10+
11+
directive @onField on FIELD
12+
13+
directive @onFragmentDefinition on FRAGMENT_DEFINITION
14+
15+
directive @onFragmentSpread on FRAGMENT_SPREAD
16+
17+
directive @onInlineFragment on INLINE_FRAGMENT
18+
19+
directive @onSchema on SCHEMA
20+
21+
directive @onScalar on SCALAR
22+
23+
directive @onObject on OBJECT
24+
25+
directive @onFieldDefinition on FIELD_DEFINITION
26+
27+
directive @onArgumentDefinition on ARGUMENT_DEFINITION
28+
29+
directive @onInterface on INTERFACE
30+
31+
directive @onUnion on UNION
32+
33+
directive @onEnum on ENUM
34+
35+
directive @onEnumValue on ENUM_VALUE
36+
37+
directive @onInputObject on INPUT_OBJECT
38+
39+
directive @onInputFieldDefinition on INPUT_FIELD_DEFINITION
40+
41+
type Alien implements Being, Intelligent {
42+
iq: Int
43+
name(surname: Boolean): String
44+
numEyes: Int
45+
}
46+
47+
interface Being {
48+
name(surname: Boolean): String
49+
}
50+
51+
interface Canine {
52+
name(surname: Boolean): String
53+
}
54+
55+
type Cat implements Being, Pet {
56+
name(surname: Boolean): String
57+
nickname: String
58+
meows: Boolean
59+
meowVolume: Int
60+
furColor: FurColor
61+
}
62+
63+
union CatOrDog = Dog | Cat
64+
65+
input ComplexInput {
66+
requiredField: Boolean!
67+
intField: Int
68+
stringField: String
69+
booleanField: Boolean
70+
stringListField: [String]
71+
}
72+
73+
type ComplicatedArgs {
74+
intArgField(intArg: Int): String
75+
nonNullIntArgField(nonNullIntArg: Int!): String
76+
stringArgField(stringArg: String): String
77+
booleanArgField(booleanArg: Boolean): String
78+
enumArgField(enumArg: FurColor): String
79+
floatArgField(floatArg: Float): String
80+
idArgField(idArg: ID): String
81+
stringListArgField(stringListArg: [String]): String
82+
complexArgField(complexArg: ComplexInput): String
83+
multipleReqs(req1: Int!, req2: Int!): String
84+
multipleOpts(opt1: Int = 0, opt2: Int = 0): String
85+
multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int = 0, opt2: Int = 0): String
86+
}
87+
88+
type Dog implements Being, Pet, Canine {
89+
name(surname: Boolean): String
90+
nickname: String
91+
barkVolume: Int
92+
barks: Boolean
93+
doesKnowCommand(dogCommand: DogCommand): Boolean
94+
isHousetrained(atOtherHomes: Boolean = true): Boolean
95+
isAtLocation(x: Int, y: Int): Boolean
96+
}
97+
98+
enum DogCommand {
99+
SIT
100+
HEEL
101+
DOWN
102+
}
103+
104+
union DogOrHuman = Dog | Human
105+
106+
enum FurColor {
107+
BROWN
108+
BLACK
109+
TAN
110+
SPOTTED
111+
}
112+
113+
type Human implements Being, Intelligent {
114+
name(surname: Boolean): String
115+
pets: [Pet]
116+
relatives: [Human]
117+
iq: Int
118+
}
119+
120+
union HumanOrAlien = Human | Alien
121+
122+
interface Intelligent {
123+
iq: Int
124+
}
125+
126+
interface Pet {
127+
name(surname: Boolean): String
128+
}
129+
130+
type QueryRoot {
131+
human(id: ID): Human
132+
alien: Alien
133+
dog: Dog
134+
cat: Cat
135+
pet: Pet
136+
catOrDog: CatOrDog
137+
dogOrHuman: DogOrHuman
138+
humanOrAlien: HumanOrAlien
139+
complicatedArgs: ComplicatedArgs
140+
}

0 commit comments

Comments
 (0)