graphql 0.18.14 → 0.18.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|