graphql 1.9.7 → 1.9.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +2 -1
  3. data/lib/generators/graphql/templates/base_argument.erb +4 -0
  4. data/lib/generators/graphql/templates/base_field.erb +2 -0
  5. data/lib/generators/graphql/templates/base_input_object.erb +1 -0
  6. data/lib/graphql/analysis/ast/query_complexity.rb +34 -18
  7. data/lib/graphql/argument.rb +8 -2
  8. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
  9. data/lib/graphql/language/lexer.rb +24 -13
  10. data/lib/graphql/language/lexer.rl +23 -13
  11. data/lib/graphql/query/arguments.rb +16 -15
  12. data/lib/graphql/schema.rb +105 -48
  13. data/lib/graphql/schema/argument.rb +12 -1
  14. data/lib/graphql/schema/build_from_definition.rb +3 -0
  15. data/lib/graphql/schema/field.rb +3 -8
  16. data/lib/graphql/schema/find_inherited_value.rb +20 -0
  17. data/lib/graphql/schema/input_object.rb +1 -3
  18. data/lib/graphql/schema/loader.rb +1 -0
  19. data/lib/graphql/schema/member/base_dsl_methods.rb +7 -18
  20. data/lib/graphql/schema/member/has_arguments.rb +4 -9
  21. data/lib/graphql/schema/member/has_fields.rb +14 -0
  22. data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
  23. data/lib/graphql/schema/resolver.rb +31 -8
  24. data/lib/graphql/schema/resolver/has_payload_type.rb +3 -2
  25. data/lib/graphql/schema/subscription.rb +1 -1
  26. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
  27. data/lib/graphql/version.rb +1 -1
  28. data/spec/graphql/analysis/analyze_query_spec.rb +14 -25
  29. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +7 -19
  30. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +5 -12
  31. data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -20
  32. data/spec/graphql/analysis/max_query_depth_spec.rb +6 -13
  33. data/spec/graphql/language/lexer_spec.rb +19 -1
  34. data/spec/graphql/schema/argument_spec.rb +1 -1
  35. data/spec/graphql/schema/build_from_definition_spec.rb +10 -0
  36. data/spec/graphql/schema/catchall_middleware_spec.rb +6 -9
  37. data/spec/graphql/schema/input_object_spec.rb +25 -0
  38. data/spec/graphql/schema/loader_spec.rb +65 -1
  39. data/spec/graphql/schema/object_spec.rb +21 -0
  40. data/spec/graphql/schema/resolver_spec.rb +30 -1
  41. data/spec/graphql/schema_spec.rb +135 -0
  42. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +25 -0
  43. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +20 -0
  44. data/spec/integration/tmp/app/graphql/types/page_type.rb +5 -0
  45. data/spec/support/dummy/schema.rb +1 -1
  46. data/spec/support/lazy_helpers.rb +1 -1
  47. data/spec/support/parser/filename_example_invalid_utf8.graphql +1 -0
  48. metadata +10 -132
  49. data/spec/integration/tmp/app/graphql/types/date_type.rb +0 -14
  50. data/spec/integration/tmp/dummy/Gemfile +0 -50
  51. data/spec/integration/tmp/dummy/README.md +0 -24
  52. data/spec/integration/tmp/dummy/Rakefile +0 -6
  53. data/spec/integration/tmp/dummy/app/assets/config/manifest.js +0 -3
  54. data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +0 -16
  55. data/spec/integration/tmp/dummy/app/assets/javascripts/cable.js +0 -13
  56. data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +0 -15
  57. data/spec/integration/tmp/dummy/app/channels/application_cable/channel.rb +0 -5
  58. data/spec/integration/tmp/dummy/app/channels/application_cable/connection.rb +0 -5
  59. data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +0 -4
  60. data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +0 -44
  61. data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +0 -3
  62. data/spec/integration/tmp/dummy/app/jobs/application_job.rb +0 -3
  63. data/spec/integration/tmp/dummy/app/mailers/application_mailer.rb +0 -5
  64. data/spec/integration/tmp/dummy/app/mydirectory/dummy_schema.rb +0 -5
  65. data/spec/integration/tmp/dummy/app/mydirectory/mutations/update_name.rb +0 -15
  66. data/spec/integration/tmp/dummy/app/mydirectory/types/base_enum.rb +0 -5
  67. data/spec/integration/tmp/dummy/app/mydirectory/types/base_input_object.rb +0 -5
  68. data/spec/integration/tmp/dummy/app/mydirectory/types/base_interface.rb +0 -6
  69. data/spec/integration/tmp/dummy/app/mydirectory/types/base_object.rb +0 -5
  70. data/spec/integration/tmp/dummy/app/mydirectory/types/base_scalar.rb +0 -5
  71. data/spec/integration/tmp/dummy/app/mydirectory/types/base_union.rb +0 -5
  72. data/spec/integration/tmp/dummy/app/mydirectory/types/mutation_type.rb +0 -12
  73. data/spec/integration/tmp/dummy/app/mydirectory/types/query_type.rb +0 -14
  74. data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +0 -14
  75. data/spec/integration/tmp/dummy/app/views/layouts/mailer.html.erb +0 -13
  76. data/spec/integration/tmp/dummy/app/views/layouts/mailer.text.erb +0 -1
  77. data/spec/integration/tmp/dummy/bin/bundle +0 -3
  78. data/spec/integration/tmp/dummy/bin/rails +0 -4
  79. data/spec/integration/tmp/dummy/bin/rake +0 -4
  80. data/spec/integration/tmp/dummy/bin/setup +0 -34
  81. data/spec/integration/tmp/dummy/bin/update +0 -29
  82. data/spec/integration/tmp/dummy/config.ru +0 -5
  83. data/spec/integration/tmp/dummy/config/application.rb +0 -26
  84. data/spec/integration/tmp/dummy/config/boot.rb +0 -4
  85. data/spec/integration/tmp/dummy/config/cable.yml +0 -9
  86. data/spec/integration/tmp/dummy/config/environment.rb +0 -6
  87. data/spec/integration/tmp/dummy/config/environments/development.rb +0 -52
  88. data/spec/integration/tmp/dummy/config/environments/production.rb +0 -84
  89. data/spec/integration/tmp/dummy/config/environments/test.rb +0 -43
  90. data/spec/integration/tmp/dummy/config/initializers/application_controller_renderer.rb +0 -9
  91. data/spec/integration/tmp/dummy/config/initializers/assets.rb +0 -12
  92. data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +0 -8
  93. data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +0 -6
  94. data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  95. data/spec/integration/tmp/dummy/config/initializers/inflections.rb +0 -17
  96. data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +0 -5
  97. data/spec/integration/tmp/dummy/config/initializers/new_framework_defaults.rb +0 -24
  98. data/spec/integration/tmp/dummy/config/initializers/session_store.rb +0 -4
  99. data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +0 -10
  100. data/spec/integration/tmp/dummy/config/locales/en.yml +0 -23
  101. data/spec/integration/tmp/dummy/config/puma.rb +0 -48
  102. data/spec/integration/tmp/dummy/config/routes.rb +0 -9
  103. data/spec/integration/tmp/dummy/config/secrets.yml +0 -22
  104. data/spec/integration/tmp/dummy/db/seeds.rb +0 -8
  105. data/spec/integration/tmp/dummy/log/test.log +0 -0
  106. data/spec/integration/tmp/dummy/public/404.html +0 -67
  107. data/spec/integration/tmp/dummy/public/422.html +0 -67
  108. data/spec/integration/tmp/dummy/public/500.html +0 -66
  109. data/spec/integration/tmp/dummy/public/apple-touch-icon-precomposed.png +0 -0
  110. data/spec/integration/tmp/dummy/public/apple-touch-icon.png +0 -0
  111. data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
  112. data/spec/integration/tmp/dummy/public/robots.txt +0 -5
  113. data/spec/integration/tmp/dummy/test/test_helper.rb +0 -8
@@ -24,6 +24,11 @@ module GraphQL
24
24
  # @return [Class, Module, nil] If this argument should load an application object, this is the type of object to load
25
25
  attr_reader :loads
26
26
 
27
+ # @return [Boolean] true if a resolver defined this argument
28
+ def from_resolver?
29
+ @from_resolver
30
+ end
31
+
27
32
  # @param arg_name [Symbol]
28
33
  # @param type_expr
29
34
  # @param desc [String]
@@ -33,7 +38,9 @@ module GraphQL
33
38
  # @param as [Symbol] Override the keyword name when passed to a method
34
39
  # @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
35
40
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
36
- def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
41
+ # @param from_resolver [Boolean] if true, a Resolver class defined this argument
42
+ # @param method_access [Boolean] If false, don't build method access on legacy {Query::Arguments} instances.
43
+ def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, &definition_block)
37
44
  arg_name ||= name
38
45
  name_str = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
39
46
  @name = name_str.freeze
@@ -46,6 +53,9 @@ module GraphQL
46
53
  @loads = loads
47
54
  @keyword = as || Schema::Member::BuildType.underscore(@name).to_sym
48
55
  @prepare = prepare
56
+ @ast_node = ast_node
57
+ @from_resolver = from_resolver
58
+ @method_access = method_access
49
59
 
50
60
  if definition_block
51
61
  if definition_block.arity == 1
@@ -94,6 +104,7 @@ module GraphQL
94
104
  argument.description = @description
95
105
  argument.metadata[:type_class] = self
96
106
  argument.as = @as
107
+ argument.method_access = @method_access
97
108
  if NO_DEFAULT != @default_value
98
109
  argument.default_value = @default_value
99
110
  end
@@ -232,6 +232,7 @@ module GraphQL
232
232
  name: input_argument.name,
233
233
  type: type_resolver.call(input_argument.type),
234
234
  description: input_argument.description,
235
+ method_access: false,
235
236
  **kwargs,
236
237
  )
237
238
 
@@ -269,6 +270,7 @@ module GraphQL
269
270
  name: directive_argument.name,
270
271
  type: type_resolver.call(directive_argument.type),
271
272
  description: directive_argument.description,
273
+ method_access: false,
272
274
  **kwargs,
273
275
  )
274
276
 
@@ -306,6 +308,7 @@ module GraphQL
306
308
  name: argument.name,
307
309
  description: argument.description,
308
310
  type: type_resolver.call(argument.type),
311
+ method_access: false,
309
312
  **kwargs,
310
313
  )
311
314
 
@@ -205,7 +205,7 @@ module GraphQL
205
205
 
206
206
  # TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
207
207
  method_name = method || hash_key || @underscored_name
208
- resolver_method ||= @underscored_name
208
+ resolver_method ||= @underscored_name.to_sym
209
209
 
210
210
  @method_str = method_name.to_s
211
211
  @method_sym = method_name.to_sym
@@ -418,13 +418,10 @@ module GraphQL
418
418
  end
419
419
 
420
420
  def authorized?(object, context)
421
- self_auth = if @resolver_class
421
+ if @resolver_class
422
+ # The resolver will check itself during `resolve()`
422
423
  @resolver_class.authorized?(object, context)
423
424
  else
424
- true
425
- end
426
-
427
- if self_auth
428
425
  # Faster than `.any?`
429
426
  arguments.each_value do |arg|
430
427
  if !arg.authorized?(object, context)
@@ -432,8 +429,6 @@ module GraphQL
432
429
  end
433
430
  end
434
431
  true
435
- else
436
- false
437
432
  end
438
433
  end
439
434
 
@@ -0,0 +1,20 @@
1
+ module GraphQL
2
+ class Schema
3
+ module FindInheritedValue
4
+ private
5
+
6
+ def find_inherited_value(method_name, default_value = nil)
7
+ if self.is_a?(Class)
8
+ superclass.respond_to?(method_name, true) ? superclass.send(method_name) : default_value
9
+ else
10
+ ancestors[1..-1].each do |ancestor|
11
+ if ancestor.respond_to?(method_name, true)
12
+ return ancestor.send(method_name)
13
+ end
14
+ end
15
+ default_value
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -23,7 +23,7 @@ module GraphQL
23
23
  ruby_kwargs_key = arg_defn.keyword
24
24
  loads = arg_defn.loads
25
25
 
26
- if @ruby_style_hash.key?(ruby_kwargs_key) && loads
26
+ if @ruby_style_hash.key?(ruby_kwargs_key) && loads && !arg_defn.from_resolver?
27
27
  value = @ruby_style_hash[ruby_kwargs_key]
28
28
  @ruby_style_hash[ruby_kwargs_key] = if arg_defn.type.list?
29
29
  GraphQL::Execution::Lazy.all(value.map { |val| load_application_object(arg_defn, loads, val) })
@@ -99,8 +99,6 @@ module GraphQL
99
99
  attr_accessor :arguments_class
100
100
 
101
101
  def argument(*args, **kwargs, &block)
102
- # Translate `loads:` to `as:` if needed`
103
- *args, kwargs = argument_with_loads(*args, **kwargs, &block)
104
102
  argument_defn = super(*args, **kwargs, &block)
105
103
  # Add a method access
106
104
  method_name = argument_defn.keyword
@@ -148,6 +148,7 @@ module GraphQL
148
148
  name: type["name"],
149
149
  type: type_resolver.call(type["type"]),
150
150
  description: type["description"],
151
+ method_access: false,
151
152
  **kwargs
152
153
  )
153
154
  when "SCALAR"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/schema/find_inherited_value"
4
+
3
5
  module GraphQL
4
6
  class Schema
5
7
  class Member
@@ -7,6 +9,8 @@ module GraphQL
7
9
  # @api private
8
10
  # @see Classes that extend this, eg {GraphQL::Schema::Object}
9
11
  module BaseDSLMethods
12
+ include GraphQL::Schema::FindInheritedValue
13
+
10
14
  # Call this with a new name to override the default name for this schema member; OR
11
15
  # call it without an argument to get the name of this schema member
12
16
  #
@@ -42,7 +46,7 @@ module GraphQL
42
46
  if new_description
43
47
  @description = new_description
44
48
  else
45
- @description || find_inherited_method(:description, nil)
49
+ @description || find_inherited_value(:description)
46
50
  end
47
51
  end
48
52
 
@@ -51,7 +55,7 @@ module GraphQL
51
55
  if !new_introspection.nil?
52
56
  @introspection = new_introspection
53
57
  else
54
- @introspection || find_inherited_method(:introspection, false)
58
+ @introspection || find_inherited_value(:introspection, false)
55
59
  end
56
60
  end
57
61
 
@@ -76,7 +80,7 @@ module GraphQL
76
80
  alias :unwrap :itself
77
81
 
78
82
  def overridden_graphql_name
79
- @graphql_name || find_inherited_method(:overridden_graphql_name, nil)
83
+ @graphql_name || find_inherited_value(:overridden_graphql_name)
80
84
  end
81
85
 
82
86
  # Creates the default name for a schema member.
@@ -113,21 +117,6 @@ module GraphQL
113
117
  true
114
118
  end
115
119
  end
116
-
117
- private
118
-
119
- def find_inherited_method(method_name, default_value)
120
- if self.is_a?(Class)
121
- superclass.respond_to?(method_name) ? superclass.public_send(method_name) : default_value
122
- else
123
- ancestors[1..-1].each do |ancestor|
124
- if ancestor.respond_to?(method_name)
125
- return ancestor.public_send(method_name)
126
- end
127
- end
128
- default_value
129
- end
130
- end
131
120
  end
132
121
  end
133
122
  end
@@ -13,7 +13,10 @@ module GraphQL
13
13
  cls.include(ArgumentObjectLoader)
14
14
  end
15
15
 
16
- def argument_with_loads(*args, **kwargs)
16
+ # @see {GraphQL::Schema::Argument#initialize} for parameters
17
+ # @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
18
+ def argument(*args, **kwargs, &block)
19
+ kwargs[:owner] = self
17
20
  loads = kwargs[:loads]
18
21
  if loads
19
22
  name = args[0]
@@ -32,14 +35,6 @@ module GraphQL
32
35
 
33
36
  kwargs[:as] ||= inferred_arg_name
34
37
  end
35
-
36
- return [*args, **kwargs]
37
- end
38
-
39
- # @see {GraphQL::Schema::Argument#initialize} for parameters
40
- # @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
41
- def argument(*args, **kwargs, &block)
42
- kwargs[:owner] = self
43
38
  arg_defn = self.argument_class.new(*args, **kwargs, &block)
44
39
  add_argument(arg_defn)
45
40
  end
@@ -38,10 +38,24 @@ module GraphQL
38
38
  end
39
39
  end
40
40
 
41
+ # A list of field names that we should advise users to pick a different
42
+ # resolve method name.
43
+ #
44
+ # @api private
45
+ CONFLICT_FIELD_NAMES = Set.new([
46
+ # GraphQL-Ruby conflicts
47
+ :context, :object,
48
+ # Ruby built-ins conflicts
49
+ :method, :class
50
+ ])
51
+
41
52
  # Register this field with the class, overriding a previous one if needed.
42
53
  # @param field_defn [GraphQL::Schema::Field]
43
54
  # @return [void]
44
55
  def add_field(field_defn)
56
+ if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method)
57
+ warn "#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`)"
58
+ end
45
59
  own_fields[field_defn.name] = field_defn
46
60
  nil
47
61
  end
@@ -8,7 +8,7 @@ module GraphQL
8
8
  if new_edge_type_class
9
9
  @edge_type_class = new_edge_type_class
10
10
  else
11
- @edge_type_class || find_inherited_method(:edge_type_class, Types::Relay::BaseEdge)
11
+ @edge_type_class || find_inherited_value(:edge_type_class, Types::Relay::BaseEdge)
12
12
  end
13
13
  end
14
14
 
@@ -16,7 +16,7 @@ module GraphQL
16
16
  if new_connection_type_class
17
17
  @connection_type_class = new_connection_type_class
18
18
  else
19
- @connection_type_class || find_inherited_method(:connection_type_class, Types::Relay::BaseConnection)
19
+ @connection_type_class || find_inherited_value(:connection_type_class, Types::Relay::BaseConnection)
20
20
  end
21
21
  end
22
22
 
@@ -123,12 +123,36 @@ module GraphQL
123
123
  # Called after arguments are loaded, but before resolving.
124
124
  #
125
125
  # Override it to check everything before calling the mutation.
126
- # @param args [Hash] The input arguments
126
+ # @param inputs [Hash] The input arguments
127
127
  # @raise [GraphQL::ExecutionError] To add an error to the response
128
128
  # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
129
129
  # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
130
- def authorized?(**args)
131
- true
130
+ def authorized?(**inputs)
131
+ self.class.arguments.each_value do |argument|
132
+ arg_keyword = argument.keyword
133
+ if inputs.key?(arg_keyword) && !(value = inputs[arg_keyword]).nil? && (value != argument.default_value)
134
+ loads_type = @arguments_loads_as_type[arg_keyword]
135
+ # If this argument resulted in an object being loaded,
136
+ # then authorize this loaded object with its own policy.
137
+ #
138
+ # But if this argument was "just" a plain argument, like
139
+ # a boolean, then authorize it based on the mutation.
140
+ authorization_value = if loads_type
141
+ value
142
+ else
143
+ self
144
+ end
145
+
146
+ arg_auth, err = argument.authorized?(authorization_value, context)
147
+ if !arg_auth
148
+ return arg_auth, err
149
+ else
150
+ true
151
+ end
152
+ else
153
+ true
154
+ end
155
+ end
132
156
  end
133
157
 
134
158
  private
@@ -254,12 +278,11 @@ module GraphQL
254
278
  # Add an argument to this field's signature, but
255
279
  # also add some preparation hook methods which will be used for this argument
256
280
  # @see {GraphQL::Schema::Argument#initialize} for the signature
257
- def argument(name, type, *rest, loads: nil, **kwargs, &block)
258
- *args, kwargs = argument_with_loads(name, type, *rest, loads: loads, **kwargs, &block)
259
- # Short-circuit the InputObject's own `loads:` implementation
281
+ def argument(*args, **kwargs, &block)
282
+ loads = kwargs[:loads]
283
+ # Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
260
284
  # so that we can support `#load_{x}` methods below.
261
- kwargs.delete(:loads)
262
- arg_defn = super(*args, **kwargs)
285
+ arg_defn = super(*args, from_resolver: true, **kwargs)
263
286
  own_arguments_loads_as_type[arg_defn.keyword] = loads if loads
264
287
 
265
288
  if loads && arg_defn.type.list?
@@ -27,7 +27,7 @@ module GraphQL
27
27
  if new_class
28
28
  @field_class = new_class
29
29
  else
30
- @field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
30
+ @field_class || find_inherited_value(:field_class, GraphQL::Schema::Field)
31
31
  end
32
32
  end
33
33
 
@@ -37,8 +37,9 @@ module GraphQL
37
37
  def object_class(new_class = nil)
38
38
  if new_class
39
39
  @object_class = new_class
40
+ else
41
+ @object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
40
42
  end
41
- @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
42
43
  end
43
44
 
44
45
  private
@@ -104,7 +104,7 @@ module GraphQL
104
104
  elsif defined?(@subscription_scope)
105
105
  @subscription_scope
106
106
  else
107
- find_inherited_method(:subscription_scope, nil)
107
+ find_inherited_value(:subscription_scope)
108
108
  end
109
109
  end
110
110
 
@@ -17,7 +17,7 @@ module GraphQL
17
17
 
18
18
  def assert_required_args(ast_node, defn)
19
19
  present_argument_names = ast_node.arguments.map(&:name)
20
- required_argument_names = defn.arguments.values
20
+ required_argument_names = context.warden.arguments(defn)
21
21
  .select { |a| a.type.kind.non_null? }
22
22
  .map(&:name)
23
23
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.9.7"
3
+ VERSION = "1.9.8"
4
4
  end
@@ -31,6 +31,8 @@ describe GraphQL::Analysis do
31
31
  end
32
32
  end
33
33
 
34
+ let(:schema) { Class.new(Dummy::Schema) }
35
+
34
36
  describe ".analyze_query" do
35
37
  let(:node_counter) {
36
38
  ->(memo, visit_type, irep_node) {
@@ -43,7 +45,7 @@ describe GraphQL::Analysis do
43
45
  let(:analyzers) { [type_collector, node_counter] }
44
46
  let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
45
47
  let(:variables) { {} }
46
- let(:query) { GraphQL::Query.new(Dummy::Schema, query_string, variables: variables) }
48
+ let(:query) { GraphQL::Query.new(schema, query_string, variables: variables) }
47
49
  let(:query_string) {%|
48
50
  {
49
51
  cheese(id: 1) {
@@ -58,7 +60,7 @@ describe GraphQL::Analysis do
58
60
  let(:analyzers) { [type_collector, conditional_analyzer] }
59
61
 
60
62
  describe "when analyze? returns false" do
61
- let(:query) { GraphQL::Query.new(Dummy::Schema, query_string, variables: variables, context: { analyze: false }) }
63
+ let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: false }) }
62
64
 
63
65
  it "does not run the analyzer" do
64
66
  # Only type_collector ran
@@ -67,7 +69,7 @@ describe GraphQL::Analysis do
67
69
  end
68
70
 
69
71
  describe "when analyze? returns true" do
70
- let(:query) { GraphQL::Query.new(Dummy::Schema, query_string, variables: variables, context: { analyze: true }) }
72
+ let(:query) { GraphQL::Query.new(schema, query_string, variables: variables, context: { analyze: true }) }
71
73
 
72
74
  it "it runs the analyzer" do
73
75
  # Both analyzers ran
@@ -93,7 +95,7 @@ describe GraphQL::Analysis do
93
95
  it "emits traces" do
94
96
  traces = TestTracing.with_trace do
95
97
  ctx = { tracers: [TestTracing] }
96
- Dummy::Schema.execute(query_string, context: ctx)
98
+ schema.execute(query_string, context: ctx)
97
99
  end
98
100
 
99
101
  # The query_trace is on the list _first_ because it finished first
@@ -119,14 +121,7 @@ describe GraphQL::Analysis do
119
121
  let(:variable_accessor) { ->(memo, visit_type, irep_node) { query.variables["cheeseId"] } }
120
122
 
121
123
  before do
122
- @previous_query_analyzers = Dummy::Schema.query_analyzers.dup
123
- Dummy::Schema.query_analyzers.clear
124
- Dummy::Schema.query_analyzers << variable_accessor
125
- end
126
-
127
- after do
128
- Dummy::Schema.query_analyzers.clear
129
- Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
124
+ schema.query_analyzer(variable_accessor)
130
125
  end
131
126
 
132
127
  it "returns an error" do
@@ -213,7 +208,7 @@ describe GraphQL::Analysis do
213
208
  let(:flavor_catcher) { FlavorCatcher.new }
214
209
  let(:analyzers) { [id_catcher, flavor_catcher] }
215
210
  let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
216
- let(:query) { GraphQL::Query.new(Dummy::Schema, query_string) }
211
+ let(:query) { GraphQL::Query.new(schema, query_string) }
217
212
  let(:query_string) {%|
218
213
  {
219
214
  cheese(id: 1) {
@@ -222,7 +217,12 @@ describe GraphQL::Analysis do
222
217
  }
223
218
  }
224
219
  |}
225
- let(:schema) { Dummy::Schema }
220
+ let(:schema) do
221
+ schema = Class.new(Dummy::Schema)
222
+ schema.query_analyzer(id_catcher)
223
+ schema.query_analyzer(flavor_catcher)
224
+ schema
225
+ end
226
226
  let(:result) { schema.execute(query_string) }
227
227
  let(:query_string) {%|
228
228
  {
@@ -233,17 +233,6 @@ describe GraphQL::Analysis do
233
233
  }
234
234
  |}
235
235
 
236
- before do
237
- @previous_query_analyzers = Dummy::Schema.query_analyzers.dup
238
- Dummy::Schema.query_analyzers.clear
239
- Dummy::Schema.query_analyzers << id_catcher << flavor_catcher
240
- end
241
-
242
- after do
243
- Dummy::Schema.query_analyzers.clear
244
- Dummy::Schema.query_analyzers.push(*@previous_query_analyzers)
245
- end
246
-
247
236
  it "groups all errors together" do
248
237
  data = result["data"]
249
238
  errors = result["errors"]