graphql 0.18.15 → 0.19.0
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/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
|