graphql 1.5.15 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +4 -19
  3. data/lib/graphql/analysis/analyze_query.rb +27 -2
  4. data/lib/graphql/analysis/query_complexity.rb +10 -11
  5. data/lib/graphql/argument.rb +7 -6
  6. data/lib/graphql/backwards_compatibility.rb +47 -0
  7. data/lib/graphql/compatibility/execution_specification.rb +14 -0
  8. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +6 -1
  9. data/lib/graphql/compatibility/lazy_execution_specification.rb +19 -0
  10. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +15 -6
  11. data/lib/graphql/directive.rb +1 -6
  12. data/lib/graphql/execution.rb +1 -0
  13. data/lib/graphql/execution/execute.rb +174 -160
  14. data/lib/graphql/execution/field_result.rb +5 -1
  15. data/lib/graphql/execution/lazy.rb +2 -2
  16. data/lib/graphql/execution/lazy/resolve.rb +8 -11
  17. data/lib/graphql/execution/multiplex.rb +134 -0
  18. data/lib/graphql/execution/selection_result.rb +5 -0
  19. data/lib/graphql/field.rb +1 -8
  20. data/lib/graphql/filter.rb +53 -0
  21. data/lib/graphql/internal_representation/node.rb +11 -6
  22. data/lib/graphql/internal_representation/rewrite.rb +3 -3
  23. data/lib/graphql/query.rb +160 -78
  24. data/lib/graphql/query/arguments.rb +14 -25
  25. data/lib/graphql/query/arguments_cache.rb +6 -13
  26. data/lib/graphql/query/context.rb +28 -10
  27. data/lib/graphql/query/executor.rb +1 -0
  28. data/lib/graphql/query/literal_input.rb +10 -4
  29. data/lib/graphql/query/null_context.rb +1 -1
  30. data/lib/graphql/query/serial_execution/field_resolution.rb +5 -1
  31. data/lib/graphql/query/validation_pipeline.rb +12 -7
  32. data/lib/graphql/query/variables.rb +1 -1
  33. data/lib/graphql/rake_task.rb +140 -0
  34. data/lib/graphql/relay/array_connection.rb +29 -48
  35. data/lib/graphql/relay/base_connection.rb +9 -7
  36. data/lib/graphql/relay/mutation.rb +0 -11
  37. data/lib/graphql/relay/mutation/instrumentation.rb +2 -2
  38. data/lib/graphql/relay/mutation/resolve.rb +7 -10
  39. data/lib/graphql/relay/relation_connection.rb +98 -61
  40. data/lib/graphql/scalar_type.rb +1 -15
  41. data/lib/graphql/schema.rb +90 -25
  42. data/lib/graphql/schema/build_from_definition.rb +22 -23
  43. data/lib/graphql/schema/build_from_definition/resolve_map.rb +70 -0
  44. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  45. data/lib/graphql/schema/middleware_chain.rb +1 -1
  46. data/lib/graphql/schema/printer.rb +2 -1
  47. data/lib/graphql/schema/timeout_middleware.rb +6 -6
  48. data/lib/graphql/schema/type_map.rb +1 -1
  49. data/lib/graphql/schema/warden.rb +5 -9
  50. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  51. data/lib/graphql/version.rb +1 -1
  52. data/spec/graphql/analysis/analyze_query_spec.rb +2 -2
  53. data/spec/graphql/analysis/max_query_complexity_spec.rb +28 -0
  54. data/spec/graphql/argument_spec.rb +3 -3
  55. data/spec/graphql/execution/lazy_spec.rb +8 -114
  56. data/spec/graphql/execution/multiplex_spec.rb +131 -0
  57. data/spec/graphql/internal_representation/rewrite_spec.rb +10 -0
  58. data/spec/graphql/query/arguments_spec.rb +14 -16
  59. data/spec/graphql/query/context_spec.rb +14 -1
  60. data/spec/graphql/query/literal_input_spec.rb +19 -13
  61. data/spec/graphql/query/variables_spec.rb +1 -1
  62. data/spec/graphql/query_spec.rb +12 -1
  63. data/spec/graphql/rake_task_spec.rb +57 -0
  64. data/spec/graphql/relay/array_connection_spec.rb +24 -3
  65. data/spec/graphql/relay/connection_instrumentation_spec.rb +23 -0
  66. data/spec/graphql/relay/mutation_spec.rb +2 -10
  67. data/spec/graphql/relay/page_info_spec.rb +2 -2
  68. data/spec/graphql/relay/relation_connection_spec.rb +167 -3
  69. data/spec/graphql/schema/build_from_definition_spec.rb +93 -19
  70. data/spec/graphql/schema/warden_spec.rb +80 -0
  71. data/spec/graphql/schema_spec.rb +26 -2
  72. data/spec/spec_helper.rb +4 -2
  73. data/spec/support/lazy_helpers.rb +152 -0
  74. data/spec/support/star_wars/schema.rb +23 -0
  75. metadata +28 -3
  76. data/lib/graphql/schema/mask.rb +0 -55
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/schema/build_from_definition/resolve_map"
3
+
2
4
  module GraphQL
3
5
  class Schema
4
6
  module BuildFromDefinition
@@ -23,24 +25,6 @@ module GraphQL
23
25
  end
24
26
  end
25
27
 
26
- # @api private
27
- class ResolveMap
28
- def initialize(resolve_hash)
29
- @resolve_hash = resolve_hash
30
- end
31
-
32
- def call(type, field, obj, args, ctx)
33
- type_hash = @resolve_hash[type.name]
34
- type_hash && (resolver = type_hash[field.name])
35
-
36
- if resolver.nil?
37
- raise(KeyError, "resolver not found for #{type.name}.#{field.name}")
38
- else
39
- resolver.call(obj, args, ctx)
40
- end
41
- end
42
- end
43
-
44
28
  # @api private
45
29
  module Builder
46
30
  extend self
@@ -72,7 +56,7 @@ module GraphQL
72
56
  when GraphQL::Language::Nodes::UnionTypeDefinition
73
57
  types[definition.name] = build_union_type(definition, type_resolver)
74
58
  when GraphQL::Language::Nodes::ScalarTypeDefinition
75
- types[definition.name] = build_scalar_type(definition, type_resolver)
59
+ types[definition.name] = build_scalar_type(definition, type_resolver, default_resolve: default_resolve)
76
60
  when GraphQL::Language::Nodes::InputObjectTypeDefinition
77
61
  types[definition.name] = build_input_object_type(definition, type_resolver)
78
62
  when GraphQL::Language::Nodes::DirectiveDefinition
@@ -107,17 +91,23 @@ module GraphQL
107
91
 
108
92
  raise InvalidDocumentError.new('Must provide schema definition with query type or a type named Query.') unless query_root_type
109
93
 
110
- Schema.define do
94
+ schema = Schema.define do
111
95
  raise_definition_error true
112
96
 
113
97
  query query_root_type
114
98
  mutation mutation_root_type
115
99
  subscription subscription_root_type
116
100
  orphan_types types.values
117
- resolve_type NullResolveType
101
+ if default_resolve.respond_to?(:resolve_type)
102
+ resolve_type(default_resolve.method(:resolve_type))
103
+ else
104
+ resolve_type(NullResolveType)
105
+ end
118
106
 
119
107
  directives directives.values
120
108
  end
109
+
110
+ schema
121
111
  end
122
112
 
123
113
  NullResolveType = ->(obj, ctx) {
@@ -151,12 +141,21 @@ module GraphQL
151
141
  reason.value
152
142
  end
153
143
 
154
- def build_scalar_type(scalar_type_definition, type_resolver)
155
- GraphQL::ScalarType.define(
144
+ def build_scalar_type(scalar_type_definition, type_resolver, default_resolve:)
145
+ scalar_type = GraphQL::ScalarType.define(
156
146
  name: scalar_type_definition.name,
157
147
  description: scalar_type_definition.description,
158
148
  coerce: NullScalarCoerce,
159
149
  )
150
+
151
+ if default_resolve.respond_to?(:coerce_input)
152
+ scalar_type = scalar_type.redefine(
153
+ coerce_input: ->(val, ctx) { default_resolve.coerce_input(scalar_type, val, ctx) },
154
+ coerce_result: ->(val, ctx) { default_resolve.coerce_result(scalar_type, val, ctx) },
155
+ )
156
+ end
157
+
158
+ scalar_type
160
159
  end
161
160
 
162
161
  def build_union_type(union_type_definition, type_resolver)
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/schema/build_from_definition/resolve_map/default_resolve"
3
+
4
+ module GraphQL
5
+ class Schema
6
+ module BuildFromDefinition
7
+ # Wrap a user-provided hash of resolution behavior for easy access at runtime.
8
+ #
9
+ # Coerce scalar values by:
10
+ # - Checking for a function in the map like `{ Date: { coerce_input: ->(val, ctx) { ... }, coerce_result: ->(val, ctx) { ... } } }`
11
+ # - Falling back to a passthrough
12
+ #
13
+ # Interface/union resolution can be provided as a `resolve_type:` key.
14
+ #
15
+ # @api private
16
+ class ResolveMap
17
+ def initialize(user_resolve_hash)
18
+ @resolve_hash = Hash.new do |h, k|
19
+ # For each type name, provide a new hash if one wasn't given:
20
+ h[k] = Hash.new do |h2, k2|
21
+ if k2 == "coerce_input" || k2 == "coerce_result"
22
+ # This isn't an object field, it's a scalar coerce function.
23
+ # Use a passthrough
24
+ Builder::NullScalarCoerce
25
+ else
26
+ # For each field, provide a resolver that will
27
+ # make runtime checks & replace itself
28
+ h2[k2] = DefaultResolve.new(h2, k2)
29
+ end
30
+ end
31
+ end
32
+ @user_resolve_hash = user_resolve_hash
33
+ # User-provided resolve functions take priority over the default:
34
+ @user_resolve_hash.each do |type_name, fields|
35
+ type_name_s = type_name.to_s
36
+ case fields
37
+ when Hash
38
+ fields.each do |field_name, resolve_fn|
39
+ @resolve_hash[type_name_s][field_name.to_s] = resolve_fn
40
+ end
41
+ when Proc
42
+ # for example, __resolve_type
43
+ @resolve_hash[type_name_s] = fields
44
+ end
45
+ end
46
+
47
+ # Check the normalized hash, not the user input:
48
+ if @resolve_hash.key?("resolve_type")
49
+ define_singleton_method :resolve_type do |type, ctx|
50
+ @resolve_hash.fetch("resolve_type").call(type, ctx)
51
+ end
52
+ end
53
+ end
54
+
55
+ def call(type, field, obj, args, ctx)
56
+ resolver = @resolve_hash[type.name][field.name]
57
+ resolver.call(obj, args, ctx)
58
+ end
59
+
60
+ def coerce_input(type, value, ctx)
61
+ @resolve_hash[type.name]["coerce_input"].call(value, ctx)
62
+ end
63
+
64
+ def coerce_result(type, value, ctx)
65
+ @resolve_hash[type.name]["coerce_result"].call(value, ctx)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ module BuildFromDefinition
5
+ class ResolveMap
6
+ class DefaultResolve
7
+ def initialize(field_map, field_name)
8
+ @field_map = field_map
9
+ @field_name = field_name
10
+ end
11
+
12
+ # Make some runtime checks about
13
+ # how `obj` implements the `field_name`.
14
+ #
15
+ # Create a new resolve function according to that implementation, then:
16
+ # - update `field_map` with this implementation
17
+ # - call the implementation now (to satisfy this field execution)
18
+ #
19
+ # If `obj` doesn't implement `field_name`, raise an error.
20
+ def call(obj, args, ctx)
21
+ method_name = @field_name
22
+ if !obj.respond_to?(method_name)
23
+ raise KeyError, "Can't resolve field #{method_name} on #{obj}"
24
+ else
25
+ method_arity = obj.method(method_name).arity
26
+ resolver = case method_arity
27
+ when 0, -1
28
+ # -1 Handles method_missing, eg openstruct
29
+ ->(o, a, c) { o.public_send(method_name) }
30
+ when 1
31
+ ->(o, a, c) { o.public_send(method_name, a) }
32
+ when 2
33
+ ->(o, a, c) { o.public_send(method_name, a, c) }
34
+ else
35
+ raise "Unexpected resolve arity: #{method_arity}. Must be 0, 1, 2"
36
+ end
37
+ # Call the resolver directly next time
38
+ @field_map[method_name] = resolver
39
+ # Call through this time
40
+ resolver.call(obj, args, ctx)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -5,7 +5,7 @@ module GraphQL
5
5
  #
6
6
  # Steps should call `next_step.call` to continue the chain, or _not_ call it to stop the chain.
7
7
  class MiddlewareChain
8
- extend GraphQL::Delegate
8
+ extend Forwardable
9
9
 
10
10
  # @return [Array<#call(*args)>] Steps in this chain, will be called with arguments and `next_middleware`
11
11
  attr_reader :steps, :final_step
@@ -49,7 +49,8 @@ module GraphQL
49
49
  @context = context
50
50
 
51
51
  blacklist = build_blacklist(only, except, introspection: introspection)
52
- @warden = GraphQL::Schema::Warden.new(blacklist, schema: @schema, context: @context)
52
+ filter = GraphQL::Filter.new(except: blacklist)
53
+ @warden = GraphQL::Schema::Warden.new(filter, schema: @schema, context: @context)
53
54
  end
54
55
 
55
56
  # Return the GraphQL schema string for the introspection type system
@@ -24,18 +24,18 @@ module GraphQL
24
24
  # end
25
25
  #
26
26
  class TimeoutMiddleware
27
- # This key is used for storing timeout data in the {Query::Context} instance
28
- DEFAULT_CONTEXT_KEY = :__timeout_at__
29
27
  # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
30
- # @param context_key [Symbol] what key should be used to read and write to the query context
31
- def initialize(max_seconds:, context_key: DEFAULT_CONTEXT_KEY, &block)
28
+ def initialize(max_seconds:, context_key: nil, &block)
32
29
  @max_seconds = max_seconds
33
- @context_key = context_key
30
+ if context_key
31
+ warn("TimeoutMiddleware's `context_key` is ignored, timeout data is now stored in isolated storage")
32
+ end
34
33
  @error_handler = block
35
34
  end
36
35
 
37
36
  def call(parent_type, parent_object, field_definition, field_args, query_context)
38
- timeout_at = query_context[@context_key] ||= Time.now + @max_seconds
37
+ ns = query_context.namespace(TimeoutMiddleware)
38
+ timeout_at = ns[:timeout_at] ||= Time.now + @max_seconds
39
39
 
40
40
  if timeout_at < Time.now
41
41
  on_timeout(parent_type, parent_object, field_definition, field_args, query_context)
@@ -8,7 +8,7 @@ module GraphQL
8
8
  #
9
9
  # If you want a type, but want to handle the undefined case, use {#fetch}.
10
10
  class TypeMap
11
- extend GraphQL::Delegate
11
+ extend Forwardable
12
12
  def_delegators :@storage, :key?, :keys, :values, :to_h, :fetch, :each, :each_value
13
13
 
14
14
  def initialize
@@ -1,21 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  class Schema
4
- # Restrict access to a {GraphQL::Schema} with a user-defined mask.
5
- #
6
- # The mask is object that responds to `#visible?(schema_member)`.
4
+ # Restrict access to a {GraphQL::Schema} with a user-defined filter.
7
5
  #
8
6
  # When validating and executing a query, all access to schema members
9
7
  # should go through a warden. If you access the schema directly,
10
8
  # you may show a client something that it shouldn't be allowed to see.
11
9
  #
12
- # Masks can be provided in {Schema#execute} (or {Query#initialize}) with the `mask:` keyword.
13
- #
14
10
  # @example Hidding private fields
15
11
  # private_members = -> (member, ctx) { member.metadata[:private] }
16
12
  # result = Schema.execute(query_string, except: private_members)
17
13
  #
18
- # @example Custom mask implementation
14
+ # @example Custom filter implementation
19
15
  # # It must respond to `#call(member)`.
20
16
  # class MissingRequiredFlags
21
17
  # def initialize(user)
@@ -38,13 +34,13 @@ module GraphQL
38
34
  #
39
35
  # @api private
40
36
  class Warden
41
- # @param mask [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
37
+ # @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
42
38
  # @param context [GraphQL::Query::Context]
43
39
  # @param schema [GraphQL::Schema]
44
40
  # @param deep_check [Boolean]
45
- def initialize(mask, context:, schema:)
41
+ def initialize(filter, context:, schema:)
46
42
  @schema = schema
47
- @visibility_cache = read_through { |m| !mask.call(m, context) }
43
+ @visibility_cache = read_through { |m| filter.call(m, context) }
48
44
  end
49
45
 
50
46
  # @return [Array<GraphQL::BaseType>] Visible types in the schema
@@ -103,7 +103,7 @@ module GraphQL
103
103
  end
104
104
 
105
105
  class NodeWithPath
106
- extend GraphQL::Delegate
106
+ extend Forwardable
107
107
  attr_reader :node, :path
108
108
  def initialize(node, path)
109
109
  @node = node
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.5.15"
3
+ VERSION = "1.6.0"
4
4
  end
@@ -9,7 +9,7 @@ describe GraphQL::Analysis do
9
9
 
10
10
  def call(memo, visit_type, irep_node)
11
11
  if visit_type == :enter
12
- memo + [irep_node.return_type]
12
+ memo + [irep_node.return_type.unwrap]
13
13
  else
14
14
  memo
15
15
  end
@@ -83,7 +83,7 @@ describe GraphQL::Analysis do
83
83
  memo ||= Hash.new { |h,k| h[k] = 0 }
84
84
  if visit_type == :enter
85
85
  if irep_node.ast_node.is_a?(GraphQL::Language::Nodes::Field)
86
- if irep_node.definition.resolve_proc.is_a?(GraphQL::Relay::ConnectionResolve)
86
+ if irep_node.definition.connection?
87
87
  memo[:connection] ||= 0
88
88
  memo[:connection] += 1
89
89
  else
@@ -60,4 +60,32 @@ describe GraphQL::Analysis::MaxQueryComplexity do
60
60
  assert_equal "Query has complexity of 10, which exceeds max complexity of 7", result["errors"][0]["message"]
61
61
  end
62
62
  end
63
+
64
+ describe "across a multiplex" do
65
+ before do
66
+ Dummy::Schema.max_complexity = 9
67
+ end
68
+
69
+ let(:queries) { 5.times.map { |n| { query: "{ cheese(id: #{n}) { id } }" } } }
70
+
71
+ it "returns errors for all queries" do
72
+ results = Dummy::Schema.multiplex(queries)
73
+ assert_equal 5, results.length
74
+ err_msg = "Query has complexity of 10, which exceeds max complexity of 9"
75
+ results.each do |res|
76
+ assert_equal err_msg, res["errors"][0]["message"]
77
+ end
78
+ end
79
+
80
+ describe "with a local override" do
81
+ it "uses the override" do
82
+ results = Dummy::Schema.multiplex(queries, max_complexity: 10)
83
+ assert_equal 5, results.length
84
+ results.each do |res|
85
+ assert_equal true, res.key?("data")
86
+ assert_equal false, res.key?("errors")
87
+ end
88
+ end
89
+ end
90
+ end
63
91
  end
@@ -60,14 +60,14 @@ describe GraphQL::Argument do
60
60
 
61
61
  describe "prepare" do
62
62
  it "accepts a prepare proc and calls it to generate the prepared value" do
63
- prepare_proc = Proc.new { |arg| arg + 1 }
63
+ prepare_proc = Proc.new { |arg, ctx| arg + ctx[:val] }
64
64
  argument = GraphQL::Argument.define(name: :plusOne, type: GraphQL::INT_TYPE, prepare: prepare_proc)
65
- assert_equal argument.prepare(1), 2
65
+ assert_equal argument.prepare(1, {val: 1}), 2
66
66
  end
67
67
 
68
68
  it "returns the value itself if no prepare proc is provided" do
69
69
  argument = GraphQL::Argument.define(name: :someNumber, type: GraphQL::INT_TYPE)
70
- assert_equal argument.prepare(1), 1
70
+ assert_equal argument.prepare(1, nil), 1
71
71
  end
72
72
  end
73
73
  end
@@ -2,117 +2,11 @@
2
2
  require "spec_helper"
3
3
 
4
4
  describe GraphQL::Execution::Lazy do
5
- class Wrapper
6
- def initialize(item = nil, &block)
7
- if block
8
- @block = block
9
- else
10
- @item = item
11
- end
12
- end
13
-
14
- def item
15
- if @block
16
- @item = @block.call()
17
- @block = nil
18
- end
19
- @item
20
- end
21
- end
22
-
23
- class SumAll
24
- attr_reader :own_value
25
- attr_accessor :value
26
-
27
- def initialize(ctx, own_value)
28
- @own_value = own_value
29
- @all = ctx[:__sum_all__] ||= []
30
- @all << self
31
- end
32
-
33
- def value
34
- @value ||= begin
35
- total_value = @all.map(&:own_value).reduce(&:+)
36
- @all.each { |v| v.value = total_value}
37
- @all.clear
38
- total_value
39
- end
40
- @value
41
- end
42
- end
43
-
44
- LazySum = GraphQL::ObjectType.define do
45
- name "LazySum"
46
- field :value, types.Int do
47
- resolve ->(o, a, c) { o == 13 ? nil : o }
48
- end
49
- field :nestedSum, !LazySum do
50
- argument :value, !types.Int
51
- resolve ->(o, args, c) {
52
- if args[:value] == 13
53
- Wrapper.new(nil)
54
- else
55
- SumAll.new(c, o + args[:value])
56
- end
57
- }
58
- end
59
-
60
- field :nullableNestedSum, LazySum do
61
- argument :value, types.Int
62
- resolve ->(o, args, c) {
63
- if args[:value] == 13
64
- Wrapper.new(nil)
65
- else
66
- SumAll.new(c, o + args[:value])
67
- end
68
- }
69
- end
70
- end
71
-
72
- LazyQuery = GraphQL::ObjectType.define do
73
- name "Query"
74
- field :int, !types.Int do
75
- argument :value, !types.Int
76
- argument :plus, types.Int, default_value: 0
77
- resolve ->(o, a, c) { Wrapper.new(a[:value] + a[:plus])}
78
- end
79
-
80
- field :nestedSum, !LazySum do
81
- argument :value, !types.Int
82
- resolve ->(o, args, c) { SumAll.new(c, args[:value]) }
83
- end
84
-
85
- field :nullableNestedSum, LazySum do
86
- argument :value, types.Int
87
- resolve ->(o, args, c) {
88
- if args[:value] == 13
89
- Wrapper.new { raise GraphQL::ExecutionError.new("13 is unlucky") }
90
- else
91
- SumAll.new(c, args[:value])
92
- end
93
- }
94
- end
95
-
96
- field :listSum, types[LazySum] do
97
- argument :values, types[types.Int]
98
- resolve ->(o, args, c) { args[:values] }
99
- end
100
- end
101
-
102
- LazySchema = GraphQL::Schema.define do
103
- query(LazyQuery)
104
- mutation(LazyQuery)
105
- lazy_resolve(Wrapper, :item)
106
- lazy_resolve(SumAll, :value)
107
- end
108
-
109
- def run_query(query_str)
110
- LazySchema.execute(query_str)
111
- end
5
+ include LazyHelpers
112
6
 
113
7
  describe "resolving" do
114
8
  it "calls value handlers" do
115
- res = run_query('{ int(value: 2, plus: 1)}')
9
+ res = run_query('{ int(value: 2, plus: 1) }')
116
10
  assert_equal 3, res["data"]["int"]
117
11
  end
118
12
 
@@ -234,16 +128,16 @@ describe GraphQL::Execution::Lazy do
234
128
  end
235
129
 
236
130
  describe "LazyMethodMap" do
237
- class SubWrapper < Wrapper; end
131
+ class SubWrapper < LazyHelpers::Wrapper; end
238
132
 
239
133
  let(:map) { GraphQL::Execution::Lazy::LazyMethodMap.new }
240
134
 
241
135
  it "finds methods for classes and subclasses" do
242
- map.set(Wrapper, :item)
243
- map.set(SumAll, :value)
244
- b = Wrapper.new(1)
245
- sub_b = Wrapper.new(2)
246
- s = SumAll.new({}, 3)
136
+ map.set(LazyHelpers::Wrapper, :item)
137
+ map.set(LazyHelpers::SumAll, :value)
138
+ b = LazyHelpers::Wrapper.new(1)
139
+ sub_b = LazyHelpers::Wrapper.new(2)
140
+ s = LazyHelpers::SumAll.new({}, 3)
247
141
  assert_equal(:item, map.get(b))
248
142
  assert_equal(:item, map.get(sub_b))
249
143
  assert_equal(:value, map.get(s))