graphql 1.2.6 → 1.3.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.rb +3 -1
- data/lib/graphql/analysis.rb +1 -0
- data/lib/graphql/analysis/analyze_query.rb +1 -0
- data/lib/graphql/analysis/field_usage.rb +1 -0
- data/lib/graphql/analysis/max_query_complexity.rb +1 -0
- data/lib/graphql/analysis/max_query_depth.rb +1 -0
- data/lib/graphql/analysis/query_complexity.rb +1 -0
- data/lib/graphql/analysis/query_depth.rb +1 -0
- data/lib/graphql/analysis/reducer_state.rb +1 -0
- data/lib/graphql/analysis_error.rb +1 -0
- data/lib/graphql/argument.rb +1 -0
- data/lib/graphql/base_type.rb +16 -7
- data/lib/graphql/boolean_type.rb +1 -0
- data/lib/graphql/compatibility.rb +2 -0
- data/lib/graphql/compatibility/execution_specification.rb +113 -192
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +195 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +186 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +97 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +1 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +1 -0
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +1 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +1 -0
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/assign_argument.rb +1 -0
- data/lib/graphql/define/assign_connection.rb +1 -0
- data/lib/graphql/define/assign_enum_value.rb +1 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -0
- data/lib/graphql/define/assign_object_field.rb +1 -0
- data/lib/graphql/define/defined_object_proxy.rb +1 -0
- data/lib/graphql/define/instance_definable.rb +11 -12
- data/lib/graphql/define/non_null_with_bang.rb +1 -0
- data/lib/graphql/define/type_definer.rb +1 -0
- data/lib/graphql/directive.rb +1 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -0
- data/lib/graphql/directive/include_directive.rb +1 -0
- data/lib/graphql/directive/skip_directive.rb +1 -0
- data/lib/graphql/enum_type.rb +8 -1
- data/lib/graphql/execution.rb +5 -0
- data/lib/graphql/execution/directive_checks.rb +1 -0
- data/lib/graphql/execution/execute.rb +222 -0
- data/lib/graphql/execution/field_result.rb +52 -0
- data/lib/graphql/execution/lazy.rb +59 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +38 -0
- data/lib/graphql/execution/lazy/resolve.rb +68 -0
- data/lib/graphql/execution/selection_result.rb +84 -0
- data/lib/graphql/execution/typecast.rb +4 -4
- data/lib/graphql/execution_error.rb +1 -0
- data/lib/graphql/field.rb +68 -18
- data/lib/graphql/field/resolve.rb +1 -0
- data/lib/graphql/float_type.rb +1 -0
- data/lib/graphql/id_type.rb +1 -0
- data/lib/graphql/input_object_type.rb +6 -0
- data/lib/graphql/int_type.rb +1 -0
- data/lib/graphql/interface_type.rb +6 -0
- data/lib/graphql/internal_representation.rb +2 -1
- data/lib/graphql/internal_representation/node.rb +2 -1
- data/lib/graphql/internal_representation/rewrite.rb +1 -0
- data/lib/graphql/internal_representation/selection.rb +85 -0
- data/lib/graphql/introspection.rb +1 -0
- data/lib/graphql/introspection/arguments_field.rb +1 -0
- data/lib/graphql/introspection/directive_location_enum.rb +1 -0
- data/lib/graphql/introspection/directive_type.rb +1 -0
- data/lib/graphql/introspection/enum_value_type.rb +1 -0
- data/lib/graphql/introspection/enum_values_field.rb +1 -0
- data/lib/graphql/introspection/field_type.rb +1 -0
- data/lib/graphql/introspection/fields_field.rb +1 -0
- data/lib/graphql/introspection/input_fields_field.rb +1 -0
- data/lib/graphql/introspection/input_value_type.rb +2 -1
- data/lib/graphql/introspection/interfaces_field.rb +1 -0
- data/lib/graphql/introspection/introspection_query.rb +1 -0
- data/lib/graphql/introspection/of_type_field.rb +1 -0
- data/lib/graphql/introspection/possible_types_field.rb +1 -0
- data/lib/graphql/introspection/schema_field.rb +1 -0
- data/lib/graphql/introspection/schema_type.rb +1 -0
- data/lib/graphql/introspection/type_by_name_field.rb +1 -0
- data/lib/graphql/introspection/type_kind_enum.rb +1 -0
- data/lib/graphql/introspection/type_type.rb +1 -0
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/invalid_null_error.rb +17 -7
- data/lib/graphql/language.rb +10 -0
- data/lib/graphql/language/comments.rb +2 -1
- data/lib/graphql/language/definition_slice.rb +1 -0
- data/lib/graphql/language/generation.rb +25 -24
- data/lib/graphql/language/nodes.rb +1 -0
- data/lib/graphql/language/token.rb +1 -0
- data/lib/graphql/language/visitor.rb +1 -0
- data/lib/graphql/list_type.rb +1 -0
- data/lib/graphql/non_null_type.rb +2 -1
- data/lib/graphql/object_type.rb +12 -0
- data/lib/graphql/query.rb +40 -43
- data/lib/graphql/query/arguments.rb +1 -0
- data/lib/graphql/query/context.rb +31 -7
- data/lib/graphql/query/executor.rb +8 -1
- data/lib/graphql/query/input_validation_result.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -0
- data/lib/graphql/query/serial_execution.rb +3 -4
- data/lib/graphql/query/serial_execution/field_resolution.rb +15 -10
- data/lib/graphql/query/serial_execution/operation_resolution.rb +3 -5
- data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -5
- data/lib/graphql/query/serial_execution/value_resolution.rb +26 -11
- data/lib/graphql/query/variable_validation_error.rb +1 -0
- data/lib/graphql/query/variables.rb +1 -0
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/array_connection.rb +3 -2
- data/lib/graphql/relay/base_connection.rb +20 -8
- data/lib/graphql/relay/connection_field.rb +1 -0
- data/lib/graphql/relay/connection_resolve.rb +14 -1
- data/lib/graphql/relay/connection_type.rb +1 -0
- data/lib/graphql/relay/edge.rb +1 -0
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/global_id_resolve.rb +1 -0
- data/lib/graphql/relay/mutation.rb +13 -0
- data/lib/graphql/relay/node.rb +1 -0
- data/lib/graphql/relay/page_info.rb +1 -0
- data/lib/graphql/relay/relation_connection.rb +3 -2
- data/lib/graphql/runtime_type_error.rb +4 -0
- data/lib/graphql/scalar_type.rb +2 -1
- data/lib/graphql/schema.rb +116 -26
- data/lib/graphql/schema/base_64_encoder.rb +14 -0
- data/lib/graphql/schema/build_from_definition.rb +4 -0
- data/lib/graphql/schema/catchall_middleware.rb +1 -0
- data/lib/graphql/schema/default_type_error.rb +15 -0
- data/lib/graphql/schema/instrumented_field_map.rb +1 -0
- data/lib/graphql/schema/invalid_type_error.rb +1 -0
- data/lib/graphql/schema/loader.rb +5 -1
- data/lib/graphql/schema/middleware_chain.rb +1 -0
- data/lib/graphql/schema/possible_types.rb +1 -0
- data/lib/graphql/schema/printer.rb +3 -2
- data/lib/graphql/schema/reduce_types.rb +1 -0
- data/lib/graphql/schema/rescue_middleware.rb +3 -2
- data/lib/graphql/schema/timeout_middleware.rb +1 -0
- data/lib/graphql/schema/type_expression.rb +1 -0
- data/lib/graphql/schema/type_map.rb +1 -0
- data/lib/graphql/schema/unique_within_type.rb +1 -0
- data/lib/graphql/schema/validation.rb +57 -1
- data/lib/graphql/schema/warden.rb +1 -0
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/arguments_validator.rb +1 -0
- data/lib/graphql/static_validation/literal_validator.rb +1 -0
- data/lib/graphql/static_validation/message.rb +1 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +6 -3
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +1 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +1 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -0
- data/lib/graphql/static_validation/type_stack.rb +1 -0
- data/lib/graphql/static_validation/validation_context.rb +2 -1
- data/lib/graphql/static_validation/validator.rb +2 -1
- data/lib/graphql/string_type.rb +1 -0
- data/lib/graphql/type_kinds.rb +1 -0
- data/lib/graphql/union_type.rb +13 -0
- data/lib/graphql/unresolved_type_error.rb +26 -5
- data/lib/graphql/version.rb +2 -1
- data/readme.md +1 -5
- data/spec/graphql/analysis/analyze_query_spec.rb +1 -0
- data/spec/graphql/analysis/field_usage_spec.rb +1 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +1 -0
- data/spec/graphql/analysis/max_query_depth_spec.rb +1 -0
- data/spec/graphql/analysis/query_complexity_spec.rb +1 -0
- data/spec/graphql/analysis/query_depth_spec.rb +1 -0
- data/spec/graphql/argument_spec.rb +1 -0
- data/spec/graphql/base_type_spec.rb +13 -0
- data/spec/graphql/boolean_type_spec.rb +1 -0
- data/spec/graphql/compatibility/execution_specification_spec.rb +1 -0
- data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +4 -0
- data/spec/graphql/compatibility/query_parser_specification_spec.rb +1 -0
- data/spec/graphql/compatibility/schema_parser_specification_spec.rb +1 -0
- data/spec/graphql/define/assign_argument_spec.rb +1 -0
- data/spec/graphql/define/instance_definable_spec.rb +1 -0
- data/spec/graphql/directive_spec.rb +1 -0
- data/spec/graphql/enum_type_spec.rb +10 -0
- data/spec/graphql/execution/execute_spec.rb +5 -0
- data/spec/graphql/execution/lazy_spec.rb +252 -0
- data/spec/graphql/execution/typecast_spec.rb +1 -0
- data/spec/graphql/execution_error_spec.rb +1 -0
- data/spec/graphql/field_spec.rb +17 -0
- data/spec/graphql/float_type_spec.rb +1 -0
- data/spec/graphql/id_type_spec.rb +1 -0
- data/spec/graphql/input_object_type_spec.rb +10 -0
- data/spec/graphql/int_type_spec.rb +1 -0
- data/spec/graphql/interface_type_spec.rb +10 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +1 -0
- data/spec/graphql/introspection/directive_type_spec.rb +1 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +1 -0
- data/spec/graphql/introspection/introspection_query_spec.rb +1 -0
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/introspection/type_type_spec.rb +1 -0
- data/spec/graphql/language/definition_slice_spec.rb +1 -0
- data/spec/graphql/language/equality_spec.rb +1 -0
- data/spec/graphql/language/generation_spec.rb +1 -0
- data/spec/graphql/language/lexer_spec.rb +1 -0
- data/spec/graphql/language/nodes_spec.rb +1 -0
- data/spec/graphql/language/parser_spec.rb +1 -0
- data/spec/graphql/language/visitor_spec.rb +1 -0
- data/spec/graphql/list_type_spec.rb +1 -0
- data/spec/graphql/non_null_type_spec.rb +17 -0
- data/spec/graphql/object_type_spec.rb +19 -0
- data/spec/graphql/query/arguments_spec.rb +1 -0
- data/spec/graphql/query/context_spec.rb +1 -0
- data/spec/graphql/query/executor_spec.rb +1 -0
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -0
- data/spec/graphql/query/variables_spec.rb +1 -0
- data/spec/graphql/query_spec.rb +25 -0
- data/spec/graphql/relay/array_connection_spec.rb +1 -0
- data/spec/graphql/relay/base_connection_spec.rb +33 -4
- data/spec/graphql/relay/connection_field_spec.rb +1 -0
- data/spec/graphql/relay/connection_type_spec.rb +1 -0
- data/spec/graphql/relay/mutation_spec.rb +6 -0
- data/spec/graphql/relay/node_spec.rb +1 -0
- data/spec/graphql/relay/page_info_spec.rb +1 -0
- data/spec/graphql/relay/relation_connection_spec.rb +1 -0
- data/spec/graphql/scalar_type_spec.rb +1 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +9 -1
- data/spec/graphql/schema/catchall_middleware_spec.rb +1 -0
- data/spec/graphql/schema/loader_spec.rb +7 -0
- data/spec/graphql/schema/middleware_chain_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +1 -0
- data/spec/graphql/schema/reduce_types_spec.rb +1 -0
- data/spec/graphql/schema/rescue_middleware_spec.rb +1 -0
- data/spec/graphql/schema/timeout_middleware_spec.rb +1 -0
- data/spec/graphql/schema/type_expression_spec.rb +1 -0
- data/spec/graphql/schema/unique_within_type_spec.rb +1 -0
- data/spec/graphql/schema/validation_spec.rb +55 -0
- data/spec/graphql/schema/warden_spec.rb +1 -0
- data/spec/graphql/schema_spec.rb +39 -0
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +515 -31
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +1 -0
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +1 -0
- data/spec/graphql/static_validation/type_stack_spec.rb +1 -0
- data/spec/graphql/static_validation/validator_spec.rb +1 -0
- data/spec/graphql/string_type_spec.rb +1 -0
- data/spec/graphql/union_type_spec.rb +11 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/dairy_app.rb +1 -0
- data/spec/support/dairy_data.rb +1 -0
- data/spec/support/minimum_input_object.rb +1 -0
- data/spec/support/star_wars_data.rb +1 -0
- data/spec/support/star_wars_schema.rb +30 -7
- data/spec/support/static_validation_helpers.rb +1 -0
- metadata +24 -5
- data/lib/graphql/internal_representation/selections.rb +0 -41
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "spec_helper"
|
2
3
|
|
3
4
|
describe GraphQL::Schema::Loader do
|
@@ -197,6 +198,12 @@ describe GraphQL::Schema::Loader do
|
|
197
198
|
assert loaded_schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY)
|
198
199
|
end
|
199
200
|
|
201
|
+
it "has no-op coerce functions" do
|
202
|
+
custom_scalar = loaded_schema.types["BigInt"]
|
203
|
+
assert_equal true, custom_scalar.valid_input?("anything", PermissiveWarden)
|
204
|
+
assert_equal true, custom_scalar.valid_input?(12345, PermissiveWarden)
|
205
|
+
end
|
206
|
+
|
200
207
|
it "sets correct default values on custom scalar arguments" do
|
201
208
|
type = loaded_schema.types["Comment"]
|
202
209
|
field = type.fields['fieldWithArg']
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "spec_helper"
|
2
3
|
|
3
4
|
describe GraphQL::Schema::Validation do
|
@@ -6,6 +7,10 @@ describe GraphQL::Schema::Validation do
|
|
6
7
|
assert_includes validation_error, error_substring
|
7
8
|
end
|
8
9
|
|
10
|
+
def assert_validation_warns(object, warning)
|
11
|
+
assert_output("", warning + "\n") { GraphQL::Schema::Validation.validate(object) }
|
12
|
+
end
|
13
|
+
|
9
14
|
describe "validating Fields" do
|
10
15
|
let(:unnamed_field) {
|
11
16
|
GraphQL::Field.define do
|
@@ -13,6 +18,13 @@ describe GraphQL::Schema::Validation do
|
|
13
18
|
end
|
14
19
|
}
|
15
20
|
|
21
|
+
let(:invalid_name_field) {
|
22
|
+
GraphQL::Field.define do
|
23
|
+
name "__Something"
|
24
|
+
type GraphQL::STRING_TYPE
|
25
|
+
end
|
26
|
+
}
|
27
|
+
|
16
28
|
let(:untyped_field) {
|
17
29
|
GraphQL::Field.define do
|
18
30
|
name "Untyped"
|
@@ -44,6 +56,10 @@ describe GraphQL::Schema::Validation do
|
|
44
56
|
assert_error_includes unnamed_field, "must return String, not NilClass"
|
45
57
|
end
|
46
58
|
|
59
|
+
it "cannot use reserved name" do
|
60
|
+
assert_validation_warns invalid_name_field, 'Name "__Something" must not begin with "__", which is reserved by GraphQL introspection.'
|
61
|
+
end
|
62
|
+
|
47
63
|
it "requires a BaseType for type" do
|
48
64
|
assert_error_includes untyped_field, "must return GraphQL::BaseType, not Symbol"
|
49
65
|
end
|
@@ -64,16 +80,27 @@ describe GraphQL::Schema::Validation do
|
|
64
80
|
end
|
65
81
|
}
|
66
82
|
|
83
|
+
let(:invalid_name_type) {
|
84
|
+
GraphQL::BaseType.define do
|
85
|
+
name '__Something'
|
86
|
+
end
|
87
|
+
}
|
88
|
+
|
67
89
|
let(:wrongly_described_type) {
|
68
90
|
GraphQL::BaseType.define do
|
69
91
|
name "WronglyDescribed"
|
70
92
|
description 12345
|
71
93
|
end
|
72
94
|
}
|
95
|
+
|
73
96
|
it "requires a String name" do
|
74
97
|
assert_error_includes unnamed_type, "must return String, not Symbol"
|
75
98
|
end
|
76
99
|
|
100
|
+
it "cannot use reserved name" do
|
101
|
+
assert_validation_warns invalid_name_type, 'Name "__Something" must not begin with "__", which is reserved by GraphQL introspection.'
|
102
|
+
end
|
103
|
+
|
77
104
|
it "requires String-or-nil description" do
|
78
105
|
assert_error_includes wrongly_described_type, "must return String or NilClass, not Fixnum"
|
79
106
|
end
|
@@ -86,6 +113,7 @@ describe GraphQL::Schema::Validation do
|
|
86
113
|
interfaces(55)
|
87
114
|
end
|
88
115
|
}
|
116
|
+
|
89
117
|
let(:invalid_interface_member_object) {
|
90
118
|
GraphQL::ObjectType.define do
|
91
119
|
name "InvalidInterfaceMember"
|
@@ -208,6 +236,13 @@ describe GraphQL::Schema::Validation do
|
|
208
236
|
end
|
209
237
|
}
|
210
238
|
|
239
|
+
let(:invalid_name_argument) {
|
240
|
+
GraphQL::Argument.define do
|
241
|
+
name "__Something"
|
242
|
+
type GraphQL::INT_TYPE
|
243
|
+
end
|
244
|
+
}
|
245
|
+
|
211
246
|
let(:null_default_value) {
|
212
247
|
GraphQL::Argument.define do
|
213
248
|
name "NullDefault"
|
@@ -224,8 +259,28 @@ describe GraphQL::Schema::Validation do
|
|
224
259
|
assert_error_includes invalid_default_argument_for_non_null_argument, 'Variable InvalidDefault of type "Int!" is required and will not use the default value. Perhaps you meant to use type "Int".'
|
225
260
|
end
|
226
261
|
|
262
|
+
it "cannot use reserved name" do
|
263
|
+
assert_validation_warns invalid_name_argument, 'Name "__Something" must not begin with "__", which is reserved by GraphQL introspection.'
|
264
|
+
end
|
265
|
+
|
227
266
|
it "allows null default value for nullable argument" do
|
228
267
|
assert_equal nil, GraphQL::Schema::Validation.validate(null_default_value)
|
229
268
|
end
|
230
269
|
end
|
270
|
+
|
271
|
+
describe "validating instrumentation" do
|
272
|
+
let(:schema) {
|
273
|
+
query_type = GraphQL::ObjectType.define(name: "Query")
|
274
|
+
GraphQL::Schema.define do
|
275
|
+
query(query_type)
|
276
|
+
instrument(:field, 1)
|
277
|
+
instrument(:query, :oops)
|
278
|
+
end
|
279
|
+
}
|
280
|
+
it "finds instrumenters missing methods" do
|
281
|
+
err = assert_raises(NotImplementedError) { schema }
|
282
|
+
assert_includes err.message, "before_query(query)"
|
283
|
+
assert_includes err.message, "instrument(type, field)"
|
284
|
+
end
|
285
|
+
end
|
231
286
|
end
|
data/spec/graphql/schema_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "spec_helper"
|
2
3
|
|
3
4
|
describe GraphQL::Schema do
|
@@ -271,4 +272,42 @@ type Query {
|
|
271
272
|
assert_equal 24, res["data"]["int"]
|
272
273
|
end
|
273
274
|
end
|
275
|
+
|
276
|
+
describe "#lazy? / #lazy_method_name" do
|
277
|
+
class LazyObj; end
|
278
|
+
class LazyObjChild < LazyObj; end
|
279
|
+
|
280
|
+
let(:schema) {
|
281
|
+
query_type = GraphQL::ObjectType.define(name: "Query")
|
282
|
+
GraphQL::Schema.define do
|
283
|
+
query(query_type)
|
284
|
+
lazy_resolve(Integer, :itself)
|
285
|
+
lazy_resolve(LazyObj, :dup)
|
286
|
+
end
|
287
|
+
}
|
288
|
+
|
289
|
+
it "returns registered lazy method names by class/superclass, or returns nil" do
|
290
|
+
assert_equal :itself, schema.lazy_method_name(68)
|
291
|
+
assert_equal true, schema.lazy?(77)
|
292
|
+
assert_equal :dup, schema.lazy_method_name(LazyObj.new)
|
293
|
+
assert_equal true, schema.lazy?(LazyObj.new)
|
294
|
+
assert_equal :dup, schema.lazy_method_name(LazyObjChild.new)
|
295
|
+
assert_equal true, schema.lazy?(LazyObjChild.new)
|
296
|
+
assert_equal nil, schema.lazy_method_name({})
|
297
|
+
assert_equal false, schema.lazy?({})
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "#dup" do
|
302
|
+
it "copies internal state" do
|
303
|
+
schema_2 = schema.dup
|
304
|
+
refute schema_2.types.equal?(schema.types)
|
305
|
+
|
306
|
+
refute schema_2.instrumenters.equal?(schema.instrumenters)
|
307
|
+
assert_equal schema_2.instrumenters, schema.instrumenters
|
308
|
+
|
309
|
+
refute schema_2.middleware.equal?(schema.middleware)
|
310
|
+
assert_equal schema_2.middleware, schema.middleware
|
311
|
+
end
|
312
|
+
end
|
274
313
|
end
|
@@ -1,43 +1,527 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "spec_helper"
|
2
3
|
|
3
4
|
describe GraphQL::StaticValidation::FieldsWillMerge do
|
4
5
|
include StaticValidationHelpers
|
5
6
|
|
6
|
-
let(:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
let(:schema) {
|
8
|
+
GraphQL::Schema.from_definition(%|
|
9
|
+
type Query {
|
10
|
+
dog: Dog
|
11
|
+
cat: Cat
|
12
|
+
pet: Pet
|
13
|
+
toy: Toy
|
14
|
+
}
|
15
|
+
|
16
|
+
enum PetCommand {
|
17
|
+
SIT
|
18
|
+
HEEL
|
19
|
+
JUMP
|
20
|
+
DOWN
|
21
|
+
}
|
22
|
+
|
23
|
+
enum ToySize {
|
24
|
+
SMALL
|
25
|
+
LARGE
|
26
|
+
}
|
15
27
|
|
16
|
-
|
17
|
-
|
18
|
-
|
28
|
+
interface Pet {
|
29
|
+
name(surname: Boolean = false): String!
|
30
|
+
nickname: String
|
31
|
+
toys: [Toy!]!
|
32
|
+
}
|
33
|
+
|
34
|
+
type Dog implements Pet {
|
35
|
+
name(surname: Boolean = false): String!
|
36
|
+
nickname: String
|
37
|
+
doesKnowCommand(dogCommand: PetCommand): Boolean!
|
38
|
+
barkVolume: Int!
|
39
|
+
toys: [Toy!]!
|
40
|
+
}
|
41
|
+
|
42
|
+
type Cat implements Pet {
|
43
|
+
name(surname: Boolean = false): String!
|
44
|
+
nickname: String
|
45
|
+
doesKnowCommand(catCommand: PetCommand): Boolean!
|
46
|
+
meowVolume: Int!
|
47
|
+
toys: [Toy!]!
|
48
|
+
}
|
49
|
+
|
50
|
+
type Toy {
|
51
|
+
name: String!
|
52
|
+
size: ToySize!
|
53
|
+
image(maxWidth: Int!): String!
|
54
|
+
}
|
55
|
+
|)
|
56
|
+
}
|
57
|
+
|
58
|
+
describe "unique fields" do
|
59
|
+
let(:query_string) {%|
|
60
|
+
{
|
61
|
+
dog {
|
62
|
+
name
|
63
|
+
nickname
|
19
64
|
}
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
65
|
+
}
|
66
|
+
|}
|
67
|
+
|
68
|
+
it "passes rule" do
|
69
|
+
assert_equal [], errors
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "identical fields" do
|
74
|
+
let(:query_string) {%|
|
75
|
+
{
|
76
|
+
dog {
|
77
|
+
name
|
78
|
+
name
|
24
79
|
}
|
25
80
|
}
|
81
|
+
|}
|
82
|
+
|
83
|
+
it "passes rule" do
|
84
|
+
assert_equal [], errors
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "identical fields with identical args" do
|
89
|
+
let(:query_string) {%|
|
90
|
+
{
|
91
|
+
dog {
|
92
|
+
doesKnowCommand(dogCommand: SIT)
|
93
|
+
doesKnowCommand(dogCommand: SIT)
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|}
|
97
|
+
|
98
|
+
it "passes rule" do
|
99
|
+
assert_equal [], errors
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "identical fields with identical values" do
|
104
|
+
let(:query_string) {%|
|
105
|
+
query($dogCommand: PetCommand) {
|
106
|
+
dog {
|
107
|
+
doesKnowCommand(dogCommand: $dogCommand)
|
108
|
+
doesKnowCommand(dogCommand: $dogCommand)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|}
|
112
|
+
|
113
|
+
it "passes rule" do
|
114
|
+
assert_equal [], errors
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "identical aliases and fields" do
|
119
|
+
let(:query_string) {%|
|
120
|
+
{
|
121
|
+
dog {
|
122
|
+
otherName: name
|
123
|
+
otherName: name
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|}
|
127
|
+
|
128
|
+
it "passes rule" do
|
129
|
+
assert_equal [], errors
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "different args with different aliases" do
|
134
|
+
let(:query_string) {%|
|
135
|
+
{
|
136
|
+
dog {
|
137
|
+
knowsSit: doesKnowCommand(dogCommand: SIT)
|
138
|
+
knowsDown: doesKnowCommand(dogCommand: DOWN)
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|}
|
142
|
+
|
143
|
+
it "passes rule" do
|
144
|
+
assert_equal [], errors
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "conflicting args value and var" do
|
149
|
+
let(:query_string) {%|
|
150
|
+
query ($dogCommand: PetCommand) {
|
151
|
+
dog {
|
152
|
+
doesKnowCommand(dogCommand: SIT)
|
153
|
+
doesKnowCommand(dogCommand: $dogCommand)
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|}
|
157
|
+
|
158
|
+
it "fails rule" do
|
159
|
+
assert_equal [%q(Field 'doesKnowCommand' has an argument conflict: {"dogCommand":"SIT"} or {"dogCommand":"$dogCommand"}?)], error_messages
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "conflicting args value and var" do
|
164
|
+
let(:query_string) {%|
|
165
|
+
query ($varOne: PetCommand, $varTwo: PetCommand) {
|
166
|
+
dog {
|
167
|
+
doesKnowCommand(dogCommand: $varOne)
|
168
|
+
doesKnowCommand(dogCommand: $varTwo)
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|}
|
172
|
+
|
173
|
+
it "fails rule" do
|
174
|
+
assert_equal [%q(Field 'doesKnowCommand' has an argument conflict: {"dogCommand":"$varOne"} or {"dogCommand":"$varTwo"}?)], error_messages
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "different directives with different aliases" do
|
179
|
+
let(:query_string) {%|
|
180
|
+
{
|
181
|
+
dog {
|
182
|
+
nameIfTrue: name @include(if: true)
|
183
|
+
nameIfFalse: name @include(if: false)
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|}
|
187
|
+
|
188
|
+
it "passes rule" do
|
189
|
+
assert_equal [], errors
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "different skip/include directives accepted" do
|
194
|
+
let(:query_string) {%|
|
195
|
+
{
|
196
|
+
dog {
|
197
|
+
name @include(if: true)
|
198
|
+
name @include(if: false)
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|}
|
202
|
+
|
203
|
+
it "passes rule" do
|
204
|
+
assert_equal [], errors
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "same aliases with different field targets" do
|
209
|
+
let(:query_string) {%|
|
210
|
+
{
|
211
|
+
dog {
|
212
|
+
fido: name
|
213
|
+
fido: nickname
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|}
|
217
|
+
|
218
|
+
it "fails rule" do
|
219
|
+
assert_equal ["Field 'fido' has a field conflict: name or nickname?"], error_messages
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "alias masking direct field access" do
|
224
|
+
let(:query_string) {%|
|
225
|
+
{
|
226
|
+
dog {
|
227
|
+
name: nickname
|
228
|
+
name
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|}
|
232
|
+
|
233
|
+
it "fails rule" do
|
234
|
+
assert_equal ["Field 'name' has a field conflict: nickname or name?"], error_messages
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "different args, second adds an argument" do
|
239
|
+
let(:query_string) {%|
|
240
|
+
{
|
241
|
+
dog {
|
242
|
+
doesKnowCommand
|
243
|
+
doesKnowCommand(dogCommand: HEEL)
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|}
|
247
|
+
|
248
|
+
it "fails rule" do
|
249
|
+
assert_equal [%q(Field 'doesKnowCommand' has an argument conflict: {} or {"dogCommand":"HEEL"}?)], error_messages
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "different args, second missing an argument" do
|
254
|
+
let(:query_string) {%|
|
255
|
+
{
|
256
|
+
dog {
|
257
|
+
doesKnowCommand(dogCommand: SIT)
|
258
|
+
doesKnowCommand
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|}
|
262
|
+
|
263
|
+
it "fails rule" do
|
264
|
+
assert_equal [%q(Field 'doesKnowCommand' has an argument conflict: {"dogCommand":"SIT"} or {}?)], error_messages
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "conflicting args" do
|
269
|
+
let(:query_string) {%|
|
270
|
+
{
|
271
|
+
dog {
|
272
|
+
doesKnowCommand(dogCommand: SIT)
|
273
|
+
doesKnowCommand(dogCommand: HEEL)
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|}
|
277
|
+
|
278
|
+
it "fails rule" do
|
279
|
+
assert_equal [%q(Field 'doesKnowCommand' has an argument conflict: {"dogCommand":"SIT"} or {"dogCommand":"HEEL"}?)], error_messages
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe "conflicting arg values" do
|
284
|
+
let(:query_string) {%|
|
285
|
+
{
|
286
|
+
toy {
|
287
|
+
image(maxWidth: 10)
|
288
|
+
image(maxWidth: 20)
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|}
|
292
|
+
|
293
|
+
it "fails rule" do
|
294
|
+
assert_equal [%q(Field 'image' has an argument conflict: {"maxWidth":"10"} or {"maxWidth":"20"}?)], error_messages
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "encounters conflict in fragments" do
|
299
|
+
let(:query_string) {%|
|
300
|
+
{
|
301
|
+
pet {
|
302
|
+
...A
|
303
|
+
...B
|
304
|
+
name
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
fragment A on Dog {
|
309
|
+
x: name
|
310
|
+
}
|
311
|
+
|
312
|
+
fragment B on Dog {
|
313
|
+
x: nickname
|
314
|
+
name: nickname
|
315
|
+
}
|
316
|
+
|}
|
317
|
+
|
318
|
+
it "fails rule" do
|
319
|
+
assert_equal [
|
320
|
+
"Field 'x' has a field conflict: name or nickname?",
|
321
|
+
"Field 'name' has a field conflict: nickname or name?",
|
322
|
+
], error_messages
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
describe "deep conflict" do
|
327
|
+
let(:query_string) {%|
|
328
|
+
{
|
329
|
+
dog {
|
330
|
+
x: name
|
331
|
+
}
|
332
|
+
|
333
|
+
dog {
|
334
|
+
x: nickname
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|}
|
338
|
+
|
339
|
+
it "fails rule" do
|
340
|
+
assert_equal ["Field 'x' has a field conflict: name or nickname?"], error_messages
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "deep conflict with multiple issues" do
|
345
|
+
let(:query_string) {%|
|
346
|
+
{
|
347
|
+
dog {
|
348
|
+
x: name
|
349
|
+
y: barkVolume
|
350
|
+
}
|
351
|
+
|
352
|
+
dog {
|
353
|
+
x: nickname
|
354
|
+
y: doesKnowCommand
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|}
|
358
|
+
|
359
|
+
it "fails rule" do
|
360
|
+
assert_equal [
|
361
|
+
"Field 'x' has a field conflict: name or nickname?",
|
362
|
+
"Field 'y' has a field conflict: barkVolume or doesKnowCommand?",
|
363
|
+
], error_messages
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe "very deep conflict" do
|
368
|
+
let(:query_string) {%|
|
369
|
+
{
|
370
|
+
dog {
|
371
|
+
toys {
|
372
|
+
x: name
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
dog {
|
377
|
+
toys {
|
378
|
+
x: size
|
379
|
+
}
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|}
|
383
|
+
|
384
|
+
it "fails rule" do
|
385
|
+
assert_equal [
|
386
|
+
"Field 'x' has a field conflict: name or size?",
|
387
|
+
], error_messages
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe "return types must be unambiguous" do
|
392
|
+
let(:schema) {
|
393
|
+
GraphQL::Schema.from_definition(%|
|
394
|
+
type Query {
|
395
|
+
someBox: SomeBox
|
396
|
+
connection: Connection
|
397
|
+
}
|
398
|
+
|
399
|
+
type Edge {
|
400
|
+
id: ID
|
401
|
+
name: String
|
402
|
+
}
|
403
|
+
|
404
|
+
interface SomeBox {
|
405
|
+
deepBox: SomeBox
|
406
|
+
unrelatedField: String
|
407
|
+
}
|
408
|
+
|
409
|
+
type StringBox implements SomeBox {
|
410
|
+
scalar: String
|
411
|
+
deepBox: StringBox
|
412
|
+
unrelatedField: String
|
413
|
+
listStringBox: [StringBox]
|
414
|
+
stringBox: StringBox
|
415
|
+
intBox: IntBox
|
416
|
+
}
|
417
|
+
|
418
|
+
type IntBox implements SomeBox {
|
419
|
+
scalar: Int
|
420
|
+
deepBox: IntBox
|
421
|
+
unrelatedField: String
|
422
|
+
listStringBox: [StringBox]
|
423
|
+
stringBox: StringBox
|
424
|
+
intBox: IntBox
|
425
|
+
}
|
426
|
+
|
427
|
+
interface NonNullStringBox1 {
|
428
|
+
scalar: String!
|
429
|
+
}
|
430
|
+
|
431
|
+
type NonNullStringBox1Impl implements SomeBox, NonNullStringBox1 {
|
432
|
+
scalar: String!
|
433
|
+
unrelatedField: String
|
434
|
+
deepBox: SomeBox
|
435
|
+
}
|
436
|
+
|
437
|
+
interface NonNullStringBox2 {
|
438
|
+
scalar: String!
|
439
|
+
}
|
440
|
+
|
441
|
+
type NonNullStringBox2Impl implements SomeBox, NonNullStringBox2 {
|
442
|
+
scalar: String!
|
443
|
+
unrelatedField: String
|
444
|
+
deepBox: SomeBox
|
445
|
+
}
|
446
|
+
|
447
|
+
type Connection {
|
448
|
+
edges: [Edge]
|
449
|
+
}
|
450
|
+
|)
|
26
451
|
}
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
452
|
+
|
453
|
+
describe "compatible return shapes on different return types" do
|
454
|
+
let(:query_string) {%|
|
455
|
+
{
|
456
|
+
someBox {
|
457
|
+
... on SomeBox {
|
458
|
+
deepBox {
|
459
|
+
unrelatedField
|
460
|
+
}
|
461
|
+
}
|
462
|
+
... on StringBox {
|
463
|
+
deepBox {
|
464
|
+
unrelatedField
|
465
|
+
}
|
466
|
+
}
|
467
|
+
}
|
468
|
+
}
|
469
|
+
|}
|
470
|
+
|
471
|
+
it "passes rule" do
|
472
|
+
assert_equal [], errors
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
describe "reports correctly when a non-exclusive follows an exclusive" do
|
477
|
+
let(:query_string) {%|
|
478
|
+
{
|
479
|
+
someBox {
|
480
|
+
... on IntBox {
|
481
|
+
deepBox {
|
482
|
+
...X
|
483
|
+
}
|
484
|
+
}
|
485
|
+
}
|
486
|
+
someBox {
|
487
|
+
... on StringBox {
|
488
|
+
deepBox {
|
489
|
+
...Y
|
490
|
+
}
|
491
|
+
}
|
492
|
+
}
|
493
|
+
memoed: someBox {
|
494
|
+
... on IntBox {
|
495
|
+
deepBox {
|
496
|
+
...X
|
497
|
+
}
|
498
|
+
}
|
499
|
+
}
|
500
|
+
memoed: someBox {
|
501
|
+
... on StringBox {
|
502
|
+
deepBox {
|
503
|
+
...Y
|
504
|
+
}
|
505
|
+
}
|
506
|
+
}
|
507
|
+
other: someBox {
|
508
|
+
...X
|
509
|
+
}
|
510
|
+
other: someBox {
|
511
|
+
...Y
|
512
|
+
}
|
513
|
+
}
|
514
|
+
fragment X on SomeBox {
|
515
|
+
scalar
|
516
|
+
}
|
517
|
+
fragment Y on SomeBox {
|
518
|
+
scalar: unrelatedField
|
519
|
+
}
|
520
|
+
|}
|
521
|
+
|
522
|
+
it "fails rule" do
|
523
|
+
assert_includes error_messages, "Field 'scalar' has a field conflict: scalar or unrelatedField?"
|
524
|
+
end
|
525
|
+
end
|
42
526
|
end
|
43
527
|
end
|