graphql 1.8.7 → 1.9.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/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/scalar_generator.rb +20 -0
- data/lib/generators/graphql/templates/base_scalar.erb +4 -0
- data/lib/generators/graphql/templates/scalar.erb +13 -0
- data/lib/graphql/analysis/ast/analyzer.rb +62 -0
- data/lib/graphql/analysis/ast/field_usage.rb +28 -0
- data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
- data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
- data/lib/graphql/analysis/ast/query_depth.rb +66 -0
- data/lib/graphql/analysis/ast/visitor.rb +255 -0
- data/lib/graphql/analysis/ast.rb +82 -0
- data/lib/graphql/analysis.rb +1 -0
- data/lib/graphql/argument.rb +5 -0
- data/lib/graphql/authorization.rb +1 -0
- data/lib/graphql/backwards_compatibility.rb +1 -1
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/directive/include_directive.rb +1 -7
- data/lib/graphql/directive/skip_directive.rb +1 -8
- data/lib/graphql/directive.rb +13 -1
- data/lib/graphql/enum_type.rb +8 -0
- data/lib/graphql/execution/execute.rb +36 -17
- data/lib/graphql/execution/instrumentation.rb +2 -0
- data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
- data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
- data/lib/graphql/execution/interpreter/resolve.rb +58 -0
- data/lib/graphql/execution/interpreter/runtime.rb +597 -0
- data/lib/graphql/execution/interpreter.rb +99 -0
- data/lib/graphql/execution/lazy.rb +8 -1
- data/lib/graphql/execution/lookahead.rb +351 -0
- data/lib/graphql/execution/multiplex.rb +37 -29
- data/lib/graphql/execution.rb +2 -0
- data/lib/graphql/execution_error.rb +1 -1
- data/lib/graphql/field.rb +1 -7
- data/lib/graphql/integer_encoding_error.rb +12 -0
- data/lib/graphql/internal_representation/rewrite.rb +127 -142
- data/lib/graphql/introspection/dynamic_fields.rb +8 -2
- data/lib/graphql/introspection/entry_points.rb +11 -6
- data/lib/graphql/introspection/enum_value_type.rb +4 -0
- data/lib/graphql/introspection/schema_type.rb +7 -2
- data/lib/graphql/introspection/type_type.rb +9 -5
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +10 -7
- data/lib/graphql/language/lexer.rb +55 -36
- data/lib/graphql/language/lexer.rl +8 -3
- data/lib/graphql/language/nodes.rb +440 -362
- data/lib/graphql/language/parser.rb +56 -56
- data/lib/graphql/language/parser.y +12 -12
- data/lib/graphql/language/printer.rb +2 -2
- data/lib/graphql/language/visitor.rb +158 -15
- data/lib/graphql/language.rb +0 -1
- data/lib/graphql/literal_validation_error.rb +6 -0
- data/lib/graphql/query/arguments.rb +3 -2
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +14 -5
- data/lib/graphql/query/executor.rb +1 -1
- data/lib/graphql/query/result.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +35 -11
- data/lib/graphql/query/variable_validation_error.rb +10 -1
- data/lib/graphql/query.rb +16 -2
- data/lib/graphql/relay/base_connection.rb +2 -0
- data/lib/graphql/relay/connection_instrumentation.rb +3 -1
- data/lib/graphql/relay/connection_resolve.rb +1 -1
- data/lib/graphql/relay/node.rb +2 -28
- data/lib/graphql/relay/relation_connection.rb +1 -1
- data/lib/graphql/schema/argument.rb +13 -5
- data/lib/graphql/schema/base_64_encoder.rb +4 -4
- data/lib/graphql/schema/build_from_definition.rb +2 -4
- data/lib/graphql/schema/default_type_error.rb +1 -1
- 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/directive.rb +103 -0
- data/lib/graphql/schema/enum_value.rb +3 -2
- data/lib/graphql/schema/field/connection_extension.rb +50 -0
- data/lib/graphql/schema/field/scope_extension.rb +18 -0
- data/lib/graphql/schema/field.rb +273 -64
- data/lib/graphql/schema/field_extension.rb +69 -0
- data/lib/graphql/schema/input_object.rb +16 -8
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/loader.rb +22 -16
- data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
- data/lib/graphql/schema/member/build_type.rb +33 -1
- data/lib/graphql/schema/member/has_arguments.rb +6 -2
- data/lib/graphql/schema/member/has_fields.rb +18 -70
- data/lib/graphql/schema/member/has_path.rb +25 -0
- data/lib/graphql/schema/member/instrumentation.rb +10 -7
- data/lib/graphql/schema/member.rb +2 -0
- data/lib/graphql/schema/mutation.rb +6 -48
- data/lib/graphql/schema/non_null.rb +5 -1
- data/lib/graphql/schema/object.rb +18 -4
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
- data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
- data/lib/graphql/schema/resolver.rb +45 -20
- data/lib/graphql/schema/subscription.rb +97 -0
- data/lib/graphql/schema/traversal.rb +11 -7
- data/lib/graphql/schema.rb +186 -38
- data/lib/graphql/static_validation/all_rules.rb +3 -2
- data/lib/graphql/static_validation/base_visitor.rb +199 -0
- data/lib/graphql/static_validation/default_visitor.rb +15 -0
- data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
- 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/no_validate_visitor.rb +10 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
- 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 +11 -11
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
- 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 +19 -14
- 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 +17 -19
- 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 +30 -14
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
- 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 +37 -29
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
- 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 +16 -16
- 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 +21 -14
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
- 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 +25 -17
- 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 +17 -18
- 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 +10 -14
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
- 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 +35 -27
- 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 +15 -14
- 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 +41 -30
- 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 +18 -14
- 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 +73 -65
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/validation_context.rb +8 -51
- data/lib/graphql/static_validation/validator.rb +23 -15
- data/lib/graphql/static_validation.rb +5 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
- data/lib/graphql/subscriptions/event.rb +28 -5
- data/lib/graphql/subscriptions/subscription_root.rb +66 -0
- data/lib/graphql/subscriptions.rb +16 -2
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
- data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
- data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
- data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
- data/lib/graphql/tracing/platform_tracing.rb +17 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
- data/lib/graphql/tracing/scout_tracing.rb +1 -1
- data/lib/graphql/tracing/skylight_tracing.rb +3 -3
- data/lib/graphql/tracing.rb +8 -8
- data/lib/graphql/types/float.rb +1 -1
- data/lib/graphql/types/int.rb +11 -2
- data/lib/graphql/types/iso_8601_date_time.rb +15 -1
- data/lib/graphql/types/relay/base_connection.rb +15 -1
- data/lib/graphql/types/relay/node.rb +0 -1
- data/lib/graphql/types/relay/node_field.rb +43 -0
- data/lib/graphql/types/relay/nodes_field.rb +45 -0
- data/lib/graphql/types/relay.rb +2 -0
- data/lib/graphql/unauthorized_error.rb +4 -0
- data/lib/graphql/unauthorized_field_error.rb +23 -0
- data/lib/graphql/upgrader/member.rb +5 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +6 -1
- data/readme.md +7 -7
- data/spec/dummy/Gemfile +1 -1
- data/spec/dummy/Gemfile.lock +157 -0
- data/spec/dummy/app/channels/graphql_channel.rb +22 -11
- data/spec/dummy/config/locales/en.yml +1 -1
- data/spec/dummy/log/test.log +199 -0
- data/spec/dummy/test/test_helper.rb +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
- data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
- data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
- data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
- data/spec/graphql/analysis/ast_spec.rb +269 -0
- data/spec/graphql/authorization_spec.rb +120 -23
- data/spec/graphql/base_type_spec.rb +6 -4
- data/spec/graphql/enum_type_spec.rb +6 -1
- data/spec/graphql/execution/execute_spec.rb +9 -9
- data/spec/graphql/execution/instrumentation_spec.rb +19 -0
- data/spec/graphql/execution/interpreter_spec.rb +485 -0
- data/spec/graphql/execution/lazy_spec.rb +67 -1
- data/spec/graphql/execution/lookahead_spec.rb +363 -0
- data/spec/graphql/execution/multiplex_spec.rb +31 -3
- data/spec/graphql/execution/typecast_spec.rb +20 -20
- data/spec/graphql/execution_error_spec.rb +110 -96
- data/spec/graphql/field_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +13 -352
- data/spec/graphql/int_type_spec.rb +19 -0
- data/spec/graphql/interface_type_spec.rb +4 -4
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
- data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
- data/spec/graphql/introspection/type_type_spec.rb +1 -2
- data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
- data/spec/graphql/language/lexer_spec.rb +72 -3
- data/spec/graphql/language/nodes_spec.rb +20 -0
- data/spec/graphql/language/printer_spec.rb +18 -6
- data/spec/graphql/language/visitor_spec.rb +320 -14
- data/spec/graphql/non_null_type_spec.rb +1 -1
- data/spec/graphql/object_type_spec.rb +32 -27
- data/spec/graphql/query/arguments_spec.rb +21 -0
- data/spec/graphql/query/context_spec.rb +28 -0
- data/spec/graphql/query/executor_spec.rb +40 -36
- data/spec/graphql/query_spec.rb +12 -6
- data/spec/graphql/schema/argument_spec.rb +35 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
- data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
- 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 +12 -3
- data/spec/graphql/schema/enum_value_spec.rb +11 -0
- data/spec/graphql/schema/field_extension_spec.rb +115 -0
- data/spec/graphql/schema/field_spec.rb +47 -7
- data/spec/graphql/schema/input_object_spec.rb +95 -0
- data/spec/graphql/schema/instrumentation_spec.rb +3 -0
- data/spec/graphql/schema/interface_spec.rb +8 -2
- data/spec/graphql/schema/introspection_system_spec.rb +9 -1
- data/spec/graphql/schema/loader_spec.rb +5 -0
- data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
- data/spec/graphql/schema/member/build_type_spec.rb +46 -0
- data/spec/graphql/schema/member/scoped_spec.rb +19 -3
- data/spec/graphql/schema/mutation_spec.rb +5 -3
- data/spec/graphql/schema/object_spec.rb +9 -1
- data/spec/graphql/schema/printer_spec.rb +255 -93
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
- data/spec/graphql/schema/resolver_spec.rb +173 -9
- data/spec/graphql/schema/scalar_spec.rb +6 -0
- data/spec/graphql/schema/subscription_spec.rb +416 -0
- data/spec/graphql/schema/traversal_spec.rb +10 -10
- data/spec/graphql/schema/type_expression_spec.rb +2 -2
- data/spec/graphql/schema/union_spec.rb +7 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +145 -88
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
- 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 +131 -5
- 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 +23 -3
- data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
- data/spec/graphql/static_validation/validator_spec.rb +50 -2
- data/spec/graphql/subscriptions_spec.rb +27 -16
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
- data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
- data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
- data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
- data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
- data/spec/graphql/union_type_spec.rb +2 -2
- data/spec/graphql/upgrader/member_spec.rb +67 -0
- data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
- data/spec/integration/mongoid/spec_helper.rb +2 -0
- data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
- data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
- data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
- data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
- data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
- data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
- data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
- data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
- data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
- data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
- data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
- data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
- data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
- data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
- data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
- data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
- data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
- data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
- data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
- data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
- data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
- data/spec/integration/rails/spec_helper.rb +25 -0
- data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
- data/spec/spec_helper.rb +23 -39
- data/spec/support/dummy/data.rb +20 -17
- data/spec/support/dummy/schema.rb +315 -305
- data/spec/support/error_bubbling_helpers.rb +23 -0
- data/spec/support/jazz.rb +213 -46
- data/spec/support/lazy_helpers.rb +69 -27
- data/spec/support/new_relic.rb +3 -0
- data/spec/support/skylight.rb +3 -0
- data/spec/support/star_wars/schema.rb +131 -81
- data/spec/support/static_validation_helpers.rb +9 -5
- metadata +418 -261
- data/lib/graphql/language/comments.rb +0 -45
- data/lib/graphql/static_validation/arguments_validator.rb +0 -50
- data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
- data/spec/rails_dependency_sanity_spec.rb +0 -14
@@ -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
|
@@ -39,13 +39,18 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
39
39
|
species: PetSpecies!
|
40
40
|
}
|
41
41
|
|
42
|
+
interface Mammal {
|
43
|
+
name(surname: Boolean = false): String!
|
44
|
+
nickname: String
|
45
|
+
}
|
46
|
+
|
42
47
|
interface Pet {
|
43
48
|
name(surname: Boolean = false): String!
|
44
49
|
nickname: String
|
45
50
|
toys: [Toy!]!
|
46
51
|
}
|
47
52
|
|
48
|
-
type Dog implements Pet {
|
53
|
+
type Dog implements Pet & Mammal {
|
49
54
|
name(surname: Boolean = false): String!
|
50
55
|
nickname: String
|
51
56
|
doesKnowCommand(dogCommand: PetCommand): Boolean!
|
@@ -53,7 +58,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
53
58
|
toys: [Toy!]!
|
54
59
|
}
|
55
60
|
|
56
|
-
type Cat implements Pet {
|
61
|
+
type Cat implements Pet & Mammal {
|
57
62
|
name(surname: Boolean = false): String!
|
58
63
|
nickname: String
|
59
64
|
doesKnowCommand(catCommand: PetCommand): Boolean!
|
@@ -348,12 +353,13 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
348
353
|
|
349
354
|
it "fails rule" do
|
350
355
|
assert_equal [
|
351
|
-
"Field 'name' has a field conflict: name or nickname?",
|
352
356
|
"Field 'x' has a field conflict: name or nickname?",
|
357
|
+
"Field 'name' has a field conflict: name or nickname?"
|
353
358
|
], error_messages
|
354
359
|
end
|
355
360
|
end
|
356
361
|
|
362
|
+
|
357
363
|
describe "deep conflict" do
|
358
364
|
let(:query_string) {%|
|
359
365
|
{
|
@@ -375,7 +381,8 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
375
381
|
{"line"=>4, "column"=>11},
|
376
382
|
{"line"=>8, "column"=>11}
|
377
383
|
],
|
378
|
-
"
|
384
|
+
"path"=>[],
|
385
|
+
"extensions"=>{"code"=>"fieldConflict", "fieldName"=>"x", "conflicts"=>"name or nickname"}
|
379
386
|
}
|
380
387
|
]
|
381
388
|
assert_equal expected_errors, errors
|
@@ -429,6 +436,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
429
436
|
end
|
430
437
|
end
|
431
438
|
|
439
|
+
|
432
440
|
describe "same aliases allowed on non-overlapping fields" do
|
433
441
|
let(:query_string) {%|
|
434
442
|
{
|
@@ -448,6 +456,53 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
448
456
|
end
|
449
457
|
end
|
450
458
|
|
459
|
+
describe "same aliases not allowed on different interfaces" do
|
460
|
+
let(:query_string) {%|
|
461
|
+
{
|
462
|
+
pet {
|
463
|
+
... on Pet {
|
464
|
+
name
|
465
|
+
}
|
466
|
+
... on Mammal {
|
467
|
+
name: nickname
|
468
|
+
}
|
469
|
+
}
|
470
|
+
}
|
471
|
+
|}
|
472
|
+
|
473
|
+
it "fails rule" do
|
474
|
+
assert_equal [
|
475
|
+
"Field 'name' has a field conflict: name or nickname?",
|
476
|
+
], error_messages
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
describe "same aliases allowed on different parent interfaces and different concrete types" do
|
481
|
+
let(:query_string) {%|
|
482
|
+
{
|
483
|
+
pet {
|
484
|
+
... on Pet {
|
485
|
+
...X
|
486
|
+
}
|
487
|
+
... on Mammal {
|
488
|
+
...Y
|
489
|
+
}
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
fragment X on Dog {
|
494
|
+
name
|
495
|
+
}
|
496
|
+
fragment Y on Cat {
|
497
|
+
name: nickname
|
498
|
+
}
|
499
|
+
|}
|
500
|
+
|
501
|
+
it "passes rule" do
|
502
|
+
assert_equal [], errors
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
451
506
|
describe "allows different args where no conflict is possible" do
|
452
507
|
let(:query_string) {%|
|
453
508
|
{
|
@@ -473,6 +528,77 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
473
528
|
it "passes rule" do
|
474
529
|
assert_equal [], errors
|
475
530
|
end
|
531
|
+
|
532
|
+
describe "allows different args where no conflict is possible" do
|
533
|
+
let(:query_string) {%|
|
534
|
+
{
|
535
|
+
pet {
|
536
|
+
... on Dog {
|
537
|
+
... on Pet {
|
538
|
+
name
|
539
|
+
}
|
540
|
+
}
|
541
|
+
... on Cat {
|
542
|
+
name(surname: true)
|
543
|
+
}
|
544
|
+
}
|
545
|
+
}
|
546
|
+
|}
|
547
|
+
|
548
|
+
it "passes rule" do
|
549
|
+
assert_equal [], errors
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
describe "allows different args where no conflict is possible with uneven abstract scoping" do
|
554
|
+
let(:query_string) {%|
|
555
|
+
{
|
556
|
+
pet {
|
557
|
+
... on Pet {
|
558
|
+
... on Dog {
|
559
|
+
name
|
560
|
+
}
|
561
|
+
}
|
562
|
+
... on Cat {
|
563
|
+
name(surname: true)
|
564
|
+
}
|
565
|
+
}
|
566
|
+
}
|
567
|
+
|}
|
568
|
+
|
569
|
+
it "passes rule" do
|
570
|
+
assert_equal [], errors
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
describe "allows different args where no conflict is possible deep" do
|
576
|
+
let(:query_string) {%|
|
577
|
+
{
|
578
|
+
pet {
|
579
|
+
... on Dog {
|
580
|
+
...X
|
581
|
+
}
|
582
|
+
}
|
583
|
+
pet {
|
584
|
+
... on Cat {
|
585
|
+
...Y
|
586
|
+
}
|
587
|
+
}
|
588
|
+
}
|
589
|
+
|
590
|
+
fragment X on Pet {
|
591
|
+
name(surname: true)
|
592
|
+
}
|
593
|
+
|
594
|
+
fragment Y on Pet {
|
595
|
+
name
|
596
|
+
}
|
597
|
+
|}
|
598
|
+
|
599
|
+
it "passes rule" do
|
600
|
+
assert_equal [], errors
|
601
|
+
end
|
476
602
|
end
|
477
603
|
|
478
604
|
describe "return types must be unambiguous" do
|
@@ -599,7 +725,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
599
725
|
}
|
600
726
|
}
|
601
727
|
fragment X on SomeBox {
|
602
|
-
scalar: deepBox {
|
728
|
+
scalar: deepBox { unrelatedField }
|
603
729
|
}
|
604
730
|
fragment Y on SomeBox {
|
605
731
|
scalar: unrelatedField
|
@@ -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
|
@@ -22,21 +22,24 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
|
|
22
22
|
query_root_error = {
|
23
23
|
"message"=>"Field 'cheese' is missing required arguments: id",
|
24
24
|
"locations"=>[{"line"=>4, "column"=>7}],
|
25
|
-
"
|
25
|
+
"path"=>["query getCheese", "cheese"],
|
26
|
+
"extensions"=>{"code"=>"missingRequiredArguments", "className"=>"Field", "name"=>"cheese", "arguments"=>"id"}
|
26
27
|
}
|
27
28
|
assert_includes(errors, query_root_error)
|
28
29
|
|
29
30
|
fragment_error = {
|
30
31
|
"message"=>"Field 'similarCheese' is missing required arguments: source",
|
31
32
|
"locations"=>[{"line"=>8, "column"=>7}],
|
32
|
-
"
|
33
|
+
"path"=>["fragment cheeseFields", "similarCheese"],
|
34
|
+
"extensions"=>{"code"=>"missingRequiredArguments", "className"=>"Field", "name"=>"similarCheese", "arguments"=>"source"}
|
33
35
|
}
|
34
36
|
assert_includes(errors, fragment_error)
|
35
37
|
|
36
38
|
directive_error = {
|
37
39
|
"message"=>"Directive 'skip' is missing required arguments: if",
|
38
40
|
"locations"=>[{"line"=>10, "column"=>10}],
|
39
|
-
"
|
41
|
+
"path"=>["fragment cheeseFields", "id"],
|
42
|
+
"extensions"=>{"code"=>"missingRequiredArguments", "className"=>"Directive", "name"=>"skip", "arguments"=>"if"}
|
40
43
|
}
|
41
44
|
assert_includes(errors, directive_error)
|
42
45
|
end
|
@@ -55,7 +58,13 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
|
|
55
58
|
"locations"=>[
|
56
59
|
{"line"=>3, "column"=>9}
|
57
60
|
],
|
58
|
-
"
|
61
|
+
"path"=>["query", "__type"],
|
62
|
+
"extensions"=>{
|
63
|
+
"code"=>"missingRequiredArguments",
|
64
|
+
"className"=>"Field",
|
65
|
+
"name"=>"__type",
|
66
|
+
"arguments"=>"name"
|
67
|
+
}
|
59
68
|
}
|
60
69
|
]
|
61
70
|
assert_equal(expected_errors, errors)
|
data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe GraphQL::StaticValidation::RequiredInputObjectAttributesArePresent do
|
5
|
+
include StaticValidationHelpers
|
6
|
+
include ErrorBubblingHelpers
|
7
|
+
|
8
|
+
let(:query_string) {%|
|
9
|
+
query getCheese {
|
10
|
+
stringCheese: cheese(id: "aasdlkfj") { ...cheeseFields }
|
11
|
+
cheese(id: 1) { source @skip(if: "whatever") }
|
12
|
+
yakSource: searchDairy(product: [{source: COW, fatContent: 1.1}]) { __typename }
|
13
|
+
badSource: searchDairy(product: [{source: 1.1}]) { __typename }
|
14
|
+
missingSource: searchDairy(product: [{fatContent: 1.1}]) { __typename }
|
15
|
+
listCoerce: cheese(id: 1) { similarCheese(source: YAK) { __typename } }
|
16
|
+
missingInputField: searchDairy(product: [{source: YAK, wacky: 1}]) { __typename }
|
17
|
+
}
|
18
|
+
|
19
|
+
fragment cheeseFields on Cheese {
|
20
|
+
similarCheese(source: 4.5) { __typename }
|
21
|
+
}
|
22
|
+
|}
|
23
|
+
describe "with error bubbling disabled" do
|
24
|
+
missing_required_field_error = {
|
25
|
+
"message"=>"Argument 'product' on Field 'missingSource' has an invalid value. Expected type '[DairyProductInput]'.",
|
26
|
+
"locations"=>[{"line"=>7, "column"=>7}],
|
27
|
+
"path"=>["query getCheese", "missingSource", "product"],
|
28
|
+
"extensions"=>{
|
29
|
+
"code"=>"argumentLiteralsIncompatible",
|
30
|
+
"typeName"=>"Field",
|
31
|
+
"argumentName"=>"product",
|
32
|
+
},
|
33
|
+
}
|
34
|
+
missing_source_error = {
|
35
|
+
"message"=>"Argument 'source' on InputObject 'DairyProductInput' is required. Expected type DairyAnimal!",
|
36
|
+
"locations"=>[{"line"=>7, "column"=>44}],
|
37
|
+
"path"=>["query getCheese", "missingSource", "product", "source"],
|
38
|
+
"extensions"=>{
|
39
|
+
"code"=>"missingRequiredInputObjectAttribute",
|
40
|
+
"argumentName"=>"source",
|
41
|
+
"argumentType"=>"DairyAnimal!",
|
42
|
+
"inputObjectType"=>"DairyProductInput"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
it "finds undefined or missing-required arguments to fields and directives" do
|
46
|
+
without_error_bubbling(schema) do
|
47
|
+
assert_includes(errors, missing_source_error)
|
48
|
+
refute_includes(errors, missing_required_field_error)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
it 'works with error bubbling enabled' do
|
52
|
+
with_error_bubbling(schema) do
|
53
|
+
assert_includes(errors, missing_required_field_error)
|
54
|
+
assert_includes(errors, missing_source_error)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -26,7 +26,8 @@ describe GraphQL::StaticValidation::SubscriptionRootExists do
|
|
26
26
|
missing_subscription_root_error = {
|
27
27
|
"message"=>"Schema is not configured for subscriptions",
|
28
28
|
"locations"=>[{"line"=>2, "column"=>5}],
|
29
|
-
"
|
29
|
+
"path"=>["subscription"],
|
30
|
+
"extensions"=>{"code"=>"missingSubscriptionConfiguration"}
|
30
31
|
}
|
31
32
|
assert_includes(errors, missing_subscription_root_error)
|
32
33
|
end
|
@@ -101,7 +101,8 @@ describe GraphQL::StaticValidation::UniqueDirectivesPerLocation do
|
|
101
101
|
assert_includes errors, {
|
102
102
|
"message" => 'The directive "A" can only be used once at this location.',
|
103
103
|
"locations" => [{ "line" => 4, "column" => 17 }, { "line" => 4, "column" => 20 }],
|
104
|
-
"
|
104
|
+
"path" => ["query", "type", "field"],
|
105
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
105
106
|
}
|
106
107
|
end
|
107
108
|
end
|
@@ -120,13 +121,15 @@ describe GraphQL::StaticValidation::UniqueDirectivesPerLocation do
|
|
120
121
|
assert_includes errors, {
|
121
122
|
"message" => 'The directive "A" can only be used once at this location.',
|
122
123
|
"locations" => [{ "line" => 4, "column" => 17 }, { "line" => 4, "column" => 20 }],
|
123
|
-
"
|
124
|
+
"path" => ["query", "type", "field"],
|
125
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
124
126
|
}
|
125
127
|
|
126
128
|
assert_includes errors, {
|
127
129
|
"message" => 'The directive "A" can only be used once at this location.',
|
128
130
|
"locations" => [{ "line" => 4, "column" => 17 }, { "line" => 4, "column" => 23 }],
|
129
|
-
"
|
131
|
+
"path" => ["query", "type", "field"],
|
132
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
130
133
|
}
|
131
134
|
end
|
132
135
|
end
|
@@ -144,13 +147,15 @@ describe GraphQL::StaticValidation::UniqueDirectivesPerLocation do
|
|
144
147
|
assert_includes errors, {
|
145
148
|
"message" => 'The directive "A" can only be used once at this location.',
|
146
149
|
"locations" => [{ "line" => 4, "column" => 17 }, { "line" => 4, "column" => 23 }],
|
147
|
-
"
|
150
|
+
"path" => ["query", "type", "field"],
|
151
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
148
152
|
}
|
149
153
|
|
150
154
|
assert_includes errors, {
|
151
155
|
"message" => 'The directive "B" can only be used once at this location.',
|
152
156
|
"locations" => [{ "line" => 4, "column" => 20 }, { "line" => 4, "column" => 26 }],
|
153
|
-
"
|
157
|
+
"path" => ["query", "type", "field"],
|
158
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"B"}
|
154
159
|
}
|
155
160
|
end
|
156
161
|
end
|
@@ -168,13 +173,15 @@ describe GraphQL::StaticValidation::UniqueDirectivesPerLocation do
|
|
168
173
|
assert_includes errors, {
|
169
174
|
"message" => 'The directive "A" can only be used once at this location.',
|
170
175
|
"locations" => [{ "line" => 3, "column" => 14 }, { "line" => 3, "column" => 17 }],
|
171
|
-
"
|
176
|
+
"path" => ["query", "type"],
|
177
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
172
178
|
}
|
173
179
|
|
174
180
|
assert_includes errors, {
|
175
181
|
"message" => 'The directive "A" can only be used once at this location.',
|
176
182
|
"locations" => [{ "line" => 4, "column" => 17 }, { "line" => 4, "column" => 20 }],
|
177
|
-
"
|
183
|
+
"path" => ["query", "type", "field"],
|
184
|
+
"extensions" => {"code"=>"directiveNotUniqueForLocation", "directiveName"=>"A"}
|
178
185
|
}
|
179
186
|
end
|
180
187
|
end
|