graphql 1.8.7 → 1.8.8

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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/enum_type.rb +4 -0
  3. data/lib/graphql/execution/multiplex.rb +1 -1
  4. data/lib/graphql/schema/argument.rb +1 -0
  5. data/lib/graphql/schema/enum_value.rb +1 -0
  6. data/lib/graphql/schema/field.rb +1 -0
  7. data/lib/graphql/schema/interface.rb +1 -0
  8. data/lib/graphql/schema/member.rb +2 -0
  9. data/lib/graphql/schema/member/has_path.rb +25 -0
  10. data/lib/graphql/schema/relay_classic_mutation.rb +3 -9
  11. data/lib/graphql/schema/resolver.rb +25 -5
  12. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
  13. data/lib/graphql/upgrader/member.rb +5 -0
  14. data/lib/graphql/version.rb +1 -1
  15. data/spec/dummy/Gemfile +1 -1
  16. data/spec/graphql/enum_type_spec.rb +5 -0
  17. data/spec/graphql/execution/execute_spec.rb +1 -1
  18. data/spec/graphql/execution/multiplex_spec.rb +28 -1
  19. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
  20. data/spec/graphql/schema/argument_spec.rb +5 -1
  21. data/spec/graphql/schema/enum_spec.rb +7 -0
  22. data/spec/graphql/schema/enum_value_spec.rb +11 -0
  23. data/spec/graphql/schema/field_spec.rb +7 -0
  24. data/spec/graphql/schema/input_object_spec.rb +11 -0
  25. data/spec/graphql/schema/interface_spec.rb +6 -0
  26. data/spec/graphql/schema/object_spec.rb +6 -0
  27. data/spec/graphql/schema/relay_classic_mutation_spec.rb +71 -0
  28. data/spec/graphql/schema/resolver_spec.rb +72 -8
  29. data/spec/graphql/schema/scalar_spec.rb +6 -0
  30. data/spec/graphql/schema/union_spec.rb +7 -0
  31. data/spec/graphql/upgrader/member_spec.rb +67 -0
  32. data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +0 -11
  33. data/spec/integration/mongoid/spec_helper.rb +2 -0
  34. data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
  35. data/spec/{support → integration/mongoid}/star_trek/schema.rb +0 -0
  36. data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
  37. data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
  38. data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
  39. data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +0 -0
  40. data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
  41. data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
  42. data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
  43. data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
  44. data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
  45. data/spec/{graphql → integration/rails/graphql}/input_object_type_spec.rb +0 -0
  46. data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +0 -0
  47. data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +0 -0
  48. data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +0 -0
  49. data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +0 -0
  50. data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +0 -0
  51. data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
  52. data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
  53. data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +0 -0
  54. data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
  55. data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +0 -0
  56. data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +0 -0
  57. data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +0 -0
  58. data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +0 -0
  59. data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +0 -0
  60. data/spec/integration/rails/spec_helper.rb +15 -0
  61. data/spec/spec_helper.rb +16 -39
  62. data/spec/support/jazz.rb +48 -0
  63. metadata +260 -243
  64. data/spec/rails_dependency_sanity_spec.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2aa5dc86bfb37cc0c46b7974618bddc91b203b0
4
- data.tar.gz: 92979d239d0fbd9a010261dec5d0b1285c617c3f
3
+ metadata.gz: c8642c253947a56246003a995f373e3088b70848
4
+ data.tar.gz: 0e027e906d12ff726e144220849ac216b66dc56d
5
5
  SHA512:
6
- metadata.gz: 26ccb7f54465c14158a933a4bbc52eaba9576725ea06ce1a5425128fd39ad133013383ffa650bc6bbbdf16030bf232ab021da6a1c39ee20933d294b49d5d8d57
7
- data.tar.gz: 7ec6717d6a3cf091189269e92d991cd49fdec20802d68cb7c83d60b9ab615535ad626c8163a5022e713f4c9f875bfaec1430b51098ec3e55eca5e91ff6e1a622
6
+ metadata.gz: cfabff78ee8e8bb710ee73bfcb191d7b040a55eb042a2b94cf8d8d3169671b954aa13901c095124a516d593f49d21f1c9f2f63ed2731308e77e74fbffad9d726
7
+ data.tar.gz: d924393eea98ab77207c0fa35abc579373f650000e66b82cd181f1e5286b58d8794e29fcc4f3796f3b8db6f0dec0c7293e8244275cdceb0f45f39bde556f8f89
@@ -147,6 +147,10 @@ module GraphQL
147
147
  GraphQL::NameValidator.validate!(new_name)
148
148
  @name = new_name
149
149
  end
150
+
151
+ def graphql_name
152
+ name
153
+ end
150
154
  end
151
155
 
152
156
  class UnresolvedValueError < GraphQL::Error
@@ -91,7 +91,7 @@ module GraphQL
91
91
  # Get the Query::Result, not the Hash
92
92
  query.result
93
93
  end
94
- rescue StandardError
94
+ rescue Exception
95
95
  # Assign values here so that the query's `@executed` becomes true
96
96
  queries.map { |q| q.result_values ||= {} }
97
97
  raise
@@ -4,6 +4,7 @@ module GraphQL
4
4
  class Argument
5
5
  include GraphQL::Schema::Member::CachedGraphQLDefinition
6
6
  include GraphQL::Schema::Member::AcceptsDefinition
7
+ include GraphQL::Schema::Member::HasPath
7
8
 
8
9
  NO_DEFAULT = :__no_default__
9
10
 
@@ -27,6 +27,7 @@ module GraphQL
27
27
  # end
28
28
  class EnumValue < GraphQL::Schema::Member
29
29
  include GraphQL::Schema::Member::AcceptsDefinition
30
+ include GraphQL::Schema::Member::HasPath
30
31
 
31
32
  attr_reader :graphql_name
32
33
 
@@ -6,6 +6,7 @@ module GraphQL
6
6
  include GraphQL::Schema::Member::CachedGraphQLDefinition
7
7
  include GraphQL::Schema::Member::AcceptsDefinition
8
8
  include GraphQL::Schema::Member::HasArguments
9
+ include GraphQL::Schema::Member::HasPath
9
10
 
10
11
  # @return [String] the GraphQL name for this field, camelized unless `camelize: false` is provided
11
12
  attr_reader :name
@@ -9,6 +9,7 @@ module GraphQL
9
9
  include GraphQL::Schema::Member::BaseDSLMethods
10
10
  include GraphQL::Schema::Member::TypeSystemHelpers
11
11
  include GraphQL::Schema::Member::HasFields
12
+ include GraphQL::Schema::Member::HasPath
12
13
  include GraphQL::Schema::Member::RelayShortcuts
13
14
  include GraphQL::Schema::Member::Scoped
14
15
 
@@ -3,6 +3,7 @@ require 'graphql/schema/member/accepts_definition'
3
3
  require 'graphql/schema/member/base_dsl_methods'
4
4
  require 'graphql/schema/member/cached_graphql_definition'
5
5
  require 'graphql/schema/member/graphql_type_names'
6
+ require 'graphql/schema/member/has_path'
6
7
  require 'graphql/schema/member/relay_shortcuts'
7
8
  require 'graphql/schema/member/scoped'
8
9
  require 'graphql/schema/member/type_system_helpers'
@@ -22,6 +23,7 @@ module GraphQL
22
23
  extend TypeSystemHelpers
23
24
  extend Scoped
24
25
  extend RelayShortcuts
26
+ extend HasPath
25
27
  end
26
28
  end
27
29
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Member
6
+ module HasPath
7
+ # @return [String] A description of this member's place in the GraphQL schema
8
+ def path
9
+ path_str = if self.respond_to?(:graphql_name)
10
+ self.graphql_name
11
+ elsif self.class.respond_to?(:graphql_name)
12
+ # Instances of resolvers
13
+ self.class.graphql_name
14
+ end
15
+
16
+ if self.respond_to?(:owner) && owner.respond_to?(:path)
17
+ path_str = "#{owner.path}.#{path_str}"
18
+ end
19
+
20
+ path_str
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -25,20 +25,14 @@ module GraphQL
25
25
  # Relay classic default:
26
26
  null(true)
27
27
 
28
- # Override {GraphQL::Schema::Mutation#resolve_mutation} to
28
+ # Override {GraphQL::Schema::Resolver#resolve_with_support} to
29
29
  # delete `client_mutation_id` from the kwargs.
30
- def resolve_mutation(**kwargs)
30
+ def resolve_with_support(**kwargs)
31
31
  # This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
32
32
  kwargs.delete(:client_mutation_id)
33
- if kwargs.any?
34
- resolve(**kwargs)
35
- else
36
- resolve
37
- end
33
+ super
38
34
  end
39
35
 
40
- resolve_method(:resolve_mutation)
41
-
42
36
  class << self
43
37
  # The base class for generated input object types
44
38
  # @param new_class [Class] The base class to use for generating input object definitions
@@ -23,6 +23,8 @@ module GraphQL
23
23
  # Really we only need description from here, but:
24
24
  extend Schema::Member::BaseDSLMethods
25
25
  extend GraphQL::Schema::Member::HasArguments
26
+ include Schema::Member::HasPath
27
+ extend Schema::Member::HasPath
26
28
 
27
29
  # @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
28
30
  # @param context [GraphQL::Query::Context]
@@ -72,7 +74,6 @@ module GraphQL
72
74
  else
73
75
  authorized?
74
76
  end
75
- authorized?(loaded_args)
76
77
  context.schema.after_lazy(authorized_val) do |(authorized_result, early_return)|
77
78
  # If the `authorized?` returned two values, `false, early_return`,
78
79
  # then use the early return value instead of continuing
@@ -323,13 +324,32 @@ module GraphQL
323
324
  # @see {GraphQL::Schema::Argument#initialize} for the signature
324
325
  def argument(name, type, *rest, loads: nil, **kwargs, &block)
325
326
  if loads
326
- arg_keyword = name.to_s.sub(/_id$/, "").to_sym
327
- kwargs[:as] = arg_keyword
328
- own_arguments_loads_as_type[arg_keyword] = loads
327
+ name_as_string = name.to_s
328
+
329
+ inferred_arg_name = case name_as_string
330
+ when /_id$/
331
+ name_as_string.sub(/_id$/, "").to_sym
332
+ when /_ids$/
333
+ name_as_string.sub(/_ids$/, "")
334
+ .sub(/([^s])$/, "\\1s")
335
+ .to_sym
336
+ else
337
+ name
338
+ end
339
+
340
+ kwargs[:as] ||= inferred_arg_name
341
+ own_arguments_loads_as_type[kwargs[:as]] = loads
329
342
  end
343
+
330
344
  arg_defn = super(name, type, *rest, **kwargs, &block)
331
345
 
332
- if loads
346
+ if loads && arg_defn.type.list?
347
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
348
+ def load_#{arg_defn.keyword}(values)
349
+ GraphQL::Execution::Lazy.all(values.map { |value| load_application_object(:#{arg_defn.keyword}, value) })
350
+ end
351
+ RUBY
352
+ elsif loads
333
353
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
334
354
  def load_#{arg_defn.keyword}(value)
335
355
  load_application_object(:#{arg_defn.keyword}, value)
@@ -39,7 +39,7 @@ module GraphQL
39
39
  # })
40
40
  #
41
41
  # payload = {
42
- # result: result.subscription? ? nil : result.to_h,
42
+ # result: result.subscription? ? { data: nil } : result.to_h,
43
43
  # more: result.subscription?,
44
44
  # }
45
45
  #
@@ -54,9 +54,28 @@ module GraphQL
54
54
  #
55
55
  # def unsubscribed
56
56
  # @subscription_ids.each { |sid|
57
- # CardsSchema.subscriptions.delete_subscription(sid)
57
+ # MySchema.subscriptions.delete_subscription(sid)
58
58
  # }
59
59
  # end
60
+ #
61
+ # private
62
+ #
63
+ # def ensure_hash(ambiguous_param)
64
+ # case ambiguous_param
65
+ # when String
66
+ # if ambiguous_param.present?
67
+ # ensure_hash(JSON.parse(ambiguous_param))
68
+ # else
69
+ # {}
70
+ # end
71
+ # when Hash, ActionController::Parameters
72
+ # ambiguous_param
73
+ # when nil
74
+ # {}
75
+ # else
76
+ # raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
77
+ # end
78
+ # end
60
79
  # end
61
80
  #
62
81
  class ActionCableSubscriptions < GraphQL::Subscriptions
@@ -19,6 +19,7 @@ module GraphQL
19
19
  # Recursively transform a `.define`-DSL-based type expression into a class-ready expression, for example:
20
20
  #
21
21
  # - `types[X]` -> `[X, null: true]`
22
+ # - `types[X.to_non_null_type]` -> `[X]`
22
23
  # - `Int` -> `Integer`
23
24
  # - `X!` -> `X`
24
25
  #
@@ -37,6 +38,9 @@ module GraphQL
37
38
  if inner_type.start_with?("!")
38
39
  nullable = false
39
40
  inner_type = inner_type[1..-1]
41
+ elsif inner_type.end_with?(".to_non_null_type")
42
+ nullable = false
43
+ inner_type = inner_type[0...-17]
40
44
  else
41
45
  nullable = true
42
46
  end
@@ -647,6 +651,7 @@ module GraphQL
647
651
 
648
652
  if return_type
649
653
  non_nullable = return_type.sub! /(^|[^\[])!/, '\1'
654
+ non_nullable ||= return_type.sub! /([^\[])\.to_non_null_type([^\]]|$)/, '\1'
650
655
  nullable = !non_nullable
651
656
  return_type = normalize_type_expression(return_type)
652
657
  else
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.8.7"
3
+ VERSION = "1.8.8"
4
4
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  source 'https://rubygems.org'
3
3
 
4
- gem 'rails'
4
+ gem 'rails', '~> 5.2.1'
5
5
  gem 'puma'
6
6
  gem 'capybara'
7
7
  gem 'selenium-webdriver'
@@ -130,6 +130,11 @@ describe GraphQL::EnumType do
130
130
  assert_equal({ "COW" => cow, "GOAT" => goat }, enum.values)
131
131
  end
132
132
 
133
+ it "values respond to graphql_name" do
134
+ cow = GraphQL::EnumType::EnumValue.define(name: "COW")
135
+ assert_equal("COW", cow.graphql_name)
136
+ end
137
+
133
138
  describe "#dup" do
134
139
  it "copies the values map without altering the original" do
135
140
  enum_2 = enum.dup
@@ -236,7 +236,7 @@ describe GraphQL::Execution::Execute do
236
236
  end
237
237
 
238
238
  describe "tracing" do
239
- if rails_should_be_installed?
239
+ if defined?(Rails)
240
240
  it "emits traces" do
241
241
  query_string = <<-GRAPHQL
242
242
  query Bases($id1: ID!, $id2: ID!){
@@ -160,6 +160,19 @@ describe GraphQL::Execution::Multiplex do
160
160
  raise GraphQL::Error, "Crash"
161
161
  }
162
162
  end
163
+
164
+ field :raiseSyntaxError, types.String do
165
+ resolve ->(object, args, ctx) {
166
+ raise SyntaxError
167
+ }
168
+ end
169
+
170
+ field :raiseException, types.String do
171
+ resolve ->(object, args, ctx) {
172
+ raise Exception
173
+ }
174
+ end
175
+
163
176
  end
164
177
 
165
178
  InspectSchema = GraphQL::Schema.define do
@@ -167,6 +180,8 @@ describe GraphQL::Execution::Multiplex do
167
180
  instrument(:query, InspectQueryInstrumentation)
168
181
  end
169
182
 
183
+ unhandled_err_json = '{}'
184
+
170
185
  it "can access the query results" do
171
186
  InspectSchema.execute("{ raiseExecutionError }")
172
187
  handled_err_json = '{"data":{"raiseExecutionError":null},"errors":[{"message":"Whoops","locations":[{"line":1,"column":3}],"path":["raiseExecutionError"]}]}'
@@ -176,7 +191,19 @@ describe GraphQL::Execution::Multiplex do
176
191
  assert_raises(GraphQL::Error) do
177
192
  InspectSchema.execute("{ raiseError }")
178
193
  end
179
- unhandled_err_json = '{}'
194
+
195
+ assert_equal unhandled_err_json, InspectQueryInstrumentation.last_json
196
+ end
197
+
198
+ it "can access the query results when the error is not a StandardError" do
199
+ assert_raises(SyntaxError) do
200
+ InspectSchema.execute("{ raiseSyntaxError }")
201
+ end
202
+ assert_equal unhandled_err_json, InspectQueryInstrumentation.last_json
203
+
204
+ assert_raises(Exception) do
205
+ InspectSchema.execute("{ raiseException }")
206
+ end
180
207
  assert_equal unhandled_err_json, InspectQueryInstrumentation.last_json
181
208
  end
182
209
  end
@@ -124,7 +124,9 @@ describe GraphQL::InternalRepresentation::Rewrite do
124
124
 
125
125
  nut_selections = plant_selection.typed_children[schema.types["Nut"]]
126
126
  # `... on Tree`, `... on Nut`, and `NutFields`, but not `... on Fruit { ... on Tree }`
127
+
127
128
  assert_equal 3, nut_selections["leafType"].ast_nodes.size
129
+
128
130
  # Multi-level merging when including fragments:
129
131
  habitats_selections = nut_selections["habitats"].typed_children[schema.types["Habitat"]]
130
132
  assert_equal ["averageWeight", "seasons"], habitats_selections.keys
@@ -29,7 +29,11 @@ describe GraphQL::Schema::Argument do
29
29
  end
30
30
  end
31
31
 
32
-
32
+ describe "#path" do
33
+ it "includes type, field and argument names" do
34
+ assert_equal "Query.field.argWithBlock", SchemaArgumentTest::Query.fields["field"].arguments["argWithBlock"].path
35
+ end
36
+ end
33
37
 
34
38
  describe "#name" do
35
39
  it "reflects camelization" do
@@ -3,6 +3,13 @@ require "spec_helper"
3
3
 
4
4
  describe GraphQL::Schema::Enum do
5
5
  let(:enum) { Jazz::Family }
6
+
7
+ describe ".path" do
8
+ it "is the name" do
9
+ assert_equal "Family", enum.path
10
+ end
11
+ end
12
+
6
13
  describe "type info" do
7
14
  it "tells about the definition" do
8
15
  assert_equal "Family", enum.graphql_name
@@ -2,6 +2,17 @@
2
2
  require "spec_helper"
3
3
 
4
4
  describe GraphQL::Schema::EnumValue do
5
+ describe "#path" do
6
+ it "Has the owner name too" do
7
+ enum = Class.new(GraphQL::Schema::Enum) do
8
+ graphql_name "Abc"
9
+ value(:XYZ)
10
+ end
11
+
12
+ assert_equal "Abc.XYZ", enum.values["XYZ"].path
13
+ end
14
+ end
15
+
5
16
  describe "#deprecation_reason" do
6
17
  it "can be written and read" do
7
18
  enum_value = GraphQL::Schema::EnumValue.new(:x, owner: nil)
@@ -6,6 +6,13 @@ describe GraphQL::Schema::Field do
6
6
  let(:object_class) { Jazz::Query }
7
7
  let(:field) { object_class.fields["inspectInput"] }
8
8
 
9
+ describe "path" do
10
+ it "is the object/interface and field name" do
11
+ assert_equal "Query.inspectInput", field.path
12
+ assert_equal "GloballyIdentifiable.id", Jazz::GloballyIdentifiableType.fields["id"].path
13
+ end
14
+ end
15
+
9
16
  it "uses the argument class" do
10
17
  arg_defn = field.graphql_definition.arguments.values.first
11
18
  assert_equal :ok, arg_defn.metadata[:custom]
@@ -3,6 +3,17 @@ require "spec_helper"
3
3
 
4
4
  describe GraphQL::Schema::InputObject do
5
5
  let(:input_object) { Jazz::EnsembleInput }
6
+
7
+ describe ".path" do
8
+ it "is the name" do
9
+ assert_equal "EnsembleInput", input_object.path
10
+ end
11
+
12
+ it "is used in argument paths" do
13
+ assert_equal "EnsembleInput.name", input_object.arguments["name"].path
14
+ end
15
+ end
16
+
6
17
  describe "type info" do
7
18
  it "has it" do
8
19
  assert_equal "EnsembleInput", input_object.graphql_name
@@ -4,6 +4,12 @@ require "spec_helper"
4
4
  describe GraphQL::Schema::Interface do
5
5
  let(:interface) { Jazz::GloballyIdentifiableType }
6
6
 
7
+ describe ".path" do
8
+ it "is the name" do
9
+ assert_equal "GloballyIdentifiable", interface.path
10
+ end
11
+ end
12
+
7
13
  describe "type info" do
8
14
  it "tells its type info" do
9
15
  assert_equal "GloballyIdentifiable", interface.graphql_name