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
@@ -50,6 +50,32 @@ describe GraphQL::Schema::RelayClassicMutation do
|
|
50
50
|
|
51
51
|
assert_equal "Sitar", res["data"]["addSitar"]["instrument"]["name"]
|
52
52
|
end
|
53
|
+
|
54
|
+
it "supports extras" do
|
55
|
+
res = Jazz::Schema.execute <<-GRAPHQL
|
56
|
+
mutation {
|
57
|
+
hasExtras(input: {}) {
|
58
|
+
nodeClass
|
59
|
+
int
|
60
|
+
}
|
61
|
+
}
|
62
|
+
GRAPHQL
|
63
|
+
|
64
|
+
assert_equal "GraphQL::Language::Nodes::Field", res["data"]["hasExtras"]["nodeClass"]
|
65
|
+
assert_nil res["data"]["hasExtras"]["int"]
|
66
|
+
|
67
|
+
# Also test with given args
|
68
|
+
res = Jazz::Schema.execute <<-GRAPHQL
|
69
|
+
mutation {
|
70
|
+
hasExtras(input: {int: 5}) {
|
71
|
+
nodeClass
|
72
|
+
int
|
73
|
+
}
|
74
|
+
}
|
75
|
+
GRAPHQL
|
76
|
+
assert_equal "GraphQL::Language::Nodes::Field", res["data"]["hasExtras"]["nodeClass"]
|
77
|
+
assert_equal 5, res["data"]["hasExtras"]["int"]
|
78
|
+
end
|
53
79
|
end
|
54
80
|
|
55
81
|
describe "loading multiple application objects" do
|
@@ -181,7 +181,7 @@ describe GraphQL::Schema::Resolver do
|
|
181
181
|
|
182
182
|
class IntegerWrapper < GraphQL::Schema::Object
|
183
183
|
implements HasValue
|
184
|
-
field :value, Integer, null: false, method: :
|
184
|
+
field :value, Integer, null: false, method: :itself
|
185
185
|
end
|
186
186
|
|
187
187
|
class PrepResolver9 < BaseResolver
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "spec_helper"
|
3
|
+
include ErrorBubblingHelpers
|
3
4
|
|
4
5
|
module MaskHelpers
|
5
6
|
class BaseArgument < GraphQL::Schema::Argument
|
@@ -185,6 +186,7 @@ module MaskHelpers
|
|
185
186
|
instrument :query, FilterInstrumentation
|
186
187
|
if TESTING_INTERPRETER
|
187
188
|
use GraphQL::Execution::Interpreter
|
189
|
+
use GraphQL::Analysis::AST
|
188
190
|
end
|
189
191
|
end
|
190
192
|
|
@@ -663,17 +665,39 @@ describe GraphQL::Schema::Warden do
|
|
663
665
|
assert_equal expected_errors, error_messages(res)
|
664
666
|
end
|
665
667
|
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
668
|
+
describe "with error bubbling disabled" do
|
669
|
+
it "isn't a valid literal input" do
|
670
|
+
without_error_bubbling(MaskHelpers::Schema) do
|
671
|
+
query_string = %|
|
672
|
+
{
|
673
|
+
languages(within: {latitude: 1.0, longitude: 2.2, miles: 3.3}) { name }
|
674
|
+
}|
|
675
|
+
res = MaskHelpers.query_with_mask(query_string, mask)
|
676
|
+
expected_errors =
|
677
|
+
[
|
678
|
+
"InputObject 'WithinInput' doesn't accept argument 'miles'"
|
679
|
+
]
|
680
|
+
assert_equal expected_errors, error_messages(res)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
describe "with error bubbling enabled" do
|
686
|
+
it "isn't a valid literal input" do
|
687
|
+
with_error_bubbling(MaskHelpers::Schema) do
|
688
|
+
query_string = %|
|
689
|
+
{
|
690
|
+
languages(within: {latitude: 1.0, longitude: 2.2, miles: 3.3}) { name }
|
691
|
+
}|
|
692
|
+
res = MaskHelpers.query_with_mask(query_string, mask)
|
693
|
+
expected_errors =
|
694
|
+
[
|
695
|
+
"Argument 'within' on Field 'languages' has an invalid value. Expected type 'WithinInput'.",
|
696
|
+
"InputObject 'WithinInput' doesn't accept argument 'miles'"
|
697
|
+
]
|
698
|
+
assert_equal expected_errors, error_messages(res)
|
699
|
+
end
|
700
|
+
end
|
677
701
|
end
|
678
702
|
|
679
703
|
it "isn't a valid variable input" do
|
@@ -3,6 +3,7 @@ require "spec_helper"
|
|
3
3
|
|
4
4
|
describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
5
5
|
include StaticValidationHelpers
|
6
|
+
include ErrorBubblingHelpers
|
6
7
|
|
7
8
|
let(:query_string) {%|
|
8
9
|
query getCheese {
|
@@ -20,65 +21,119 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
20
21
|
}
|
21
22
|
|}
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
describe "with error bubbling disabled" do
|
25
|
+
it "finds undefined or missing-required arguments to fields and directives" do
|
26
|
+
without_error_bubbling(schema) do
|
27
|
+
# `wacky` above is handled by ArgumentsAreDefined, missingSource is handled by RequiredInputObjectAttributesArePresent
|
28
|
+
# so only 4 are tested below
|
29
|
+
assert_equal(6, errors.length)
|
30
|
+
|
31
|
+
query_root_error = {
|
32
|
+
"message"=>"Argument 'id' on Field 'stringCheese' has an invalid value. Expected type 'Int!'.",
|
33
|
+
"locations"=>[{"line"=>3, "column"=>7}],
|
34
|
+
"path"=>["query getCheese", "stringCheese", "id"],
|
35
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"id"},
|
36
|
+
}
|
37
|
+
assert_includes(errors, query_root_error)
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
39
|
+
directive_error = {
|
40
|
+
"message"=>"Argument 'if' on Directive 'skip' has an invalid value. Expected type 'Boolean!'.",
|
41
|
+
"locations"=>[{"line"=>4, "column"=>30}],
|
42
|
+
"path"=>["query getCheese", "cheese", "source", "if"],
|
43
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Directive", "argumentName"=>"if"},
|
44
|
+
}
|
45
|
+
assert_includes(errors, directive_error)
|
33
46
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
47
|
+
input_object_field_error = {
|
48
|
+
"message"=>"Argument 'source' on InputObject 'DairyProductInput' has an invalid value. Expected type 'DairyAnimal!'.",
|
49
|
+
"locations"=>[{"line"=>6, "column"=>40}],
|
50
|
+
"path"=>["query getCheese", "badSource", "product", "source"],
|
51
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"InputObject", "argumentName"=>"source"},
|
52
|
+
}
|
53
|
+
assert_includes(errors, input_object_field_error)
|
40
54
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
fragment_error = {
|
56
|
+
"message"=>"Argument 'source' on Field 'similarCheese' has an invalid value. Expected type '[DairyAnimal!]!'.",
|
57
|
+
"locations"=>[{"line"=>13, "column"=>7}],
|
58
|
+
"path"=>["fragment cheeseFields", "similarCheese", "source"],
|
59
|
+
"extensions"=> {"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"source"}
|
60
|
+
}
|
61
|
+
assert_includes(errors, fragment_error)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
it 'works with error bubbling enabled' do
|
65
|
+
with_error_bubbling(schema) do
|
66
|
+
assert_equal(9, errors.length)
|
67
|
+
|
68
|
+
query_root_error = {
|
69
|
+
"message"=>"Argument 'id' on Field 'stringCheese' has an invalid value. Expected type 'Int!'.",
|
70
|
+
"locations"=>[{"line"=>3, "column"=>7}],
|
71
|
+
"path"=>["query getCheese", "stringCheese", "id"],
|
72
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"id"},
|
73
|
+
}
|
74
|
+
assert_includes(errors, query_root_error)
|
47
75
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
76
|
+
directive_error = {
|
77
|
+
"message"=>"Argument 'if' on Directive 'skip' has an invalid value. Expected type 'Boolean!'.",
|
78
|
+
"locations"=>[{"line"=>4, "column"=>30}],
|
79
|
+
"path"=>["query getCheese", "cheese", "source", "if"],
|
80
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Directive", "argumentName"=>"if"},
|
81
|
+
}
|
82
|
+
assert_includes(errors, directive_error)
|
54
83
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
84
|
+
input_object_error = {
|
85
|
+
"message"=>"Argument 'product' on Field 'badSource' has an invalid value. Expected type '[DairyProductInput]'.",
|
86
|
+
"locations"=>[{"line"=>6, "column"=>7}],
|
87
|
+
"path"=>["query getCheese", "badSource", "product"],
|
88
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"product"},
|
89
|
+
}
|
90
|
+
assert_includes(errors, input_object_error)
|
61
91
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
92
|
+
input_object_field_error = {
|
93
|
+
"message"=>"Argument 'source' on InputObject 'DairyProductInput' has an invalid value. Expected type 'DairyAnimal!'.",
|
94
|
+
"locations"=>[{"line"=>6, "column"=>40}],
|
95
|
+
"path"=>["query getCheese", "badSource", "product", "source"],
|
96
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"InputObject", "argumentName"=>"source"},
|
97
|
+
}
|
98
|
+
assert_includes(errors, input_object_field_error)
|
99
|
+
|
100
|
+
missing_required_field_error = {
|
101
|
+
"message"=>"Argument 'product' on Field 'missingSource' has an invalid value. Expected type '[DairyProductInput]'.",
|
102
|
+
"locations"=>[{"line"=>7, "column"=>7}],
|
103
|
+
"path"=>["query getCheese", "missingSource", "product"],
|
104
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"product"}
|
105
|
+
}
|
106
|
+
assert_includes(errors, missing_required_field_error)
|
107
|
+
|
108
|
+
fragment_error = {
|
109
|
+
"message"=>"Argument 'source' on Field 'similarCheese' has an invalid value. Expected type '[DairyAnimal!]!'.",
|
110
|
+
"locations"=>[{"line"=>13, "column"=>7}],
|
111
|
+
"path"=>["fragment cheeseFields", "similarCheese", "source"],
|
112
|
+
"extensions"=> {"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"source"}
|
113
|
+
}
|
114
|
+
assert_includes(errors, fragment_error)
|
115
|
+
end
|
116
|
+
end
|
68
117
|
end
|
69
118
|
|
70
|
-
describe "using input objects for enums" do
|
119
|
+
describe "using input objects for enums it adds an error" do
|
71
120
|
let(:query_string) { <<-GRAPHQL
|
72
121
|
{
|
73
122
|
yakSource: searchDairy(product: [{source: {a: 1, b: 2}, fatContent: 1.1}]) { __typename }
|
74
123
|
}
|
75
124
|
GRAPHQL
|
76
125
|
}
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
126
|
+
it "works with error bubbling disabled" do
|
127
|
+
without_error_bubbling(schema) do
|
128
|
+
assert_equal 1, errors.length
|
129
|
+
end
|
130
|
+
end
|
131
|
+
it "works with error bubbling enabled" do
|
132
|
+
with_error_bubbling(schema) do
|
133
|
+
# TODO:
|
134
|
+
# It's annoying that this error cascades up, there should only be one:
|
135
|
+
assert_equal 2, errors.length
|
136
|
+
end
|
82
137
|
end
|
83
138
|
end
|
84
139
|
|
@@ -120,7 +175,8 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
120
175
|
assert_equal [{
|
121
176
|
"message"=>"Argument 'arg' on Field 'field' has an invalid value. Expected type 'Int!'.",
|
122
177
|
"locations"=>[{"line"=>3, "column"=>11}],
|
123
|
-
"
|
178
|
+
"path"=>["query", "field", "arg"],
|
179
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"arg"}
|
124
180
|
}], errors
|
125
181
|
end
|
126
182
|
end
|
@@ -143,7 +199,8 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
143
199
|
assert_equal [{
|
144
200
|
"message"=>"Argument 'arg' on Field 'field' has an invalid value. Expected type '[Int!]'.",
|
145
201
|
"locations"=>[{"line"=>3, "column"=>11}],
|
146
|
-
"
|
202
|
+
"path"=>["query", "field", "arg"],
|
203
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"arg"}
|
147
204
|
}], errors
|
148
205
|
end
|
149
206
|
end
|
@@ -186,20 +243,42 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
186
243
|
}
|
187
244
|
|}
|
188
245
|
|
189
|
-
it
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
246
|
+
describe "it finds errors" do
|
247
|
+
it "works with error bubbling disabled" do
|
248
|
+
without_error_bubbling(schema) do
|
249
|
+
assert_equal 1, errors.length
|
250
|
+
refute_includes errors, {
|
251
|
+
"message"=>"Argument 'arg' on Field 'field' has an invalid value. Expected type 'Input'.",
|
252
|
+
"locations"=>[{"line"=>3, "column"=>11}],
|
253
|
+
"path"=>["query", "field", "arg"],
|
254
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"arg"}
|
255
|
+
}
|
256
|
+
assert_includes errors, {
|
257
|
+
"message"=>"Argument 'b' on InputObject 'Input' has an invalid value. Expected type 'Int!'.",
|
258
|
+
"locations"=>[{"line"=>3, "column"=>22}],
|
259
|
+
"path"=>["query", "field", "arg", "b"],
|
260
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"InputObject", "argumentName"=>"b"}
|
261
|
+
}
|
262
|
+
end
|
263
|
+
end
|
264
|
+
it "works with error bubbling enabled" do
|
265
|
+
with_error_bubbling(schema) do
|
266
|
+
assert_equal 2, errors.length
|
267
|
+
assert_includes errors, {
|
268
|
+
"message"=>"Argument 'arg' on Field 'field' has an invalid value. Expected type 'Input'.",
|
269
|
+
"locations"=>[{"line"=>3, "column"=>11}],
|
270
|
+
"path"=>["query", "field", "arg"],
|
271
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"arg"}
|
272
|
+
}
|
273
|
+
|
274
|
+
assert_includes errors, {
|
275
|
+
"message"=>"Argument 'b' on InputObject 'Input' has an invalid value. Expected type 'Int!'.",
|
276
|
+
"locations"=>[{"line"=>3, "column"=>22}],
|
277
|
+
"path"=>["query", "field", "arg", "b"],
|
278
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"InputObject", "argumentName"=>"b"}
|
279
|
+
}
|
280
|
+
end
|
281
|
+
end
|
203
282
|
end
|
204
283
|
end
|
205
284
|
end
|
@@ -215,15 +294,15 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
215
294
|
assert_includes(errors, {
|
216
295
|
"message"=>"Argument 'name' on Field '__type' has an invalid value. Expected type 'String!'.",
|
217
296
|
"locations"=>[{"line"=>3, "column"=>9}],
|
218
|
-
"
|
297
|
+
"path"=>["query", "__type", "name"],
|
298
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"Field", "argumentName"=>"name"}
|
219
299
|
})
|
220
300
|
end
|
221
301
|
end
|
222
302
|
|
223
303
|
describe "custom error messages" do
|
224
304
|
let(:schema) {
|
225
|
-
|
226
|
-
CoerceTestTimeType = GraphQL::ScalarType.define do
|
305
|
+
CoerceTestTimeType ||= GraphQL::ScalarType.define do
|
227
306
|
name "Time"
|
228
307
|
description "Time since epoch in seconds"
|
229
308
|
|
@@ -238,17 +317,26 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
238
317
|
coerce_result ->(value, ctx) { value.to_f }
|
239
318
|
end
|
240
319
|
|
241
|
-
|
320
|
+
CoerceTestDeepTimeType ||= GraphQL::InputObjectType.define do
|
321
|
+
name "range"
|
322
|
+
description "Time range"
|
323
|
+
argument :from, !CoerceTestTimeType
|
324
|
+
argument :to, !CoerceTestTimeType
|
325
|
+
end
|
326
|
+
|
327
|
+
CoerceTestQueryType ||= GraphQL::ObjectType.define do
|
242
328
|
name "Query"
|
243
329
|
description "The query root of this schema"
|
244
330
|
|
245
331
|
field :time do
|
246
332
|
type CoerceTestTimeType
|
247
|
-
argument :value,
|
333
|
+
argument :value, CoerceTestTimeType
|
334
|
+
argument :range, CoerceTestDeepTimeType
|
248
335
|
resolve ->(obj, args, ctx) { args[:value] }
|
249
336
|
end
|
250
337
|
end
|
251
338
|
|
339
|
+
|
252
340
|
GraphQL::Schema.define do
|
253
341
|
query CoerceTestQueryType
|
254
342
|
end
|
@@ -260,14 +348,66 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
260
348
|
}
|
261
349
|
|}
|
262
350
|
|
263
|
-
|
264
|
-
|
351
|
+
describe "with a shallow coercion" do
|
352
|
+
it "sets error message from a CoercionError if raised" do
|
353
|
+
assert_equal 1, errors.length
|
265
354
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
355
|
+
assert_includes errors, {
|
356
|
+
"message"=> "cannot coerce to Float",
|
357
|
+
"locations"=>[{"line"=>3, "column"=>9}],
|
358
|
+
"path"=>["query", "time", "value"],
|
359
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"CoercionError"}
|
360
|
+
}
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
describe "with a deep coercion" do
|
365
|
+
let(:query_string) {%|
|
366
|
+
query {
|
367
|
+
time(range: { from: "a", to: "b" })
|
368
|
+
}
|
369
|
+
|}
|
370
|
+
|
371
|
+
from_error = {
|
372
|
+
"message"=>"cannot coerce to Float",
|
373
|
+
"locations"=>[{"line"=>3, "column"=>23}],
|
374
|
+
"path"=>["query", "time", "range", "from"],
|
375
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"CoercionError"},
|
376
|
+
}
|
377
|
+
|
378
|
+
to_error = {
|
379
|
+
"message"=>"cannot coerce to Float",
|
380
|
+
"locations"=>[{"line"=>3, "column"=>23}],
|
381
|
+
"path"=>["query", "time", "range", "to"],
|
382
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"CoercionError"},
|
383
|
+
}
|
384
|
+
|
385
|
+
bubbling_error = {
|
386
|
+
"message"=>"cannot coerce to Float",
|
387
|
+
"locations"=>[{"line"=>3, "column"=>11}],
|
388
|
+
"path"=>["query", "time", "range"],
|
389
|
+
"extensions"=>{"code"=>"argumentLiteralsIncompatible", "typeName"=>"CoercionError"},
|
270
390
|
}
|
391
|
+
|
392
|
+
describe "sets deep error message from a CoercionError if raised" do
|
393
|
+
it "works with error bubbling enabled" do
|
394
|
+
with_error_bubbling(schema) do
|
395
|
+
assert_equal 3, errors.length
|
396
|
+
assert_includes(errors, from_error)
|
397
|
+
assert_includes(errors, to_error)
|
398
|
+
assert_includes(errors, bubbling_error)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
it "works without error bubbling enabled" do
|
403
|
+
without_error_bubbling(schema) do
|
404
|
+
assert_equal 2, errors.length
|
405
|
+
assert_includes(errors, from_error)
|
406
|
+
assert_includes(errors, to_error)
|
407
|
+
refute_includes(errors, bubbling_error)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
271
411
|
end
|
272
412
|
end
|
273
413
|
end
|