graphql 1.8.7 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
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