graphql 0.18.14 → 0.18.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/query_complexity.rb +15 -6
- data/lib/graphql/analysis/query_depth.rb +11 -10
- data/lib/graphql/directive.rb +2 -6
- data/lib/graphql/directive/include_directive.rb +0 -4
- data/lib/graphql/directive/skip_directive.rb +0 -4
- data/lib/graphql/execution/directive_checks.rb +22 -13
- data/lib/graphql/execution_error.rb +7 -0
- data/lib/graphql/internal_representation/node.rb +20 -2
- data/lib/graphql/internal_representation/rewrite.rb +66 -20
- data/lib/graphql/language/generation.rb +22 -8
- data/lib/graphql/language/nodes.rb +48 -20
- data/lib/graphql/language/parser.rb +436 -423
- data/lib/graphql/language/parser.y +22 -19
- data/lib/graphql/language/parser_tests.rb +131 -2
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -0
- data/lib/graphql/query/serial_execution/selection_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution/value_resolution.rb +4 -1
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/static_validation/message.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +10 -12
- data/spec/graphql/directive_spec.rb +139 -1
- data/spec/graphql/execution_error_spec.rb +63 -3
- data/spec/graphql/introspection/type_type_spec.rb +2 -0
- data/spec/graphql/language/generation_spec.rb +55 -7
- data/spec/graphql/query/executor_spec.rb +4 -2
- data/spec/graphql/schema/catchall_middleware_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +1 -1
- data/spec/graphql/schema/timeout_middleware_spec.rb +10 -5
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +6 -6
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +3 -3
- data/spec/graphql/static_validation/validator_spec.rb +1 -1
- data/spec/support/dairy_app.rb +8 -0
- metadata +30 -2
@@ -18,6 +18,28 @@ describe GraphQL::ExecutionError do
|
|
18
18
|
}
|
19
19
|
flavor
|
20
20
|
}
|
21
|
+
allDairy {
|
22
|
+
... on Cheese {
|
23
|
+
flavor
|
24
|
+
}
|
25
|
+
... on Milk {
|
26
|
+
source
|
27
|
+
executionError
|
28
|
+
}
|
29
|
+
}
|
30
|
+
dairy {
|
31
|
+
milks {
|
32
|
+
source
|
33
|
+
executionError
|
34
|
+
allDairy {
|
35
|
+
__typename
|
36
|
+
... on Milk {
|
37
|
+
origin
|
38
|
+
executionError
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
21
43
|
executionError
|
22
44
|
}
|
23
45
|
|
@@ -38,20 +60,58 @@ describe GraphQL::ExecutionError do
|
|
38
60
|
},
|
39
61
|
"flavor" => "Brie",
|
40
62
|
},
|
63
|
+
"allDairy" => [
|
64
|
+
{ "flavor" => "Brie" },
|
65
|
+
{ "flavor" => "Gouda" },
|
66
|
+
{ "flavor" => "Manchego" },
|
67
|
+
{ "source" => "COW", "executionError" => nil }
|
68
|
+
],
|
69
|
+
"dairy" => {
|
70
|
+
"milks" => [
|
71
|
+
{
|
72
|
+
"source" => "COW",
|
73
|
+
"executionError" => nil,
|
74
|
+
"allDairy" => [
|
75
|
+
{ "__typename" => "Cheese" },
|
76
|
+
{ "__typename" => "Cheese" },
|
77
|
+
{ "__typename" => "Cheese" },
|
78
|
+
{ "__typename" => "Milk", "origin" => "Antiquity", "executionError" => nil }
|
79
|
+
]
|
80
|
+
}
|
81
|
+
]
|
82
|
+
},
|
41
83
|
"executionError" => nil,
|
42
84
|
},
|
43
85
|
"errors"=>[
|
44
86
|
{
|
45
87
|
"message"=>"No cheeses are made from Yak milk!",
|
46
|
-
"locations"=>[{"line"=>5, "column"=>9}]
|
88
|
+
"locations"=>[{"line"=>5, "column"=>9}],
|
89
|
+
"path"=>["cheese", "error1"]
|
47
90
|
},
|
48
91
|
{
|
49
92
|
"message"=>"No cheeses are made from Yak milk!",
|
50
|
-
"locations"=>[{"line"=>8, "column"=>9}]
|
93
|
+
"locations"=>[{"line"=>8, "column"=>9}],
|
94
|
+
"path"=>["cheese", "error2"]
|
95
|
+
},
|
96
|
+
{
|
97
|
+
"message"=>"There was an execution error",
|
98
|
+
"locations"=>[{"line"=>22, "column"=>11}],
|
99
|
+
"path"=>["allDairy", 3, "executionError"]
|
100
|
+
},
|
101
|
+
{
|
102
|
+
"message"=>"There was an execution error",
|
103
|
+
"locations"=>[{"line"=>28, "column"=>11}],
|
104
|
+
"path"=>["dairy", "milks", 0, "executionError"]
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"message"=>"There was an execution error",
|
108
|
+
"locations"=>[{"line"=>33, "column"=>15}],
|
109
|
+
"path"=>["dairy", "milks", 0, "allDairy", 3, "executionError"]
|
51
110
|
},
|
52
111
|
{
|
53
112
|
"message"=>"There was an execution error",
|
54
|
-
"locations"=>[{"line"=>
|
113
|
+
"locations"=>[{"line"=>38, "column"=>7}],
|
114
|
+
"path"=>["executionError"]
|
55
115
|
},
|
56
116
|
]
|
57
117
|
}
|
@@ -41,6 +41,8 @@ describe GraphQL::Introspection::TypeType do
|
|
41
41
|
{"name"=>"LocalProduct"},
|
42
42
|
],
|
43
43
|
"fields"=>[
|
44
|
+
{"type"=>{"name"=>"List", "ofType"=>{"name"=>"DairyProduct"}}},
|
45
|
+
{"type"=>{"name"=>"String", "ofType"=>nil}},
|
44
46
|
{"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Float"}}},
|
45
47
|
{"type"=>{"name"=>"List", "ofType"=>{"name"=>"String"}}},
|
46
48
|
{"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"ID"}}},
|
@@ -10,7 +10,7 @@ describe GraphQL::Language::Generation do
|
|
10
10
|
...moreNestedFields @skip(if: $skipNested)
|
11
11
|
}
|
12
12
|
... on OtherType @include(unless: false) {
|
13
|
-
field(arg: [{
|
13
|
+
field(arg: [{key: "value", anotherKey: 0.9, anotherAnotherKey: WHATEVER}])
|
14
14
|
anotherField
|
15
15
|
}
|
16
16
|
... {
|
@@ -31,7 +31,7 @@ describe GraphQL::Language::Generation do
|
|
31
31
|
describe "inputs" do
|
32
32
|
let(:query_string) {%|
|
33
33
|
query {
|
34
|
-
field(int: 3, float: 4.7e-24, bool: false, string: "☀︎🏆\\n escaped \\" unicode ¶ /", enum: ENUM_NAME, array: [7, 8, 9], object: {
|
34
|
+
field(int: 3, float: 4.7e-24, bool: false, string: "☀︎🏆\\n escaped \\" unicode ¶ /", enum: ENUM_NAME, array: [7, 8, 9], object: {a: [1, 2, 3], b: {c: "4"}}, unicode_bom: "\xef\xbb\xbfquery")
|
35
35
|
}
|
36
36
|
|}
|
37
37
|
|
@@ -41,15 +41,63 @@ describe GraphQL::Language::Generation do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "schema" do
|
44
|
-
|
44
|
+
# From: https://github.com/graphql/graphql-js/blob/a725499b155285c2e33647a93393c82689b20b0f/src/language/__tests__/schema-kitchen-sink.graphql
|
45
|
+
let(:query_string) {<<-schema
|
45
46
|
schema {
|
46
|
-
query:
|
47
|
+
query: QueryType
|
48
|
+
mutation: MutationType
|
47
49
|
}
|
48
50
|
|
49
|
-
type
|
50
|
-
|
51
|
+
type Foo implements Bar {
|
52
|
+
one: Type
|
53
|
+
two(argument: InputType!): Type
|
54
|
+
three(argument: InputType, other: String): Int
|
55
|
+
four(argument: String = "string"): String
|
56
|
+
five(argument: [String] = ["string", "string"]): String
|
57
|
+
six(argument: InputType = {key: "value"}): Type
|
51
58
|
}
|
52
|
-
|
59
|
+
|
60
|
+
type AnnotatedObject @onObject(arg: "value") {
|
61
|
+
annotatedField(arg: Type = "default" @onArg): Type @onField
|
62
|
+
}
|
63
|
+
|
64
|
+
interface Bar {
|
65
|
+
one: Type
|
66
|
+
four(argument: String = "string"): String
|
67
|
+
}
|
68
|
+
|
69
|
+
interface AnnotatedInterface @onInterface {
|
70
|
+
annotatedField(arg: Type @onArg): Type @onField
|
71
|
+
}
|
72
|
+
|
73
|
+
union Feed = Story | Article | Advert
|
74
|
+
|
75
|
+
union AnnotatedUnion @onUnion = A | B
|
76
|
+
|
77
|
+
scalar CustomScalar
|
78
|
+
|
79
|
+
scalar AnnotatedScalar @onScalar
|
80
|
+
|
81
|
+
enum Site {
|
82
|
+
DESKTOP
|
83
|
+
MOBILE
|
84
|
+
}
|
85
|
+
|
86
|
+
enum AnnotatedEnum @onEnum {
|
87
|
+
ANNOTATED_VALUE @onEnumValue
|
88
|
+
OTHER_VALUE
|
89
|
+
}
|
90
|
+
|
91
|
+
input InputType {
|
92
|
+
key: String!
|
93
|
+
answer: Int = 42
|
94
|
+
}
|
95
|
+
|
96
|
+
input AnnotatedInput @onInputObjectType {
|
97
|
+
annotatedField: Type @onField
|
98
|
+
}
|
99
|
+
schema
|
100
|
+
}
|
53
101
|
|
54
102
|
it "generate" do
|
55
103
|
assert_equal query_string.gsub(/^ /, "").strip, document.to_query_string
|
@@ -143,7 +143,8 @@ describe GraphQL::Query::Executor do
|
|
143
143
|
"errors" => [
|
144
144
|
{
|
145
145
|
"message" => "BOOM",
|
146
|
-
"locations" => [ { "line" => 1, "column" => 28 } ]
|
146
|
+
"locations" => [ { "line" => 1, "column" => 28 } ],
|
147
|
+
"path" => ["noMilk", "cow", "cantBeNullButRaisesExecutionError"]
|
147
148
|
}
|
148
149
|
]
|
149
150
|
}
|
@@ -167,7 +168,8 @@ describe GraphQL::Query::Executor do
|
|
167
168
|
"errors"=>[
|
168
169
|
{
|
169
170
|
"message"=>"Error was handled!",
|
170
|
-
"locations" => [{"line"=>1, "column"=>17}]
|
171
|
+
"locations" => [{"line"=>1, "column"=>17}],
|
172
|
+
"path"=>["noMilk", "error"]
|
171
173
|
}
|
172
174
|
]
|
173
175
|
}
|
@@ -176,7 +176,7 @@ type Post {
|
|
176
176
|
}
|
177
177
|
|
178
178
|
type Query {
|
179
|
-
post(id: ID!, varied: Varied = {
|
179
|
+
post(id: ID!, varied: Varied = {id: \"123\", int: 234, float: 2.3, enum: FOO, sub: [{string: \"str\"}]}): Post
|
180
180
|
}
|
181
181
|
|
182
182
|
input Sub {
|
@@ -64,11 +64,13 @@ describe GraphQL::Schema::TimeoutMiddleware do
|
|
64
64
|
expected_errors = [
|
65
65
|
{
|
66
66
|
"message"=>"Timeout on Query.sleepFor",
|
67
|
-
"locations"=>[{"line"=>6, "column"=>9}]
|
67
|
+
"locations"=>[{"line"=>6, "column"=>9}],
|
68
|
+
"path"=>["d"]
|
68
69
|
},
|
69
70
|
{
|
70
71
|
"message"=>"Timeout on Query.sleepFor",
|
71
|
-
"locations"=>[{"line"=>7, "column"=>9}]
|
72
|
+
"locations"=>[{"line"=>7, "column"=>9}],
|
73
|
+
"path"=>["e"]
|
72
74
|
},
|
73
75
|
]
|
74
76
|
assert_equal expected_data, result["data"]
|
@@ -116,11 +118,13 @@ describe GraphQL::Schema::TimeoutMiddleware do
|
|
116
118
|
expected_errors = [
|
117
119
|
{
|
118
120
|
"message"=>"Timeout on NestedSleep.seconds",
|
119
|
-
"locations"=>[{"line"=>10, "column"=>15}]
|
121
|
+
"locations"=>[{"line"=>10, "column"=>15}],
|
122
|
+
"path"=>["a", "b", "c", "d", "seconds"]
|
120
123
|
},
|
121
124
|
{
|
122
125
|
"message"=>"Timeout on NestedSleep.nestedSleep",
|
123
|
-
"locations"=>[{"line"=>11, "column"=>15}]
|
126
|
+
"locations"=>[{"line"=>11, "column"=>15}],
|
127
|
+
"path"=>["a", "b", "c", "d", "e"]
|
124
128
|
},
|
125
129
|
]
|
126
130
|
|
@@ -149,7 +153,8 @@ describe GraphQL::Schema::TimeoutMiddleware do
|
|
149
153
|
expected_errors = [
|
150
154
|
{
|
151
155
|
"message"=>"Timeout on Query.sleepFor",
|
152
|
-
"locations"=>[{"line"=>6, "column"=>9}]
|
156
|
+
"locations"=>[{"line"=>6, "column"=>9}],
|
157
|
+
"path"=>["d"]
|
153
158
|
},
|
154
159
|
]
|
155
160
|
|
@@ -27,42 +27,42 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
27
27
|
query_root_error = {
|
28
28
|
"message"=>"Argument 'id' on Field 'cheese' has an invalid value. Expected type 'Int!'.",
|
29
29
|
"locations"=>[{"line"=>3, "column"=>7}],
|
30
|
-
"
|
30
|
+
"fields"=>["query getCheese", "cheese", "id"],
|
31
31
|
}
|
32
32
|
assert_includes(errors, query_root_error)
|
33
33
|
|
34
34
|
directive_error = {
|
35
35
|
"message"=>"Argument 'if' on Directive 'skip' has an invalid value. Expected type 'Boolean!'.",
|
36
36
|
"locations"=>[{"line"=>4, "column"=>30}],
|
37
|
-
"
|
37
|
+
"fields"=>["query getCheese", "cheese", "source", "if"],
|
38
38
|
}
|
39
39
|
assert_includes(errors, directive_error)
|
40
40
|
|
41
41
|
input_object_error = {
|
42
42
|
"message"=>"Argument 'product' on Field 'badSource' has an invalid value. Expected type '[DairyProductInput]'.",
|
43
43
|
"locations"=>[{"line"=>6, "column"=>7}],
|
44
|
-
"
|
44
|
+
"fields"=>["query getCheese", "badSource", "product"],
|
45
45
|
}
|
46
46
|
assert_includes(errors, input_object_error)
|
47
47
|
|
48
48
|
input_object_field_error = {
|
49
49
|
"message"=>"Argument 'source' on InputObject 'DairyProductInput' has an invalid value. Expected type 'DairyAnimal!'.",
|
50
50
|
"locations"=>[{"line"=>6, "column"=>40}],
|
51
|
-
"
|
51
|
+
"fields"=>["query getCheese", "badSource", "product", "source"],
|
52
52
|
}
|
53
53
|
assert_includes(errors, input_object_field_error)
|
54
54
|
|
55
55
|
missing_required_field_error = {
|
56
56
|
"message"=>"Argument 'product' on Field 'missingSource' has an invalid value. Expected type '[DairyProductInput]'.",
|
57
57
|
"locations"=>[{"line"=>7, "column"=>7}],
|
58
|
-
"
|
58
|
+
"fields"=>["query getCheese", "missingSource", "product"],
|
59
59
|
}
|
60
60
|
assert_includes(errors, missing_required_field_error)
|
61
61
|
|
62
62
|
fragment_error = {
|
63
63
|
"message"=>"Argument 'source' on Field 'similarCheese' has an invalid value. Expected type '[DairyAnimal!]!'.",
|
64
64
|
"locations"=>[{"line"=>13, "column"=>7}],
|
65
|
-
"
|
65
|
+
"fields"=>["fragment cheeseFields", "similarCheese", "source"],
|
66
66
|
}
|
67
67
|
assert_includes(errors, fragment_error)
|
68
68
|
end
|
@@ -24,28 +24,28 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
|
|
24
24
|
query_root_error = {
|
25
25
|
"message"=>"Field 'cheese' doesn't accept argument 'silly'",
|
26
26
|
"locations"=>[{"line"=>4, "column"=>7}],
|
27
|
-
"
|
27
|
+
"fields"=>["query getCheese", "cheese", "silly"],
|
28
28
|
}
|
29
29
|
assert_includes(errors, query_root_error)
|
30
30
|
|
31
31
|
input_obj_record = {
|
32
32
|
"message"=>"InputObject 'DairyProductInput' doesn't accept argument 'wacky'",
|
33
33
|
"locations"=>[{"line"=>5, "column"=>29}],
|
34
|
-
"
|
34
|
+
"fields"=>["query getCheese", "searchDairy", "product", "wacky"],
|
35
35
|
}
|
36
36
|
assert_includes(errors, input_obj_record)
|
37
37
|
|
38
38
|
fragment_error = {
|
39
39
|
"message"=>"Field 'similarCheese' doesn't accept argument 'nonsense'",
|
40
40
|
"locations"=>[{"line"=>9, "column"=>7}],
|
41
|
-
"
|
41
|
+
"fields"=>["fragment cheeseFields", "similarCheese", "nonsense"],
|
42
42
|
}
|
43
43
|
assert_includes(errors, fragment_error)
|
44
44
|
|
45
45
|
directive_error = {
|
46
46
|
"message"=>"Directive 'skip' doesn't accept argument 'something'",
|
47
47
|
"locations"=>[{"line"=>10, "column"=>10}],
|
48
|
-
"
|
48
|
+
"fields"=>["fragment cheeseFields", "id", "something"],
|
49
49
|
}
|
50
50
|
assert_includes(errors, directive_error)
|
51
51
|
end
|
@@ -23,11 +23,11 @@ describe GraphQL::StaticValidation::DirectivesAreDefined do
|
|
23
23
|
{
|
24
24
|
"message"=>"Directive @nonsense is not defined",
|
25
25
|
"locations"=>[{"line"=>5, "column"=>16}],
|
26
|
-
"
|
26
|
+
"fields"=>["query getCheese", "okCheese", "source"],
|
27
27
|
}, {
|
28
28
|
"message"=>"Directive @moreNonsense is not defined",
|
29
29
|
"locations"=>[{"line"=>7, "column"=>18}],
|
30
|
-
"
|
30
|
+
"fields"=>["query getCheese", "okCheese", "... on Cheese", "flavor"],
|
31
31
|
}
|
32
32
|
]
|
33
33
|
assert_equal(expected, errors)
|
@@ -27,12 +27,12 @@ describe GraphQL::StaticValidation::DirectivesAreInValidLocations do
|
|
27
27
|
{
|
28
28
|
"message"=> "'@skip' can't be applied to queries (allowed: fields, fragment spreads, inline fragments)",
|
29
29
|
"locations"=>[{"line"=>2, "column"=>21}],
|
30
|
-
"
|
30
|
+
"fields"=>["query getCheese"],
|
31
31
|
},
|
32
32
|
{
|
33
33
|
"message"=>"'@skip' can't be applied to fragment definitions (allowed: fields, fragment spreads, inline fragments)",
|
34
34
|
"locations"=>[{"line"=>12, "column"=>33}],
|
35
|
-
"
|
35
|
+
"fields"=>["fragment whatever"],
|
36
36
|
},
|
37
37
|
]
|
38
38
|
assert_equal(expected, errors)
|
@@ -34,7 +34,7 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
34
34
|
{
|
35
35
|
"message"=>"Field 'notDefinedField' doesn't exist on type 'Query'",
|
36
36
|
"locations"=>[{"line"=>1, "column"=>18}],
|
37
|
-
"
|
37
|
+
"fields"=>["query getStuff", "notDefinedField"],
|
38
38
|
}
|
39
39
|
]
|
40
40
|
assert_equal(expected_errors, errors)
|
@@ -49,7 +49,7 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
49
49
|
{
|
50
50
|
"message"=>"Field 'amountThatILikeIt' doesn't exist on type 'Edible'",
|
51
51
|
"locations"=>[{"line"=>1, "column"=>35}],
|
52
|
-
"
|
52
|
+
"fields"=>["query getStuff", "favoriteEdible", "amountThatILikeIt"],
|
53
53
|
}
|
54
54
|
]
|
55
55
|
assert_equal(expected_errors, errors)
|
@@ -71,7 +71,7 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
71
71
|
"locations"=>[
|
72
72
|
{"line"=>3, "column"=>7}
|
73
73
|
],
|
74
|
-
"
|
74
|
+
"fields"=>["fragment dbFields", "source"],
|
75
75
|
}
|
76
76
|
]
|
77
77
|
assert_equal(expected_errors, errors)
|
@@ -19,14 +19,14 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
|
|
19
19
|
illegal_selection_error = {
|
20
20
|
"message"=>"Selections can't be made on scalars (field 'id' returns Int but has selections [something, someFields])",
|
21
21
|
"locations"=>[{"line"=>5, "column"=>47}],
|
22
|
-
"
|
22
|
+
"fields"=>["query getCheese", "illegalSelectionCheese", "id"],
|
23
23
|
}
|
24
24
|
assert_includes(errors, illegal_selection_error, "finds illegal selections on scalarss")
|
25
25
|
|
26
26
|
selection_required_error = {
|
27
27
|
"message"=>"Objects must have selections (field 'cheese' returns Cheese but has no selections)",
|
28
28
|
"locations"=>[{"line"=>4, "column"=>7}],
|
29
|
-
"
|
29
|
+
"fields"=>["query getCheese", "missingFieldsCheese"],
|
30
30
|
}
|
31
31
|
assert_includes(errors, selection_required_error, "finds objects without selections")
|
32
32
|
end
|
@@ -32,17 +32,17 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
|
32
32
|
{
|
33
33
|
"message"=>"Fragment on Milk can't be spread inside Cheese",
|
34
34
|
"locations"=>[{"line"=>6, "column"=>9}],
|
35
|
-
"
|
35
|
+
"fields"=>["query getCheese", "cheese", "... on Milk"],
|
36
36
|
},
|
37
37
|
{
|
38
38
|
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
39
39
|
"locations"=>[{"line"=>4, "column"=>9}],
|
40
|
-
"
|
40
|
+
"fields"=>["query getCheese", "cheese", "... milkFields"],
|
41
41
|
},
|
42
42
|
{
|
43
43
|
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
44
44
|
"locations"=>[{"line"=>18, "column"=>7}],
|
45
|
-
"
|
45
|
+
"fields"=>["fragment cheeseFields", "... milkFields"],
|
46
46
|
}
|
47
47
|
]
|
48
48
|
assert_equal(expected, errors)
|