graphql 1.7.6 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/install_generator.rb +14 -8
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +6 -1
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/generators/graphql/templates/schema.erb +1 -1
- data/lib/graphql/argument.rb +25 -19
- data/lib/graphql/backtrace/tracer.rb +16 -22
- data/lib/graphql/backtrace.rb +1 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +31 -31
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +42 -0
- data/lib/graphql/directive.rb +1 -0
- data/lib/graphql/enum_type.rb +3 -1
- data/lib/graphql/execution/execute.rb +21 -13
- data/lib/graphql/execution/instrumentation.rb +82 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
- data/lib/graphql/execution/lazy/resolve.rb +1 -3
- data/lib/graphql/execution/multiplex.rb +12 -29
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/field.rb +21 -4
- data/lib/graphql/function.rb +14 -0
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/interface_type.rb +5 -3
- data/lib/graphql/internal_representation/node.rb +26 -14
- data/lib/graphql/internal_representation/visit.rb +3 -6
- data/lib/graphql/introspection/base_object.rb +16 -0
- data/lib/graphql/introspection/directive_location_enum.rb +11 -7
- data/lib/graphql/introspection/directive_type.rb +23 -16
- data/lib/graphql/introspection/dynamic_fields.rb +11 -0
- data/lib/graphql/introspection/entry_points.rb +29 -0
- data/lib/graphql/introspection/enum_value_type.rb +16 -11
- data/lib/graphql/introspection/field_type.rb +21 -12
- data/lib/graphql/introspection/input_value_type.rb +26 -23
- data/lib/graphql/introspection/schema_field.rb +7 -2
- data/lib/graphql/introspection/schema_type.rb +36 -22
- data/lib/graphql/introspection/type_by_name_field.rb +10 -2
- data/lib/graphql/introspection/type_kind_enum.rb +10 -6
- data/lib/graphql/introspection/type_type.rb +85 -23
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/introspection.rb +3 -10
- data/lib/graphql/language/block_string.rb +47 -0
- data/lib/graphql/language/document_from_schema_definition.rb +280 -0
- data/lib/graphql/language/generation.rb +3 -182
- data/lib/graphql/language/lexer.rb +144 -69
- data/lib/graphql/language/lexer.rl +15 -4
- data/lib/graphql/language/nodes.rb +141 -78
- data/lib/graphql/language/parser.rb +677 -630
- data/lib/graphql/language/parser.y +18 -12
- data/lib/graphql/language/printer.rb +361 -0
- data/lib/graphql/language/token.rb +10 -3
- data/lib/graphql/language.rb +3 -0
- data/lib/graphql/non_null_type.rb +1 -1
- data/lib/graphql/object_type.rb +1 -6
- data/lib/graphql/query/arguments.rb +63 -32
- data/lib/graphql/query/context.rb +32 -2
- data/lib/graphql/query/literal_input.rb +4 -1
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query/result.rb +1 -1
- data/lib/graphql/query/variables.rb +21 -3
- data/lib/graphql/query.rb +19 -6
- data/lib/graphql/railtie.rb +109 -0
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/connection_type.rb +5 -3
- data/lib/graphql/relay/edge_type.rb +2 -1
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
- data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
- data/lib/graphql/relay/mutation/resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +14 -19
- data/lib/graphql/relay/type_extensions.rb +30 -0
- data/lib/graphql/relay.rb +2 -0
- data/lib/graphql/scalar_type.rb +14 -2
- data/lib/graphql/schema/argument.rb +92 -0
- data/lib/graphql/schema/build_from_definition.rb +64 -18
- data/lib/graphql/schema/enum.rb +85 -0
- data/lib/graphql/schema/enum_value.rb +74 -0
- data/lib/graphql/schema/field.rb +372 -0
- data/lib/graphql/schema/finder.rb +153 -0
- data/lib/graphql/schema/input_object.rb +87 -0
- data/lib/graphql/schema/interface.rb +105 -0
- data/lib/graphql/schema/introspection_system.rb +93 -0
- data/lib/graphql/schema/late_bound_type.rb +32 -0
- data/lib/graphql/schema/list.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member/accepts_definition.rb +152 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
- data/lib/graphql/schema/member/build_type.rb +137 -0
- data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +50 -0
- data/lib/graphql/schema/member/has_fields.rb +130 -0
- data/lib/graphql/schema/member/instrumentation.rb +115 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
- data/lib/graphql/schema/member.rb +28 -0
- data/lib/graphql/schema/middleware_chain.rb +5 -1
- data/lib/graphql/schema/mutation.rb +138 -0
- data/lib/graphql/schema/non_null.rb +38 -0
- data/lib/graphql/schema/object.rb +81 -0
- data/lib/graphql/schema/printer.rb +33 -266
- data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
- data/lib/graphql/schema/rescue_middleware.rb +8 -7
- data/lib/graphql/schema/resolver.rb +122 -0
- data/lib/graphql/schema/scalar.rb +35 -0
- data/lib/graphql/schema/traversal.rb +102 -22
- data/lib/graphql/schema/union.rb +36 -0
- data/lib/graphql/schema/validation.rb +3 -2
- data/lib/graphql/schema.rb +381 -12
- data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
- data/lib/graphql/static_validation/literal_validator.rb +16 -4
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
- data/lib/graphql/static_validation/validation_context.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
- data/lib/graphql/subscriptions/instrumentation.rb +5 -1
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +90 -16
- data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
- data/lib/graphql/tracing/platform_tracing.rb +20 -7
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/unresolved_type_error.rb +3 -2
- data/lib/graphql/upgrader/member.rb +894 -0
- data/lib/graphql/upgrader/schema.rb +37 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +5 -25
- data/readme.md +2 -2
- data/spec/dummy/app/channels/graphql_channel.rb +23 -2
- data/spec/dummy/log/development.log +239 -0
- data/spec/dummy/log/test.log +410 -0
- data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/fixtures/upgrader/account.original.rb +19 -0
- data/spec/fixtures/upgrader/account.transformed.rb +20 -0
- data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
- data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
- data/spec/fixtures/upgrader/date_time.original.rb +24 -0
- data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
- data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
- data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
- data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
- data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
- data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
- data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
- data/spec/fixtures/upgrader/photo.original.rb +10 -0
- data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
- data/spec/fixtures/upgrader/release_order.original.rb +15 -0
- data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
- data/spec/fixtures/upgrader/starrable.original.rb +49 -0
- data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
- data/spec/fixtures/upgrader/type_x.original.rb +65 -0
- data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
- data/spec/generators/graphql/function_generator_spec.rb +26 -0
- data/spec/generators/graphql/install_generator_spec.rb +1 -1
- data/spec/generators/graphql/loader_generator_spec.rb +24 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/argument_spec.rb +21 -0
- data/spec/graphql/backtrace_spec.rb +10 -0
- data/spec/graphql/base_type_spec.rb +42 -0
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +3 -1
- data/spec/graphql/enum_type_spec.rb +18 -5
- data/spec/graphql/execution/execute_spec.rb +4 -4
- data/spec/graphql/execution/instrumentation_spec.rb +165 -0
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/execution_error_spec.rb +18 -0
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +15 -2
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/interface_type_spec.rb +12 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +2 -0
- data/spec/graphql/language/block_string_spec.rb +70 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
- data/spec/graphql/language/generation_spec.rb +21 -186
- data/spec/graphql/language/lexer_spec.rb +21 -1
- data/spec/graphql/language/nodes_spec.rb +21 -12
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/language/printer_spec.rb +203 -0
- data/spec/graphql/object_type_spec.rb +22 -0
- data/spec/graphql/query/arguments_spec.rb +25 -15
- data/spec/graphql/query/context_spec.rb +18 -0
- data/spec/graphql/query/executor_spec.rb +2 -1
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
- data/spec/graphql/query/variables_spec.rb +42 -1
- data/spec/graphql/query_spec.rb +31 -5
- data/spec/graphql/rake_task_spec.rb +3 -1
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
- data/spec/graphql/relay/mutation_spec.rb +9 -7
- data/spec/graphql/relay/range_add_spec.rb +5 -1
- data/spec/graphql/relay/relation_connection_spec.rb +65 -1
- data/spec/graphql/schema/argument_spec.rb +87 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
- data/spec/graphql/schema/enum_spec.rb +74 -0
- data/spec/graphql/schema/field_spec.rb +225 -0
- data/spec/graphql/schema/finder_spec.rb +135 -0
- data/spec/graphql/schema/input_object_spec.rb +111 -0
- data/spec/graphql/schema/instrumentation_spec.rb +40 -0
- data/spec/graphql/schema/interface_spec.rb +185 -0
- data/spec/graphql/schema/introspection_system_spec.rb +39 -0
- data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
- data/spec/graphql/schema/member/build_type_spec.rb +17 -0
- data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
- data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
- data/spec/graphql/schema/mutation_spec.rb +148 -0
- data/spec/graphql/schema/object_spec.rb +175 -0
- data/spec/graphql/schema/printer_spec.rb +111 -15
- data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
- data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
- data/spec/graphql/schema/resolver_spec.rb +131 -0
- data/spec/graphql/schema/scalar_spec.rb +95 -0
- data/spec/graphql/schema/traversal_spec.rb +31 -0
- data/spec/graphql/schema/union_spec.rb +65 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +55 -12
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +273 -184
- data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
- data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
- data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
- data/spec/graphql/union_type_spec.rb +1 -1
- data/spec/graphql/upgrader/member_spec.rb +516 -0
- data/spec/graphql/upgrader/schema_spec.rb +82 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/dummy/schema.rb +53 -24
- data/spec/support/jazz.rb +544 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/new_relic.rb +24 -0
- data/spec/support/star_trek/data.rb +109 -0
- data/spec/support/star_trek/schema.rb +388 -0
- data/spec/support/star_wars/data.rb +6 -7
- data/spec/support/star_wars/schema.rb +127 -171
- metadata +233 -11
- data/lib/graphql/introspection/arguments_field.rb +0 -7
- data/lib/graphql/introspection/enum_values_field.rb +0 -18
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -11
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -75,7 +75,7 @@ class InMemoryBackend
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
# Just a random stateful object for tracking what happens:
|
78
|
-
class
|
78
|
+
class SubscriptionPayload
|
79
79
|
attr_reader :str
|
80
80
|
|
81
81
|
def initialize
|
@@ -87,7 +87,65 @@ class InMemoryBackend
|
|
87
87
|
@counter += 1
|
88
88
|
end
|
89
89
|
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class ClassBasedInMemoryBackend < InMemoryBackend
|
93
|
+
class Payload < GraphQL::Schema::Object
|
94
|
+
field :str, String, null: false
|
95
|
+
field :int, Integer, null: false
|
96
|
+
end
|
97
|
+
|
98
|
+
class PayloadType < GraphQL::Schema::Enum
|
99
|
+
graphql_name "PayloadType"
|
100
|
+
# Arbitrary "kinds" of payloads which may be
|
101
|
+
# subscribed to separately
|
102
|
+
value "ONE"
|
103
|
+
value "TWO"
|
104
|
+
end
|
105
|
+
|
106
|
+
class StreamInput < GraphQL::Schema::InputObject
|
107
|
+
argument :user_id, ID, required: true
|
108
|
+
argument :type, PayloadType, required: false, default_value: "ONE"
|
109
|
+
end
|
110
|
+
|
111
|
+
class Subscription < GraphQL::Schema::Object
|
112
|
+
field :payload, Payload, null: false do
|
113
|
+
argument :id, ID, required: true
|
114
|
+
end
|
115
|
+
|
116
|
+
def payload(id:)
|
117
|
+
object
|
118
|
+
end
|
119
|
+
|
120
|
+
field :event, Payload, null: true do
|
121
|
+
argument :stream, StreamInput, required: false
|
122
|
+
end
|
123
|
+
|
124
|
+
def event(stream: nil)
|
125
|
+
object
|
126
|
+
end
|
127
|
+
|
128
|
+
field :my_event, Payload, null: true, subscription_scope: :me do
|
129
|
+
argument :type, PayloadType, required: false
|
130
|
+
end
|
131
|
+
|
132
|
+
def my_event(type: nil)
|
133
|
+
object
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Query < GraphQL::Schema::Object
|
138
|
+
field :dummy, Integer, null: true
|
139
|
+
end
|
140
|
+
|
141
|
+
class Schema < GraphQL::Schema
|
142
|
+
query(Query)
|
143
|
+
subscription(Subscription)
|
144
|
+
use InMemoryBackend::Subscriptions, extra: 123
|
145
|
+
end
|
146
|
+
end
|
90
147
|
|
148
|
+
class FromDefinitionInMemoryBackend < InMemoryBackend
|
91
149
|
SchemaDefinition = <<-GRAPHQL
|
92
150
|
type Subscription {
|
93
151
|
payload(id: ID!): Payload!
|
@@ -126,7 +184,7 @@ class InMemoryBackend
|
|
126
184
|
}
|
127
185
|
Schema = GraphQL::Schema.from_definition(SchemaDefinition, default_resolve: Resolvers).redefine do
|
128
186
|
use InMemoryBackend::Subscriptions,
|
129
|
-
|
187
|
+
extra: 123
|
130
188
|
end
|
131
189
|
|
132
190
|
# TODO don't hack this (no way to add metadata from IDL parser right now)
|
@@ -162,233 +220,264 @@ describe GraphQL::Subscriptions do
|
|
162
220
|
schema.subscriptions.reset
|
163
221
|
end
|
164
222
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
223
|
+
[ClassBasedInMemoryBackend, FromDefinitionInMemoryBackend].each do |in_memory_backend_class|
|
224
|
+
describe "using #{in_memory_backend_class}" do
|
225
|
+
let(:root_object) {
|
226
|
+
OpenStruct.new(
|
227
|
+
payload: in_memory_backend_class::SubscriptionPayload.new,
|
228
|
+
)
|
229
|
+
}
|
170
230
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
231
|
+
let(:schema) { in_memory_backend_class::Schema }
|
232
|
+
let(:implementation) { schema.subscriptions }
|
233
|
+
let(:deliveries) { implementation.deliveries }
|
234
|
+
describe "pushing updates" do
|
235
|
+
it "sends updated data" do
|
236
|
+
query_str = <<-GRAPHQL
|
177
237
|
subscription ($id: ID!){
|
178
238
|
firstPayload: payload(id: $id) { str, int }
|
179
239
|
otherPayload: payload(id: "900") { int }
|
180
240
|
}
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
241
|
+
GRAPHQL
|
242
|
+
|
243
|
+
# Initial subscriptions
|
244
|
+
res_1 = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
|
245
|
+
res_2 = schema.execute(query_str, context: { socket: "2" }, variables: { "id" => "200" }, root_value: root_object)
|
246
|
+
|
247
|
+
# Initial response is nil, no broadcasts yet
|
248
|
+
assert_equal(nil, res_1["data"])
|
249
|
+
assert_equal(nil, res_2["data"])
|
250
|
+
assert_equal [], deliveries["1"]
|
251
|
+
assert_equal [], deliveries["2"]
|
252
|
+
|
253
|
+
# Application stuff happens.
|
254
|
+
# The application signals graphql via `subscriptions.trigger`:
|
255
|
+
schema.subscriptions.trigger(:payload, {"id" => "100"}, root_object.payload)
|
256
|
+
schema.subscriptions.trigger("payload", {"id" => "200"}, root_object.payload)
|
257
|
+
# Symobls are OK too
|
258
|
+
schema.subscriptions.trigger(:payload, {:id => "100"}, root_object.payload)
|
259
|
+
schema.subscriptions.trigger("payload", {"id" => "300"}, nil)
|
260
|
+
|
261
|
+
# Let's see what GraphQL sent over the wire:
|
262
|
+
assert_equal({"str" => "Update", "int" => 1}, deliveries["1"][0]["data"]["firstPayload"])
|
263
|
+
assert_equal({"str" => "Update", "int" => 2}, deliveries["2"][0]["data"]["firstPayload"])
|
264
|
+
assert_equal({"str" => "Update", "int" => 3}, deliveries["1"][1]["data"]["firstPayload"])
|
265
|
+
end
|
266
|
+
end
|
207
267
|
|
208
|
-
|
209
|
-
|
210
|
-
|
268
|
+
describe "subscribing" do
|
269
|
+
it "doesn't call the subscriptions for invalid queries" do
|
270
|
+
query_str = <<-GRAPHQL
|
211
271
|
subscription ($id: ID){
|
212
272
|
payload(id: $id) { str, int }
|
213
273
|
}
|
214
|
-
|
274
|
+
GRAPHQL
|
215
275
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
276
|
+
res = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
|
277
|
+
assert_equal true, res.key?("errors")
|
278
|
+
assert_equal 0, implementation.size
|
279
|
+
end
|
280
|
+
end
|
221
281
|
|
222
|
-
|
223
|
-
|
224
|
-
|
282
|
+
describe "trigger" do
|
283
|
+
it "uses the provided queue" do
|
284
|
+
query_str = <<-GRAPHQL
|
225
285
|
subscription ($id: ID!){
|
226
286
|
payload(id: $id) { str, int }
|
227
287
|
}
|
228
|
-
|
288
|
+
GRAPHQL
|
229
289
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
290
|
+
schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
|
291
|
+
schema.subscriptions.trigger("payload", { "id" => "8"}, root_object.payload)
|
292
|
+
assert_equal ["1"], implementation.pushes
|
293
|
+
end
|
234
294
|
|
235
|
-
|
236
|
-
|
295
|
+
it "pushes errors" do
|
296
|
+
query_str = <<-GRAPHQL
|
237
297
|
subscription ($id: ID!){
|
238
298
|
payload(id: $id) { str, int }
|
239
299
|
}
|
240
|
-
|
300
|
+
GRAPHQL
|
241
301
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
302
|
+
schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
|
303
|
+
schema.subscriptions.trigger("payload", { "id" => "8"}, OpenStruct.new(str: nil, int: nil))
|
304
|
+
delivery = deliveries["1"].first
|
305
|
+
assert_nil delivery.fetch("data")
|
306
|
+
assert_equal 1, delivery["errors"].length
|
307
|
+
end
|
248
308
|
|
249
|
-
|
250
|
-
|
309
|
+
it "coerces args" do
|
310
|
+
query_str = <<-GRAPHQL
|
251
311
|
subscription($type: PayloadType) {
|
252
312
|
e1: event(stream: { userId: "3", type: $type }) { int }
|
253
313
|
}
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
314
|
+
GRAPHQL
|
315
|
+
|
316
|
+
# Subscribe with explicit `TYPE`
|
317
|
+
schema.execute(query_str, context: { socket: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
|
318
|
+
# Subscribe with default `TYPE`
|
319
|
+
schema.execute(query_str, context: { socket: "2" }, root_value: root_object)
|
320
|
+
# Subscribe with non-matching `TYPE`
|
321
|
+
schema.execute(query_str, context: { socket: "3" }, variables: { "type" => "TWO" }, root_value: root_object)
|
322
|
+
# Subscribe with explicit null
|
323
|
+
schema.execute(query_str, context: { socket: "4" }, variables: { "type" => nil }, root_value: root_object)
|
324
|
+
|
325
|
+
# Trigger the subscription with coerceable args, different orders:
|
326
|
+
schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => "ONE"} }, OpenStruct.new(str: "", int: 1))
|
327
|
+
schema.subscriptions.trigger("event", { "stream" => {"type" => "ONE", "userId" => "3"} }, OpenStruct.new(str: "", int: 2))
|
328
|
+
# This is a non-trigger
|
329
|
+
schema.subscriptions.trigger("event", { "stream" => {"userId" => "3", "type" => "TWO"} }, OpenStruct.new(str: "", int: 3))
|
330
|
+
# These get default value of ONE (underscored / symbols are ok)
|
331
|
+
schema.subscriptions.trigger("event", { stream: { user_id: "3"} }, OpenStruct.new(str: "", int: 4))
|
332
|
+
# Trigger with null updates subscriptionss to null
|
333
|
+
schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => nil} }, OpenStruct.new(str: "", int: 5))
|
334
|
+
|
335
|
+
assert_equal [1,2,4], deliveries["1"].map { |d| d["data"]["e1"]["int"] }
|
336
|
+
|
337
|
+
# Same as socket_1
|
338
|
+
assert_equal [1,2,4], deliveries["2"].map { |d| d["data"]["e1"]["int"] }
|
339
|
+
|
340
|
+
# Received the "non-trigger"
|
341
|
+
assert_equal [3], deliveries["3"].map { |d| d["data"]["e1"]["int"] }
|
342
|
+
|
343
|
+
# Received the trigger with null
|
344
|
+
assert_equal [5], deliveries["4"].map { |d| d["data"]["e1"]["int"] }
|
345
|
+
end
|
286
346
|
|
287
|
-
|
288
|
-
|
347
|
+
it "allows context-scoped subscriptions" do
|
348
|
+
query_str = <<-GRAPHQL
|
289
349
|
subscription($type: PayloadType) {
|
290
350
|
myEvent(type: $type) { int }
|
291
351
|
}
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
352
|
+
GRAPHQL
|
353
|
+
|
354
|
+
# Subscriptions for user 1
|
355
|
+
schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
|
356
|
+
schema.execute(query_str, context: { socket: "2", me: "1" }, variables: { "type" => "TWO" }, root_value: root_object)
|
357
|
+
# Subscription for user 2
|
358
|
+
schema.execute(query_str, context: { socket: "3", me: "2" }, variables: { "type" => "ONE" }, root_value: root_object)
|
359
|
+
|
360
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: "1")
|
361
|
+
schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: "1")
|
362
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: "2")
|
363
|
+
|
364
|
+
# Delivered to user 1
|
365
|
+
assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
|
366
|
+
assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
|
367
|
+
# Delivered to user 2
|
368
|
+
assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
|
369
|
+
end
|
310
370
|
|
311
|
-
|
312
|
-
|
313
|
-
|
371
|
+
if defined?(GlobalID)
|
372
|
+
it "allows complex object subscription scopes" do
|
373
|
+
query_str = <<-GRAPHQL
|
314
374
|
subscription($type: PayloadType) {
|
315
375
|
myEvent(type: $type) { int }
|
316
376
|
}
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
end
|
341
|
-
|
342
|
-
describe "errors" do
|
343
|
-
class ErrorPayload
|
344
|
-
def int
|
345
|
-
raise "Boom!"
|
377
|
+
GRAPHQL
|
378
|
+
|
379
|
+
# Global ID Backed User
|
380
|
+
schema.execute(query_str, context: { socket: "1", me: GlobalIDUser.new(1) }, variables: { "type" => "ONE" }, root_value: root_object)
|
381
|
+
schema.execute(query_str, context: { socket: "2", me: GlobalIDUser.new(1) }, variables: { "type" => "TWO" }, root_value: root_object)
|
382
|
+
# ToParam Backed User
|
383
|
+
schema.execute(query_str, context: { socket: "3", me: ToParamUser.new(2) }, variables: { "type" => "ONE" }, root_value: root_object)
|
384
|
+
# Array of Objects
|
385
|
+
schema.execute(query_str, context: { socket: "4", me: [GlobalIDUser.new(4), ToParamUser.new(5)] }, variables: { "type" => "ONE" }, root_value: root_object)
|
386
|
+
|
387
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: GlobalIDUser.new(1))
|
388
|
+
schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: GlobalIDUser.new(1))
|
389
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: ToParamUser.new(2))
|
390
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 4), scope: [GlobalIDUser.new(4), ToParamUser.new(5)])
|
391
|
+
|
392
|
+
# Delivered to GlobalIDUser
|
393
|
+
assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
|
394
|
+
assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
|
395
|
+
# Delivered to ToParamUser
|
396
|
+
assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
|
397
|
+
# Delivered to Array of GlobalIDUser and ToParamUser
|
398
|
+
assert_equal [4], deliveries["4"].map { |d| d["data"]["myEvent"]["int"] }
|
399
|
+
end
|
346
400
|
end
|
347
401
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
402
|
+
describe "errors" do
|
403
|
+
class ErrorPayload
|
404
|
+
def int
|
405
|
+
raise "Boom!"
|
406
|
+
end
|
352
407
|
|
353
|
-
|
354
|
-
|
408
|
+
def str
|
409
|
+
raise GraphQL::ExecutionError.new("This is handled")
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
it "lets unhandled errors crash "do
|
414
|
+
query_str = <<-GRAPHQL
|
355
415
|
subscription($type: PayloadType) {
|
356
416
|
myEvent(type: $type) { int }
|
357
417
|
}
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
418
|
+
GRAPHQL
|
419
|
+
|
420
|
+
schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
|
421
|
+
err = assert_raises(RuntimeError) {
|
422
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
|
423
|
+
}
|
424
|
+
assert_equal "Boom!", err.message
|
425
|
+
end
|
426
|
+
end
|
367
427
|
|
368
|
-
|
369
|
-
|
428
|
+
it "sends query errors to the subscriptions" do
|
429
|
+
query_str = <<-GRAPHQL
|
370
430
|
subscription($type: PayloadType) {
|
371
431
|
myEvent(type: $type) { str }
|
372
432
|
}
|
373
|
-
|
433
|
+
GRAPHQL
|
374
434
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
435
|
+
schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
|
436
|
+
schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
|
437
|
+
res = deliveries["1"].first
|
438
|
+
assert_equal "This is handled", res["errors"][0]["message"]
|
439
|
+
end
|
440
|
+
end
|
381
441
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
442
|
+
describe "implementation" do
|
443
|
+
it "is initialized with keywords" do
|
444
|
+
assert_equal 123, schema.subscriptions.extra
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
describe "#build_id" do
|
449
|
+
it "returns a unique ID string" do
|
450
|
+
assert_instance_of String, schema.subscriptions.build_id
|
451
|
+
refute_equal schema.subscriptions.build_id, schema.subscriptions.build_id
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
describe ".trigger" do
|
456
|
+
it "raises when event name is not found" do
|
457
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
458
|
+
schema.subscriptions.trigger(:nonsense_field, {}, nil)
|
459
|
+
end
|
460
|
+
|
461
|
+
assert_includes err.message, "trigger: nonsense_field"
|
462
|
+
assert_includes err.message, "Subscription.nonsenseField"
|
463
|
+
end
|
464
|
+
|
465
|
+
it "raises when argument is not found" do
|
466
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
467
|
+
schema.subscriptions.trigger(:event, { scream: {"userId" => "😱"} }, nil)
|
468
|
+
end
|
387
469
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
470
|
+
assert_includes err.message, "arguments: scream"
|
471
|
+
assert_includes err.message, "arguments of Subscription.event"
|
472
|
+
|
473
|
+
err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
|
474
|
+
schema.subscriptions.trigger(:event, { stream: { user_id_number: "😱"} }, nil)
|
475
|
+
end
|
476
|
+
|
477
|
+
assert_includes err.message, "arguments: user_id_number"
|
478
|
+
assert_includes err.message, "arguments of StreamInput"
|
479
|
+
end
|
480
|
+
end
|
392
481
|
end
|
393
482
|
end
|
394
483
|
end
|
@@ -41,10 +41,10 @@ describe GraphQL::Tracing::ActiveSupportNotificationsTracing do
|
|
41
41
|
"graphql.execute_field",
|
42
42
|
"graphql.execute_query",
|
43
43
|
"graphql.lazy_loader",
|
44
|
-
"graphql.execute_field",
|
45
44
|
"graphql.execute_field_lazy",
|
46
45
|
"graphql.execute_field",
|
47
46
|
"graphql.execute_field_lazy",
|
47
|
+
"graphql.execute_field",
|
48
48
|
"graphql.execute_field_lazy",
|
49
49
|
"graphql.execute_field_lazy",
|
50
50
|
"graphql.execute_query_lazy",
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe GraphQL::Tracing::NewRelicTracing do
|
5
|
+
module NewRelicTest
|
6
|
+
class Query < GraphQL::Schema::Object
|
7
|
+
field :int, Integer, null: false
|
8
|
+
|
9
|
+
def int
|
10
|
+
1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class SchemaWithoutTransactionName < GraphQL::Schema
|
15
|
+
query(Query)
|
16
|
+
use(GraphQL::Tracing::NewRelicTracing)
|
17
|
+
end
|
18
|
+
|
19
|
+
class SchemaWithTransactionName < GraphQL::Schema
|
20
|
+
query(Query)
|
21
|
+
use(GraphQL::Tracing::NewRelicTracing, set_transaction_name: true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
NewRelic.clear_all
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can leave the transaction name in place" do
|
30
|
+
NewRelicTest::SchemaWithoutTransactionName.execute "query X { int }"
|
31
|
+
assert_equal [], NewRelic::TRANSACTION_NAMES
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can override the transaction name" do
|
35
|
+
NewRelicTest::SchemaWithTransactionName.execute "query X { int }"
|
36
|
+
assert_equal ["GraphQL/query.X"], NewRelic::TRANSACTION_NAMES
|
37
|
+
end
|
38
|
+
|
39
|
+
it "can override the transaction name per query" do
|
40
|
+
# Override with `false`
|
41
|
+
NewRelicTest::SchemaWithTransactionName.execute "{ int }", context: { set_new_relic_transaction_name: false }
|
42
|
+
assert_equal [], NewRelic::TRANSACTION_NAMES
|
43
|
+
# Override with `true`
|
44
|
+
NewRelicTest::SchemaWithoutTransactionName.execute "{ int }", context: { set_new_relic_transaction_name: true }
|
45
|
+
assert_equal ["GraphQL/query.anonymous"], NewRelic::TRANSACTION_NAMES
|
46
|
+
end
|
47
|
+
end
|