graphql 1.9.0.pre1 → 1.9.0.pre2
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.rb +5 -1
- data/lib/graphql/analysis/ast/analyzer.rb +1 -1
- data/lib/graphql/analysis/ast/visitor.rb +6 -1
- data/lib/graphql/backwards_compatibility.rb +1 -1
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/directive.rb +13 -1
- data/lib/graphql/directive/include_directive.rb +1 -7
- data/lib/graphql/directive/skip_directive.rb +1 -8
- data/lib/graphql/execution/interpreter.rb +23 -13
- data/lib/graphql/execution/interpreter/resolve.rb +56 -0
- data/lib/graphql/execution/interpreter/runtime.rb +174 -74
- data/lib/graphql/execution/lazy.rb +7 -1
- data/lib/graphql/execution/lookahead.rb +71 -6
- data/lib/graphql/execution_error.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +5 -1
- data/lib/graphql/introspection/type_type.rb +4 -4
- data/lib/graphql/language.rb +0 -1
- data/lib/graphql/language/block_string.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +1 -1
- data/lib/graphql/language/lexer.rb +55 -36
- data/lib/graphql/language/lexer.rl +8 -3
- data/lib/graphql/language/nodes.rb +27 -4
- data/lib/graphql/language/parser.rb +55 -55
- data/lib/graphql/language/parser.y +11 -11
- data/lib/graphql/language/printer.rb +1 -1
- data/lib/graphql/language/visitor.rb +22 -13
- data/lib/graphql/literal_validation_error.rb +6 -0
- data/lib/graphql/query.rb +13 -0
- data/lib/graphql/query/arguments.rb +2 -1
- data/lib/graphql/query/context.rb +3 -10
- data/lib/graphql/query/executor.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/relay/connection_resolve.rb +1 -1
- data/lib/graphql/relay/relation_connection.rb +1 -1
- data/lib/graphql/schema.rb +81 -11
- data/lib/graphql/schema/argument.rb +1 -1
- data/lib/graphql/schema/build_from_definition.rb +2 -4
- data/lib/graphql/schema/directive.rb +103 -0
- data/lib/graphql/schema/directive/feature.rb +66 -0
- data/lib/graphql/schema/directive/include.rb +25 -0
- data/lib/graphql/schema/directive/skip.rb +25 -0
- data/lib/graphql/schema/directive/transform.rb +48 -0
- data/lib/graphql/schema/enum_value.rb +2 -2
- data/lib/graphql/schema/field.rb +63 -17
- data/lib/graphql/schema/input_object.rb +1 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +4 -2
- data/lib/graphql/schema/member/build_type.rb +33 -1
- data/lib/graphql/schema/member/has_fields.rb +8 -73
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -1
- data/lib/graphql/schema/resolver.rb +1 -1
- data/lib/graphql/static_validation.rb +2 -1
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +25 -10
- data/lib/graphql/static_validation/definition_dependencies.rb +3 -3
- data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
- data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
- data/lib/graphql/static_validation/literal_validator.rb +54 -11
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +34 -5
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +2 -2
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +7 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +5 -1
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +11 -2
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +11 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +14 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +24 -6
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +5 -1
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -1
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +5 -1
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -1
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +4 -1
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +5 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +13 -3
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +4 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +2 -2
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +9 -2
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +7 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +4 -1
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +4 -3
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +20 -6
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +5 -1
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +8 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +12 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +18 -2
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/validator.rb +24 -14
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -2
- data/lib/graphql/tracing/skylight_tracing.rb +2 -2
- data/lib/graphql/unauthorized_field_error.rb +23 -0
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/ast_spec.rb +40 -0
- data/spec/graphql/authorization_spec.rb +93 -20
- data/spec/graphql/base_type_spec.rb +3 -1
- data/spec/graphql/execution/interpreter_spec.rb +127 -4
- data/spec/graphql/execution/lazy_spec.rb +49 -0
- data/spec/graphql/execution/lookahead_spec.rb +113 -21
- data/spec/graphql/execution/multiplex_spec.rb +2 -1
- data/spec/graphql/introspection/type_type_spec.rb +1 -1
- data/spec/graphql/language/lexer_spec.rb +72 -3
- data/spec/graphql/language/printer_spec.rb +18 -6
- data/spec/graphql/query/arguments_spec.rb +21 -0
- data/spec/graphql/query/context_spec.rb +10 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
- data/spec/graphql/schema/directive/feature_spec.rb +81 -0
- data/spec/graphql/schema/directive/transform_spec.rb +39 -0
- data/spec/graphql/schema/enum_spec.rb +5 -3
- data/spec/graphql/schema/field_extension_spec.rb +3 -3
- data/spec/graphql/schema/field_spec.rb +19 -0
- data/spec/graphql/schema/input_object_spec.rb +81 -0
- data/spec/graphql/schema/member/build_type_spec.rb +46 -0
- data/spec/graphql/schema/member/scoped_spec.rb +3 -3
- data/spec/graphql/schema/printer_spec.rb +244 -96
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +26 -0
- data/spec/graphql/schema/resolver_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +35 -11
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +212 -72
- data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
- data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
- data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +6 -3
- data/spec/graphql/static_validation/validator_spec.rb +6 -4
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +10 -0
- data/spec/graphql/tracing/skylight_tracing_spec.rb +10 -0
- data/spec/graphql/types/iso_8601_date_time_spec.rb +1 -2
- data/spec/integration/mongoid/star_trek/schema.rb +5 -5
- data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +37 -8
- data/spec/integration/rails/graphql/schema_spec.rb +2 -2
- data/spec/integration/rails/spec_helper.rb +10 -0
- data/spec/integration/tmp/app/graphql/types/bird_type.rb +7 -0
- data/spec/integration/tmp/dummy/Gemfile +45 -0
- data/spec/integration/tmp/dummy/README.rdoc +28 -0
- data/spec/integration/tmp/dummy/Rakefile +6 -0
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +43 -0
- data/spec/integration/tmp/dummy/app/graphql/dummy_schema.rb +34 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_enum.rb +4 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_input_object.rb +4 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_interface.rb +5 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_object.rb +4 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_scalar.rb +4 -0
- data/spec/integration/tmp/dummy/app/graphql/types/base_union.rb +4 -0
- data/spec/integration/tmp/dummy/app/graphql/types/mutation_type.rb +10 -0
- data/spec/integration/tmp/dummy/app/graphql/types/query_type.rb +15 -0
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/integration/tmp/dummy/bin/bundle +3 -0
- data/spec/integration/tmp/dummy/bin/rails +4 -0
- data/spec/integration/tmp/dummy/bin/rake +4 -0
- data/spec/integration/tmp/dummy/bin/setup +29 -0
- data/spec/integration/tmp/dummy/config.ru +4 -0
- data/spec/integration/tmp/dummy/config/application.rb +32 -0
- data/spec/integration/tmp/dummy/config/boot.rb +3 -0
- data/spec/integration/tmp/dummy/config/environment.rb +5 -0
- data/spec/integration/tmp/dummy/config/environments/development.rb +38 -0
- data/spec/integration/tmp/dummy/config/environments/production.rb +76 -0
- data/spec/integration/tmp/dummy/config/environments/test.rb +42 -0
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +11 -0
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +16 -0
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +3 -0
- data/spec/integration/tmp/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/spec/integration/tmp/dummy/config/locales/en.yml +23 -0
- data/spec/integration/tmp/dummy/config/routes.rb +61 -0
- data/spec/integration/tmp/dummy/config/secrets.yml +22 -0
- data/spec/integration/tmp/dummy/db/seeds.rb +7 -0
- data/spec/integration/tmp/dummy/public/404.html +67 -0
- data/spec/integration/tmp/dummy/public/422.html +67 -0
- data/spec/integration/tmp/dummy/public/500.html +66 -0
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +5 -0
- data/spec/support/dummy/schema.rb +2 -2
- data/spec/support/error_bubbling_helpers.rb +23 -0
- data/spec/support/jazz.rb +53 -6
- data/spec/support/lazy_helpers.rb +26 -8
- data/spec/support/new_relic.rb +3 -0
- data/spec/support/skylight.rb +3 -0
- data/spec/support/star_wars/schema.rb +13 -9
- data/spec/support/static_validation_helpers.rb +3 -1
- metadata +145 -22
- data/lib/graphql/language/comments.rb +0 -45
- data/spec/graphql/schema/member/has_fields_spec.rb +0 -132
- data/spec/integration/tmp/app/graphql/types/family_type.rb +0 -9
@@ -19,7 +19,7 @@ describe GraphQL::StaticValidation::ArgumentNamesAreUnique do
|
|
19
19
|
error = errors.first
|
20
20
|
assert_equal 'There can be only one argument named "id"', error["message"]
|
21
21
|
assert_equal [{ "line" => 2, "column" => 18}, { "line" => 2, "column" => 25 }], error["locations"]
|
22
|
-
assert_equal ["query GetStuff", "c1"], error["
|
22
|
+
assert_equal ["query GetStuff", "c1"], error["path"]
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -38,7 +38,7 @@ describe GraphQL::StaticValidation::ArgumentNamesAreUnique do
|
|
38
38
|
error = errors.first
|
39
39
|
assert_equal 'There can be only one argument named "if"', error["message"]
|
40
40
|
assert_equal [{ "line" => 2, "column" => 34}, { "line" => 2, "column" => 44 }], error["locations"]
|
41
|
-
assert_equal ["query GetStuff", "c1"], error["
|
41
|
+
assert_equal ["query GetStuff", "c1"], error["path"]
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -3,6 +3,7 @@ require "spec_helper"
|
|
3
3
|
|
4
4
|
describe GraphQL::StaticValidation::ArgumentsAreDefined do
|
5
5
|
include StaticValidationHelpers
|
6
|
+
include ErrorBubblingHelpers
|
6
7
|
|
7
8
|
let(:query_string) {"
|
8
9
|
query getCheese {
|
@@ -17,38 +18,79 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
|
|
17
18
|
}
|
18
19
|
"}
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
describe "finds undefined arguments to fields and directives" do
|
22
|
+
it "works with error bubbling" do
|
23
|
+
with_error_bubbling(Dummy::Schema) do
|
24
|
+
# There's an extra error here, the unexpected argument on "DairyProductInput"
|
25
|
+
# triggers _another_ error that the field expected a different type
|
26
|
+
assert_equal(6, errors.length)
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
query_root_error = {
|
29
|
+
"message"=>"Field 'cheese' doesn't accept argument 'silly'",
|
30
|
+
"locations"=>[{"line"=>4, "column"=>14}],
|
31
|
+
"path"=>["query getCheese", "cheese", "silly"],
|
32
|
+
"extensions"=>{
|
33
|
+
"code"=>"argumentNotAccepted",
|
34
|
+
"name"=>"cheese",
|
35
|
+
"typeName"=>"Field",
|
36
|
+
"argumentName"=>"silly"
|
37
|
+
},
|
38
|
+
}
|
39
|
+
assert_includes(errors, query_root_error)
|
31
40
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
input_obj_record = {
|
42
|
+
"message"=>"InputObject 'DairyProductInput' doesn't accept argument 'wacky'",
|
43
|
+
"locations"=>[{"line"=>5, "column"=>30}],
|
44
|
+
"path"=>["query getCheese", "searchDairy", "product", "wacky"],
|
45
|
+
"extensions"=>{
|
46
|
+
"code"=>"argumentNotAccepted",
|
47
|
+
"name"=>"DairyProductInput",
|
48
|
+
"typeName"=>"InputObject",
|
49
|
+
"argumentName"=>"wacky"
|
50
|
+
},
|
51
|
+
}
|
52
|
+
assert_includes(errors, input_obj_record)
|
38
53
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
54
|
+
fragment_error = {
|
55
|
+
"message"=>"Field 'similarCheese' doesn't accept argument 'nonsense'",
|
56
|
+
"locations"=>[{"line"=>9, "column"=>36}],
|
57
|
+
"path"=>["fragment cheeseFields", "similarCheese", "nonsense"],
|
58
|
+
"extensions"=>{
|
59
|
+
"code"=>"argumentNotAccepted",
|
60
|
+
"name"=>"similarCheese",
|
61
|
+
"typeName"=>"Field",
|
62
|
+
"argumentName"=>"nonsense",
|
63
|
+
},
|
64
|
+
}
|
65
|
+
assert_includes(errors, fragment_error)
|
45
66
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
67
|
+
directive_error = {
|
68
|
+
"message"=>"Directive 'skip' doesn't accept argument 'something'",
|
69
|
+
"locations"=>[{"line"=>10, "column"=>16}],
|
70
|
+
"path"=>["fragment cheeseFields", "id", "something"],
|
71
|
+
"extensions"=>{
|
72
|
+
"code"=>"argumentNotAccepted",
|
73
|
+
"name"=>"skip",
|
74
|
+
"typeName"=>"Directive",
|
75
|
+
"argumentName"=>"something",
|
76
|
+
},
|
77
|
+
}
|
78
|
+
assert_includes(errors, directive_error)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "works without error bubbling" do
|
83
|
+
without_error_bubbling(Dummy::Schema) do
|
84
|
+
assert_equal(5, errors.length)
|
85
|
+
|
86
|
+
extra_error = {
|
87
|
+
"message"=>"Argument 'product' on Field 'searchDairy' has an invalid value. Expected type '[DairyProductInput]'.",
|
88
|
+
"locations"=>[{"line"=>5, "column"=>7}],
|
89
|
+
"path"=>["query getCheese", "searchDairy", "product"]
|
90
|
+
}
|
91
|
+
refute_includes(errors, extra_error)
|
92
|
+
end
|
93
|
+
end
|
52
94
|
end
|
53
95
|
|
54
96
|
describe "dynamic fields" do
|
@@ -62,7 +104,8 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
|
|
62
104
|
assert_includes(errors, {
|
63
105
|
"message"=>"Field '__type' doesn't accept argument 'somethingInvalid'",
|
64
106
|
"locations"=>[{"line"=>3, "column"=>16}],
|
65
|
-
"
|
107
|
+
"path"=>["query", "__type", "somethingInvalid"],
|
108
|
+
"extensions"=>{"code"=>"argumentNotAccepted", "name"=>"__type", "typeName"=>"Field", "argumentName"=>"somethingInvalid"}
|
66
109
|
})
|
67
110
|
end
|
68
111
|
end
|
@@ -20,11 +20,13 @@ describe GraphQL::StaticValidation::DirectivesAreDefined do
|
|
20
20
|
{
|
21
21
|
"message"=>"Directive @nonsense is not defined",
|
22
22
|
"locations"=>[{"line"=>5, "column"=>16}],
|
23
|
-
"
|
23
|
+
"path"=>["query getCheese", "okCheese", "source"],
|
24
|
+
"extensions"=>{"code"=>"undefinedDirective", "directiveName"=>"nonsense"}
|
24
25
|
}, {
|
25
26
|
"message"=>"Directive @moreNonsense is not defined",
|
26
27
|
"locations"=>[{"line"=>7, "column"=>18}],
|
27
|
-
"
|
28
|
+
"path"=>["query getCheese", "okCheese", "... on Cheese", "flavor"],
|
29
|
+
"extensions"=>{"code"=>"undefinedDirective", "directiveName"=>"moreNonsense"}
|
28
30
|
}
|
29
31
|
]
|
30
32
|
assert_equal(expected, errors)
|
@@ -26,12 +26,14 @@ describe GraphQL::StaticValidation::DirectivesAreInValidLocations do
|
|
26
26
|
{
|
27
27
|
"message"=> "'@skip' can't be applied to queries (allowed: fields, fragment spreads, inline fragments)",
|
28
28
|
"locations"=>[{"line"=>2, "column"=>21}],
|
29
|
-
"
|
29
|
+
"path"=>["query getCheese"],
|
30
|
+
"extensions"=>{"code"=>"directiveCannotBeApplied", "targetName"=>"queries", "name"=>"skip"}
|
30
31
|
},
|
31
32
|
{
|
32
33
|
"message"=>"'@skip' can't be applied to fragment definitions (allowed: fields, fragment spreads, inline fragments)",
|
33
34
|
"locations"=>[{"line"=>13, "column"=>33}],
|
34
|
-
"
|
35
|
+
"path"=>["fragment whatever"],
|
36
|
+
"extensions"=>{"code"=>"directiveCannotBeApplied", "targetName"=>"fragment definitions", "name"=>"skip"}
|
35
37
|
},
|
36
38
|
]
|
37
39
|
assert_equal(expected, errors)
|
@@ -31,7 +31,8 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
31
31
|
{
|
32
32
|
"message"=>"Field 'notDefinedField' doesn't exist on type 'Query'",
|
33
33
|
"locations"=>[{"line"=>1, "column"=>18}],
|
34
|
-
"
|
34
|
+
"path"=>["query getStuff", "notDefinedField"],
|
35
|
+
"extensions"=>{"code"=>"undefinedField", "typeName"=>"Query", "fieldName"=>"notDefinedField"}
|
35
36
|
}
|
36
37
|
]
|
37
38
|
assert_equal(expected_errors, errors)
|
@@ -46,7 +47,8 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
46
47
|
{
|
47
48
|
"message"=>"Field 'amountThatILikeIt' doesn't exist on type 'Edible'",
|
48
49
|
"locations"=>[{"line"=>1, "column"=>35}],
|
49
|
-
"
|
50
|
+
"path"=>["query getStuff", "favoriteEdible", "amountThatILikeIt"],
|
51
|
+
"extensions"=>{"code"=>"undefinedField", "typeName"=>"Edible", "fieldName"=>"amountThatILikeIt"}
|
50
52
|
}
|
51
53
|
]
|
52
54
|
assert_equal(expected_errors, errors)
|
@@ -67,7 +69,8 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
67
69
|
"locations"=>[
|
68
70
|
{"line"=>3, "column"=>7}
|
69
71
|
],
|
70
|
-
"
|
72
|
+
"path"=>["fragment dpFields", "source"],
|
73
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"DairyProduct"}
|
71
74
|
}
|
72
75
|
]
|
73
76
|
assert_equal(expected_errors, errors)
|
@@ -120,7 +123,8 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
120
123
|
"locations"=>[
|
121
124
|
{"line"=>2, "column"=>33}
|
122
125
|
],
|
123
|
-
"
|
126
|
+
"path"=>["query", "cheese", "__schema"],
|
127
|
+
"extensions"=>{"code"=>"undefinedField", "typeName"=>"Cheese", "fieldName"=>"__schema"}
|
124
128
|
}
|
125
129
|
]
|
126
130
|
assert_equal(expected_errors, errors)
|
@@ -151,7 +155,8 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
151
155
|
"locations"=>[
|
152
156
|
{"line"=>2, "column"=>33}
|
153
157
|
],
|
154
|
-
"
|
158
|
+
"path"=>["query", "cheese", "__type"],
|
159
|
+
"extensions"=>{"code"=>"undefinedField", "typeName"=>"Cheese", "fieldName"=>"__type"}
|
155
160
|
}
|
156
161
|
]
|
157
162
|
assert_equal(expected_errors, errors)
|
@@ -19,28 +19,32 @@ 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"=>6, "column"=>47}],
|
22
|
-
"
|
22
|
+
"path"=>["query getCheese", "illegalSelectionCheese", "id"],
|
23
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'id'", "typeName"=>"Int"}
|
23
24
|
}
|
24
25
|
assert_includes(errors, illegal_selection_error, "finds illegal selections on scalars")
|
25
26
|
|
26
27
|
objects_selection_required_error = {
|
27
28
|
"message"=>"Field must have selections (field 'cheese' returns Cheese but has no selections. Did you mean 'cheese { ... }'?)",
|
28
29
|
"locations"=>[{"line"=>4, "column"=>7}],
|
29
|
-
"
|
30
|
+
"path"=>["query getCheese", "missingFieldsObject"],
|
31
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'cheese'", "typeName"=>"Cheese"}
|
30
32
|
}
|
31
33
|
assert_includes(errors, objects_selection_required_error, "finds objects without selections")
|
32
34
|
|
33
35
|
interfaces_selection_required_error = {
|
34
36
|
"message"=>"Field must have selections (field 'selfAsEdible' returns Edible but has no selections. Did you mean 'selfAsEdible { ... }'?)",
|
35
37
|
"locations"=>[{"line"=>5, "column"=>47}],
|
36
|
-
"
|
38
|
+
"path"=>["query getCheese", "missingFieldsInterface", "selfAsEdible"],
|
39
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'selfAsEdible'", "typeName"=>"Edible"}
|
37
40
|
}
|
38
41
|
assert_includes(errors, interfaces_selection_required_error, "finds interfaces without selections")
|
39
42
|
|
40
43
|
incorrect_fragment_error = {
|
41
44
|
"message"=>"Selections can't be made on scalars (field 'flavor' returns String but has inline fragments [String])",
|
42
45
|
"locations"=>[{"line"=>7, "column"=>48}],
|
43
|
-
"
|
46
|
+
"path"=>["query getCheese", "incorrectFragmentSpread", "flavor"],
|
47
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'flavor'", "typeName"=>"String"}
|
44
48
|
}
|
45
49
|
assert_includes(errors, incorrect_fragment_error, "finds scalar fields with selections")
|
46
50
|
end
|
@@ -53,7 +57,8 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
|
|
53
57
|
selections_required_error = {
|
54
58
|
"message"=> "Field must have selections (anonymous query returns Query but has no selections. Did you mean ' { ... }'?)",
|
55
59
|
"locations"=>[{"line"=>1, "column"=>1}],
|
56
|
-
"
|
60
|
+
"path"=>["query"],
|
61
|
+
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"anonymous query", "typeName"=>"Query"}
|
57
62
|
}
|
58
63
|
assert_includes(errors, selections_required_error)
|
59
64
|
end
|
@@ -381,7 +381,8 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
381
381
|
{"line"=>4, "column"=>11},
|
382
382
|
{"line"=>8, "column"=>11}
|
383
383
|
],
|
384
|
-
"
|
384
|
+
"path"=>[],
|
385
|
+
"extensions"=>{"code"=>"fieldConflict", "fieldName"=>"x", "conflicts"=>"name or nickname"}
|
385
386
|
}
|
386
387
|
]
|
387
388
|
assert_equal expected_errors, errors
|
@@ -20,7 +20,8 @@ describe GraphQL::StaticValidation::FragmentNamesAreUnique do
|
|
20
20
|
fragment_def_error = {
|
21
21
|
"message"=>"Fragment name \"frag1\" must be unique",
|
22
22
|
"locations"=>[{"line"=>8, "column"=>5}, {"line"=>9, "column"=>5}],
|
23
|
-
"
|
23
|
+
"path"=>[],
|
24
|
+
"extensions"=>{"code"=>"fragmentNotUnique", "fragmentName"=>"frag1"}
|
24
25
|
}
|
25
26
|
assert_includes(errors, fragment_def_error)
|
26
27
|
end
|
@@ -31,17 +31,20 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
|
31
31
|
{
|
32
32
|
"message"=>"Fragment on Milk can't be spread inside Cheese",
|
33
33
|
"locations"=>[{"line"=>6, "column"=>9}],
|
34
|
-
"
|
34
|
+
"path"=>["query getCheese", "cheese", "... on Milk"],
|
35
|
+
"extensions"=>{"code"=>"cannotSpreadFragment", "typeName"=>"Milk", "fragmentName"=>"unknown", "parentName"=>"Cheese"}
|
35
36
|
},
|
36
37
|
{
|
37
38
|
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
38
39
|
"locations"=>[{"line"=>4, "column"=>9}],
|
39
|
-
"
|
40
|
+
"path"=>["query getCheese", "cheese", "... milkFields"],
|
41
|
+
"extensions"=>{"code"=>"cannotSpreadFragment", "typeName"=>"Milk", "fragmentName"=>" milkFields", "parentName"=>"Cheese"}
|
40
42
|
},
|
41
43
|
{
|
42
44
|
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
43
45
|
"locations"=>[{"line"=>18, "column"=>7}],
|
44
|
-
"
|
46
|
+
"path"=>["fragment cheeseFields", "... milkFields"],
|
47
|
+
"extensions"=>{"code"=>"cannotSpreadFragment", "typeName"=>"Milk", "fragmentName"=>" milkFields", "parentName"=>"Cheese"}
|
45
48
|
}
|
46
49
|
]
|
47
50
|
assert_equal(expected, errors)
|
@@ -27,13 +27,15 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
|
|
27
27
|
inline_fragment_error = {
|
28
28
|
"message"=>"No such type Something, so it can't be a fragment condition",
|
29
29
|
"locations"=>[{"line"=>11, "column"=>5}],
|
30
|
-
"
|
30
|
+
"path"=>["fragment somethingFields"],
|
31
|
+
"extensions"=>{"code"=>"undefinedType", "typeName"=>"Something"}
|
31
32
|
}
|
32
33
|
assert_includes(errors, inline_fragment_error, "on inline fragments")
|
33
34
|
fragment_def_error = {
|
34
35
|
"message"=>"No such type Nothing, so it can't be a fragment condition",
|
35
36
|
"locations"=>[{"line"=>5, "column"=>9}],
|
36
|
-
"
|
37
|
+
"path"=>["query getCheese", "cheese", "... on Nothing"],
|
38
|
+
"extensions"=>{"code"=>"undefinedType", "typeName"=>"Nothing"}
|
37
39
|
}
|
38
40
|
assert_includes(errors, fragment_def_error, "on fragment definitions")
|
39
41
|
end
|
@@ -38,12 +38,14 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
|
|
38
38
|
{
|
39
39
|
"message"=>"Fragment sourceField contains an infinite loop",
|
40
40
|
"locations"=>[{"line"=>12, "column"=>5}],
|
41
|
-
"
|
41
|
+
"path"=>["fragment sourceField"],
|
42
|
+
"extensions"=>{"code"=>"infiniteLoop", "fragmentName"=>"sourceField"}
|
42
43
|
},
|
43
44
|
{
|
44
45
|
"message"=>"Fragment flavorField contains an infinite loop",
|
45
46
|
"locations"=>[{"line"=>17, "column"=>5}],
|
46
|
-
"
|
47
|
+
"path"=>["fragment flavorField"],
|
48
|
+
"extensions"=>{"code"=>"infiniteLoop", "fragmentName"=>"flavorField"}
|
47
49
|
}
|
48
50
|
]
|
49
51
|
assert_equal(expected, errors)
|
@@ -16,7 +16,8 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
|
|
16
16
|
fragment_def_error = {
|
17
17
|
"message"=>"Fragment definition has no name",
|
18
18
|
"locations"=>[{"line"=>2, "column"=>5}],
|
19
|
-
"
|
19
|
+
"path"=>["fragment "],
|
20
|
+
"extensions"=>{"code"=>"anonymousFragment"}
|
20
21
|
}
|
21
22
|
assert_includes(errors, fragment_def_error, "on fragment definitions")
|
22
23
|
end
|
@@ -35,17 +35,20 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
|
35
35
|
{
|
36
36
|
"message"=>"Invalid fragment on type Boolean (must be Union, Interface or Object)",
|
37
37
|
"locations"=>[{"line"=>6, "column"=>11}],
|
38
|
-
"
|
38
|
+
"path"=>["query getCheese", "cheese", "... on Cheese", "... on Boolean"],
|
39
|
+
"extensions"=>{"code"=>"fragmentOnNonCompositeType", "typeName"=>"Boolean"}
|
39
40
|
},
|
40
41
|
{
|
41
42
|
"message"=>"Invalid fragment on type DairyProductInput (must be Union, Interface or Object)",
|
42
43
|
"locations"=>[{"line"=>16, "column"=>9}],
|
43
|
-
"
|
44
|
+
"path"=>["query getCheese", "cheese", "... on DairyProductInput"],
|
45
|
+
"extensions"=>{"code"=>"fragmentOnNonCompositeType", "typeName"=>"DairyProductInput"}
|
44
46
|
},
|
45
47
|
{
|
46
48
|
"message"=>"Invalid fragment on type Int (must be Union, Interface or Object)",
|
47
49
|
"locations"=>[{"line"=>22, "column"=>5}],
|
48
|
-
"
|
50
|
+
"path"=>["fragment intFields"],
|
51
|
+
"extensions"=>{"code"=>"fragmentOnNonCompositeType", "typeName"=>"Int"}
|
49
52
|
},
|
50
53
|
]
|
51
54
|
assert_equal(expected, errors)
|
@@ -17,7 +17,8 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
|
|
17
17
|
assert_includes(errors, {
|
18
18
|
"message"=>"Fragment unusedFields was defined, but not used",
|
19
19
|
"locations"=>[{"line"=>8, "column"=>5}],
|
20
|
-
"
|
20
|
+
"path"=>["fragment unusedFields"],
|
21
|
+
"extensions"=>{"code"=>"useAndDefineFragment", "fragmentName"=>"unusedFields"}
|
21
22
|
})
|
22
23
|
end
|
23
24
|
|
@@ -25,7 +26,8 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
|
|
25
26
|
assert_includes(errors, {
|
26
27
|
"message"=>"Fragment undefinedFields was used, but not defined",
|
27
28
|
"locations"=>[{"line"=>5, "column"=>7}],
|
28
|
-
"
|
29
|
+
"path"=>["query getCheese", "... undefinedFields"],
|
30
|
+
"extensions"=>{"code"=>"useAndDefineFragment", "fragmentName"=>"undefinedFields"}
|
29
31
|
})
|
30
32
|
end
|
31
33
|
|
@@ -38,4 +40,22 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
|
|
38
40
|
assert_equal({}, result)
|
39
41
|
end
|
40
42
|
end
|
43
|
+
|
44
|
+
describe "invalid unused fragments" do
|
45
|
+
let(:query_string) {"
|
46
|
+
query getCheese {
|
47
|
+
name
|
48
|
+
}
|
49
|
+
fragment Invalid on DoesNotExist { fatContent }
|
50
|
+
"}
|
51
|
+
|
52
|
+
it "handles them gracefully" do
|
53
|
+
assert_includes(errors, {
|
54
|
+
"message"=>"No such type DoesNotExist, so it can't be a fragment condition",
|
55
|
+
"locations"=>[{"line"=>5, "column"=>7}],
|
56
|
+
"path"=>["fragment Invalid"],
|
57
|
+
"extensions"=>{"code"=>"undefinedType", "typeName"=>"DoesNotExist"}
|
58
|
+
})
|
59
|
+
end
|
60
|
+
end
|
41
61
|
end
|
@@ -31,7 +31,8 @@ describe GraphQL::StaticValidation::MutationRootExists do
|
|
31
31
|
missing_mutation_root_error = {
|
32
32
|
"message"=>"Schema is not configured for mutations",
|
33
33
|
"locations"=>[{"line"=>2, "column"=>5}],
|
34
|
-
"
|
34
|
+
"path"=>["mutation addBagel"],
|
35
|
+
"extensions"=>{"code"=>"missingMutationConfiguration"}
|
35
36
|
}
|
36
37
|
assert_includes(errors, missing_mutation_root_error)
|
37
38
|
end
|
@@ -25,7 +25,8 @@ describe GraphQL::StaticValidation::OperationNamesAreValid do
|
|
25
25
|
requires_name_error = {
|
26
26
|
"message"=>"Operation name is required when multiple operations are present",
|
27
27
|
"locations"=>[{"line"=>5, "column"=>5}, {"line"=>9, "column"=>5}],
|
28
|
-
"
|
28
|
+
"path"=>[],
|
29
|
+
"extensions"=>{"code"=>"uniquelyNamedOperations"}
|
29
30
|
}
|
30
31
|
assert_includes(errors, requires_name_error)
|
31
32
|
end
|
@@ -48,7 +49,8 @@ describe GraphQL::StaticValidation::OperationNamesAreValid do
|
|
48
49
|
requires_name_error = {
|
49
50
|
"message"=>"Operation name is required when multiple operations are present",
|
50
51
|
"locations"=>[{"line"=>1, "column"=>5}, {"line"=>5, "column"=>5}],
|
51
|
-
"
|
52
|
+
"path"=>[],
|
53
|
+
"extensions"=>{"code"=>"uniquelyNamedOperations"}
|
52
54
|
}
|
53
55
|
assert_includes(errors, requires_name_error)
|
54
56
|
end
|
@@ -71,7 +73,8 @@ describe GraphQL::StaticValidation::OperationNamesAreValid do
|
|
71
73
|
name_uniqueness_error = {
|
72
74
|
"message"=>'Operation name "getCheese" must be unique',
|
73
75
|
"locations"=>[{"line"=>1, "column"=>5}, {"line"=>5, "column"=>5}],
|
74
|
-
"
|
76
|
+
"path"=>[],
|
77
|
+
"extensions"=>{"code"=>"uniquelyNamedOperations", "operationName"=>"getCheese"}
|
75
78
|
}
|
76
79
|
assert_includes(errors, name_uniqueness_error)
|
77
80
|
end
|