graphql 0.18.15 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/define/assign_global_id_field.rb +1 -2
- data/lib/graphql/directive.rb +41 -7
- data/lib/graphql/directive/deprecated_directive.rb +11 -0
- data/lib/graphql/directive/include_directive.rb +2 -2
- data/lib/graphql/directive/skip_directive.rb +2 -2
- data/lib/graphql/input_object_type.rb +14 -0
- data/lib/graphql/internal_representation/node.rb +8 -4
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/directive_location_enum.rb +3 -2
- data/lib/graphql/introspection/directive_type.rb +12 -7
- data/lib/graphql/introspection/enum_value_type.rb +4 -2
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/field_type.rb +8 -7
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- data/lib/graphql/introspection/input_value_type.rb +8 -10
- data/lib/graphql/introspection/interfaces_field.rb +0 -1
- data/lib/graphql/introspection/of_type_field.rb +0 -1
- data/lib/graphql/introspection/possible_types_field.rb +0 -1
- data/lib/graphql/introspection/schema_type.rb +11 -9
- data/lib/graphql/introspection/type_kind_enum.rb +3 -3
- data/lib/graphql/introspection/type_type.rb +9 -6
- data/lib/graphql/language/generation.rb +4 -1
- data/lib/graphql/language/lexer.rb +353 -316
- data/lib/graphql/language/lexer.rl +8 -6
- data/lib/graphql/language/nodes.rb +12 -0
- data/lib/graphql/language/parser.rb +553 -501
- data/lib/graphql/language/parser.y +26 -16
- data/lib/graphql/language/parser_tests.rb +20 -1
- data/lib/graphql/list_type.rb +5 -1
- data/lib/graphql/non_null_type.rb +4 -0
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/relay.rb +1 -1
- data/lib/graphql/relay/global_id_resolve.rb +3 -5
- data/lib/graphql/relay/node.rb +34 -0
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema.rb +43 -15
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/printer.rb +50 -8
- data/lib/graphql/schema/unique_within_type.rb +28 -0
- data/lib/graphql/schema/validation.rb +10 -3
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +9 -1
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -2
- data/lib/graphql/type_kinds.rb +12 -12
- data/lib/graphql/version.rb +1 -1
- data/readme.md +6 -5
- data/spec/graphql/argument_spec.rb +1 -1
- data/spec/graphql/execution_error_spec.rb +53 -0
- data/spec/graphql/introspection/directive_type_spec.rb +10 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +23 -0
- data/spec/graphql/language/generation_spec.rb +4 -0
- data/spec/graphql/query/executor_spec.rb +2 -2
- data/spec/graphql/relay/mutation_spec.rb +1 -1
- data/spec/graphql/relay/node_spec.rb +87 -0
- data/spec/graphql/schema/catchall_middleware_spec.rb +1 -1
- data/spec/graphql/schema/loader_spec.rb +37 -4
- data/spec/graphql/schema/printer_spec.rb +30 -7
- data/spec/graphql/schema/unique_within_type_spec.rb +27 -0
- data/spec/graphql/schema/validation_spec.rb +7 -11
- data/spec/graphql/schema_spec.rb +32 -2
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +14 -15
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +10 -10
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -5
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +3 -5
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +7 -11
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -4
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +10 -13
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +3 -5
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -6
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +7 -7
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -4
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +3 -6
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -4
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +12 -14
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +7 -9
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +20 -22
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +27 -23
- data/spec/spec_helper.rb +1 -0
- data/spec/support/dairy_app.rb +2 -2
- data/spec/support/star_wars_schema.rb +15 -18
- data/spec/support/static_validation_helpers.rb +27 -0
- metadata +25 -5
- data/lib/graphql/relay/global_node_identification.rb +0 -138
- data/spec/graphql/relay/global_node_identification_spec.rb +0 -153
@@ -1,15 +1,17 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FieldsWillMerge do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {"
|
5
|
-
query getCheese($sourceVar: DairyAnimal!) {
|
7
|
+
query getCheese($sourceVar: [DairyAnimal!] = [YAK]) {
|
6
8
|
cheese(id: 1) {
|
7
9
|
id,
|
8
|
-
nickname:
|
10
|
+
nickname: flavor,
|
9
11
|
nickname: fatContent,
|
10
12
|
fatContent
|
11
13
|
differentLevel: fatContent
|
12
|
-
similarCheese(source: $sourceVar)
|
14
|
+
similarCheese(source: $sourceVar) { __typename }
|
13
15
|
|
14
16
|
similarCow: similarCheese(source: COW) {
|
15
17
|
similarCowSource: source,
|
@@ -17,27 +19,22 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
17
19
|
}
|
18
20
|
...cheeseFields
|
19
21
|
... on Cheese {
|
20
|
-
fatContent:
|
21
|
-
similarCheese(source: SHEEP)
|
22
|
+
fatContent: flavor
|
23
|
+
similarCheese(source: SHEEP) { __typename }
|
22
24
|
}
|
23
25
|
}
|
24
26
|
}
|
25
27
|
fragment cheeseFields on Cheese {
|
26
28
|
fatContent,
|
27
29
|
similarCow: similarCheese(source: COW) { similarCowSource: id, id }
|
28
|
-
id @
|
30
|
+
id @skip(if: true)
|
29
31
|
}
|
30
32
|
"}
|
31
33
|
|
32
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsWillMerge]) }
|
33
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
34
|
-
let(:errors) { validator.validate(query)[:errors] }
|
35
|
-
let(:error_messages) { errors.map { |e| e["message" ] }}
|
36
|
-
|
37
34
|
it "finds field naming conflicts" do
|
38
35
|
expected_errors = [
|
39
|
-
"Field 'nickname' has a field conflict:
|
40
|
-
"Field 'fatContent' has a field conflict: fatContent or
|
36
|
+
"Field 'nickname' has a field conflict: flavor or fatContent?", # alias conflict in query
|
37
|
+
"Field 'fatContent' has a field conflict: fatContent or flavor?", # alias/name conflict in query and fragment
|
41
38
|
"Field 'similarCheese' has an argument conflict: {\"source\":\"sourceVar\"} or {\"source\":\"SHEEP\"}?", # different arguments
|
42
39
|
"Field 'similarCowSource' has a field conflict: source or id?", # nested conflict
|
43
40
|
]
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
query getCheese {
|
6
8
|
cheese(id: 1) {
|
@@ -9,7 +11,7 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
|
9
11
|
... on Milk { fatContent }
|
10
12
|
... on AnimalProduct { source }
|
11
13
|
... on DairyProduct {
|
12
|
-
fatContent
|
14
|
+
... on Cheese { fatContent }
|
13
15
|
... on Edible { fatContent }
|
14
16
|
}
|
15
17
|
}
|
@@ -22,10 +24,6 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
|
22
24
|
}
|
23
25
|
|}
|
24
26
|
|
25
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentSpreadsArePossible]) }
|
26
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
27
|
-
let(:errors) { validator.validate(query)[:errors] }
|
28
|
-
|
29
27
|
it "doesnt allow spreads where they'll never apply" do
|
30
28
|
# TODO: more negative, abstract examples here, add stuff to the schema
|
31
29
|
expected = [
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentTypesExist do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {"
|
5
7
|
query getCheese {
|
6
8
|
cheese(id: 1) {
|
@@ -19,10 +21,6 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
|
|
19
21
|
}
|
20
22
|
"}
|
21
23
|
|
22
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentTypesExist]) }
|
23
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
24
|
-
let(:errors) { validator.validate(query)[:errors] }
|
25
|
-
|
26
24
|
it "finds non-existent types on fragments" do
|
27
25
|
assert_equal(2, errors.length)
|
28
26
|
inline_fragment_error = {
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentsAreFinite do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
query getCheese {
|
6
8
|
cheese(id: 1) {
|
7
9
|
... idField
|
8
10
|
... sourceField
|
9
|
-
similarCheese {
|
11
|
+
similarCheese(source: SHEEP) {
|
10
12
|
... flavorField
|
11
13
|
}
|
12
14
|
}
|
@@ -19,7 +21,7 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
|
|
19
21
|
}
|
20
22
|
fragment flavorField on Cheese {
|
21
23
|
flavor,
|
22
|
-
similarCheese {
|
24
|
+
similarCheese(source: SHEEP) {
|
23
25
|
... on Cheese {
|
24
26
|
... sourceField
|
25
27
|
}
|
@@ -30,10 +32,6 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
|
|
30
32
|
}
|
31
33
|
|}
|
32
34
|
|
33
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreFinite]) }
|
34
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
35
|
-
let(:errors) { validator.validate(query)[:errors] }
|
36
|
-
|
37
35
|
it "doesnt allow infinite loops" do
|
38
36
|
expected = [
|
39
37
|
{
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentTypesExist do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {"
|
5
7
|
fragment on Cheese {
|
6
8
|
id
|
@@ -8,10 +10,6 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
|
|
8
10
|
}
|
9
11
|
"}
|
10
12
|
|
11
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreNamed]) }
|
12
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
13
|
-
let(:errors) { validator.validate(query)[:errors] }
|
14
|
-
|
15
13
|
it "finds non-existent types on fragments" do
|
16
14
|
assert_equal(1, errors.length)
|
17
15
|
fragment_def_error = {
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
query getCheese {
|
6
8
|
cheese(id: 1) {
|
@@ -12,7 +14,9 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
|
12
14
|
}
|
13
15
|
... intFields
|
14
16
|
... on DairyProduct {
|
15
|
-
|
17
|
+
... on Cheese {
|
18
|
+
flavor
|
19
|
+
}
|
16
20
|
}
|
17
21
|
... on DairyProductInput {
|
18
22
|
something
|
@@ -25,10 +29,6 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
|
25
29
|
}
|
26
30
|
|}
|
27
31
|
|
28
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreOnCompositeTypes]) }
|
29
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
30
|
-
let(:errors) { validator.validate(query)[:errors] }
|
31
|
-
|
32
32
|
it "requires Object/Union/Interface fragment types" do
|
33
33
|
expected = [
|
34
34
|
{
|
@@ -38,12 +38,12 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
|
38
38
|
},
|
39
39
|
{
|
40
40
|
"message"=>"Invalid fragment on type DairyProductInput (must be Union, Interface or Object)",
|
41
|
-
"locations"=>[{"line"=>
|
41
|
+
"locations"=>[{"line"=>16, "column"=>9}],
|
42
42
|
"fields"=>["query getCheese", "cheese", "... on DairyProductInput"],
|
43
43
|
},
|
44
44
|
{
|
45
45
|
"message"=>"Invalid fragment on type Int (must be Union, Interface or Object)",
|
46
|
-
"locations"=>[{"line"=>
|
46
|
+
"locations"=>[{"line"=>22, "column"=>5}],
|
47
47
|
"fields"=>["fragment intFields"],
|
48
48
|
},
|
49
49
|
]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::FragmentsAreUsed do
|
4
|
+
include StaticValidationHelpers
|
4
5
|
let(:query_string) {"
|
5
6
|
query getCheese {
|
6
7
|
name,
|
@@ -11,10 +12,6 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
|
|
11
12
|
fragment unusedFields on Cheese { is, not, used }
|
12
13
|
"}
|
13
14
|
|
14
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreUsed]) }
|
15
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
16
|
-
let(:errors) { validator.validate(query)[:errors] }
|
17
|
-
|
18
15
|
it "adds errors for unused fragment definitions" do
|
19
16
|
assert_includes(errors, {
|
20
17
|
"message"=>"Fragment unusedFields was defined, but not used",
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::MutationRootExists do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
mutation addBagel {
|
6
8
|
introduceShip(input: {shipName: "Bagel"}) {
|
@@ -23,10 +25,6 @@ describe GraphQL::StaticValidation::MutationRootExists do
|
|
23
25
|
end
|
24
26
|
}
|
25
27
|
|
26
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: schema, rules: [GraphQL::StaticValidation::MutationRootExists]) }
|
27
|
-
let(:query) { GraphQL::Query.new(schema, query_string) }
|
28
|
-
let(:errors) { validator.validate(query)[:errors] }
|
29
|
-
|
30
28
|
it "errors when a mutation is performed on a schema without a mutation root" do
|
31
29
|
assert_equal(1, errors.length)
|
32
30
|
missing_mutation_root_error = {
|
@@ -1,23 +1,20 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
|
4
|
+
include StaticValidationHelpers
|
4
5
|
let(:query_string) {"
|
5
6
|
query getCheese {
|
6
|
-
cheese(id: 1) {
|
7
|
+
okCheese: cheese(id: 1) { ...cheeseFields }
|
7
8
|
cheese { source }
|
8
9
|
}
|
9
10
|
|
10
11
|
fragment cheeseFields on Cheese {
|
11
|
-
similarCheese(
|
12
|
+
similarCheese() { __typename }
|
12
13
|
flavor @include(if: true)
|
13
14
|
id @skip
|
14
15
|
}
|
15
16
|
"}
|
16
17
|
|
17
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::RequiredArgumentsArePresent]) }
|
18
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
19
|
-
let(:errors) { validator.validate(query)[:errors] }
|
20
|
-
|
21
18
|
it "finds undefined arguments to fields and directives" do
|
22
19
|
assert_equal(3, errors.length)
|
23
20
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::SubscriptionRootExists do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
subscription {
|
6
8
|
test
|
@@ -18,10 +20,6 @@ describe GraphQL::StaticValidation::SubscriptionRootExists do
|
|
18
20
|
end
|
19
21
|
}
|
20
22
|
|
21
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: schema, rules: [GraphQL::StaticValidation::SubscriptionRootExists]) }
|
22
|
-
let(:query) { GraphQL::Query.new(schema, query_string) }
|
23
|
-
let(:errors) { validator.validate(query)[:errors] }
|
24
|
-
|
25
23
|
it "errors when a subscription is performed on a schema without a subscription root" do
|
26
24
|
assert_equal(1, errors.length)
|
27
25
|
missing_subscription_root_error = {
|
data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb
CHANGED
@@ -1,45 +1,43 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {%|
|
5
7
|
query getCheese(
|
6
8
|
$id: Int = 1,
|
7
9
|
$int: Int = 3.4e24, # can be coerced
|
8
10
|
$str: String!,
|
9
|
-
$badFloat: Float = true,
|
10
11
|
$badInt: Int = "abc",
|
11
12
|
$input: DairyProductInput = {source: YAK, fatContent: 1},
|
12
13
|
$badInput: DairyProductInput = {source: YAK, fatContent: true},
|
13
14
|
$nonNull: Int! = 1,
|
14
15
|
) {
|
15
|
-
cheese(id: $id) { source }
|
16
|
+
cheese1: cheese(id: $id) { source }
|
17
|
+
cheese4: cheese(id: $int) { source }
|
18
|
+
cheese2: cheese(id: $badInt) { source }
|
19
|
+
cheese3: cheese(id: $nonNull) { source }
|
20
|
+
search1: searchDairy(product: [$input]) { __typename }
|
21
|
+
search2: searchDairy(product: [$badInput]) { __typename }
|
22
|
+
__type(name: $str) { name }
|
16
23
|
}
|
17
24
|
|}
|
18
25
|
|
19
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped]) }
|
20
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
21
|
-
let(:errors) { validator.validate(query)[:errors] }
|
22
|
-
|
23
26
|
it "finds default values that don't match their types" do
|
24
27
|
expected = [
|
25
|
-
{
|
26
|
-
"message"=>"Default value for $badFloat doesn't match type Float",
|
27
|
-
"locations"=>[{"line"=>6, "column"=>7}],
|
28
|
-
"fields"=>["query getCheese"],
|
29
|
-
},
|
30
28
|
{
|
31
29
|
"message"=>"Default value for $badInt doesn't match type Int",
|
32
|
-
"locations"=>[{"line"=>
|
30
|
+
"locations"=>[{"line"=>6, "column"=>7}],
|
33
31
|
"fields"=>["query getCheese"],
|
34
32
|
},
|
35
33
|
{
|
36
34
|
"message"=>"Default value for $badInput doesn't match type DairyProductInput",
|
37
|
-
"locations"=>[{"line"=>
|
35
|
+
"locations"=>[{"line"=>8, "column"=>7}],
|
38
36
|
"fields"=>["query getCheese"],
|
39
37
|
},
|
40
38
|
{
|
41
39
|
"message"=>"Non-null variable $nonNull can't have a default value",
|
42
|
-
"locations"=>[{"line"=>
|
40
|
+
"locations"=>[{"line"=>9, "column"=>7}],
|
43
41
|
"fields"=>["query getCheese"],
|
44
42
|
}
|
45
43
|
]
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {'
|
5
7
|
query getCheese(
|
6
8
|
$goodInt: Int = 1,
|
@@ -17,11 +19,11 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
|
|
17
19
|
badCheese: cheese(id: $badInt) { source }
|
18
20
|
badStrCheese: cheese(id: $badStr) { source }
|
19
21
|
cheese(id: 1) {
|
20
|
-
similarCheese(source: $goodAnimals)
|
21
|
-
other: similarCheese(source: $badAnimals)
|
22
|
-
tooDeep: similarCheese(source: $deepAnimals)
|
23
|
-
nullableCheese(source: $goodAnimals)
|
24
|
-
deeplyNullableCheese(source: $deepAnimals)
|
22
|
+
similarCheese(source: $goodAnimals) { source }
|
23
|
+
other: similarCheese(source: $badAnimals) { source }
|
24
|
+
tooDeep: similarCheese(source: $deepAnimals) { source }
|
25
|
+
nullableCheese(source: $goodAnimals) { source }
|
26
|
+
deeplyNullableCheese(source: $deepAnimals) { source }
|
25
27
|
}
|
26
28
|
|
27
29
|
milk(id: 1) {
|
@@ -34,10 +36,6 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
|
|
34
36
|
}
|
35
37
|
'}
|
36
38
|
|
37
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableUsagesAreAllowed]) }
|
38
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
39
|
-
let(:errors) { validator.validate(query)[:errors] }
|
40
|
-
|
41
39
|
it "finds variables used as arguments but don't match the argument's type" do
|
42
40
|
assert_equal(4, errors.length)
|
43
41
|
expected = [
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::VariablesAreInputTypes do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {'
|
5
7
|
query getCheese(
|
6
8
|
$id: Int = 1,
|
@@ -10,31 +12,27 @@ describe GraphQL::StaticValidation::VariablesAreInputTypes do
|
|
10
12
|
$objects: [Cheese]!,
|
11
13
|
) {
|
12
14
|
cheese(id: $id) { source }
|
15
|
+
__type(name: $str) { name }
|
13
16
|
}
|
14
17
|
'}
|
15
18
|
|
16
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreInputTypes]) }
|
17
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
18
|
-
let(:errors) { validator.validate(query)[:errors] }
|
19
|
-
|
20
19
|
it "finds variables whose types are invalid" do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
assert_equal(expected, errors)
|
20
|
+
assert_includes(errors, {
|
21
|
+
"message"=>"AnimalProduct isn't a valid input type (on $interface)",
|
22
|
+
"locations"=>[{"line"=>5, "column"=>7}],
|
23
|
+
"fields"=>["query getCheese"],
|
24
|
+
})
|
25
|
+
|
26
|
+
assert_includes(errors, {
|
27
|
+
"message"=>"Milk isn't a valid input type (on $object)",
|
28
|
+
"locations"=>[{"line"=>6, "column"=>7}],
|
29
|
+
"fields"=>["query getCheese"],
|
30
|
+
})
|
31
|
+
|
32
|
+
assert_includes(errors, {
|
33
|
+
"message"=>"Cheese isn't a valid input type (on $objects)",
|
34
|
+
"locations"=>[{"line"=>7, "column"=>7}],
|
35
|
+
"fields"=>["query getCheese"],
|
36
|
+
})
|
39
37
|
end
|
40
38
|
end
|
@@ -1,38 +1,41 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
|
4
|
+
include StaticValidationHelpers
|
5
|
+
|
4
6
|
let(:query_string) {'
|
5
7
|
query getCheese(
|
6
|
-
$usedVar: Int
|
7
|
-
$usedInnerVar:
|
8
|
-
$usedInlineFragmentVar:
|
9
|
-
$usedFragmentVar: Int
|
10
|
-
$notUsedVar:
|
8
|
+
$usedVar: Int!,
|
9
|
+
$usedInnerVar: [DairyAnimal!]!,
|
10
|
+
$usedInlineFragmentVar: Int!,
|
11
|
+
$usedFragmentVar: Int!,
|
12
|
+
$notUsedVar: Int!,
|
11
13
|
) {
|
12
|
-
cheese(id: $usedVar) {
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
c1: cheese(id: $usedVar) {
|
15
|
+
__typename
|
16
|
+
}
|
17
|
+
... on Query {
|
18
|
+
c2: cheese(id: $usedInlineFragmentVar) {
|
19
|
+
similarCheese(source: $usedInnerVar) { __typename }
|
17
20
|
}
|
18
|
-
|
21
|
+
|
19
22
|
}
|
23
|
+
|
24
|
+
c3: cheese(id: $undefinedVar) { __typename }
|
25
|
+
|
26
|
+
... outerCheeseFields
|
20
27
|
}
|
21
28
|
|
22
|
-
fragment outerCheeseFields on
|
29
|
+
fragment outerCheeseFields on Query {
|
23
30
|
... innerCheeseFields
|
24
31
|
}
|
25
32
|
|
26
|
-
fragment innerCheeseFields on
|
27
|
-
|
28
|
-
|
33
|
+
fragment innerCheeseFields on Query {
|
34
|
+
c4: cheese(id: $undefinedFragmentVar) { __typename }
|
35
|
+
c5: cheese(id: $usedFragmentVar) { __typename }
|
29
36
|
}
|
30
37
|
'}
|
31
38
|
|
32
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreUsedAndDefined]) }
|
33
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
|
34
|
-
let(:errors) { validator.validate(query)[:errors] }
|
35
|
-
|
36
39
|
it "finds variables which are used-but-not-defined or defined-but-not-used" do
|
37
40
|
expected = [
|
38
41
|
{
|
@@ -42,15 +45,16 @@ describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
|
|
42
45
|
},
|
43
46
|
{
|
44
47
|
"message"=>"Variable $undefinedVar is used by getCheese but not declared",
|
45
|
-
"locations"=>[{"line"=>
|
46
|
-
"fields"=>["query getCheese", "
|
48
|
+
"locations"=>[{"line"=>19, "column"=>22}],
|
49
|
+
"fields"=>["query getCheese", "c3", "id"],
|
47
50
|
},
|
48
51
|
{
|
49
52
|
"message"=>"Variable $undefinedFragmentVar is used by innerCheeseFields but not declared",
|
50
|
-
"locations"=>[{"line"=>
|
51
|
-
"fields"=>["fragment innerCheeseFields", "
|
53
|
+
"locations"=>[{"line"=>29, "column"=>22}],
|
54
|
+
"fields"=>["fragment innerCheeseFields", "c4", "id"],
|
52
55
|
},
|
53
56
|
]
|
57
|
+
|
54
58
|
assert_equal(expected, errors)
|
55
59
|
end
|
56
60
|
end
|