graphql 2.1.10 → 2.2.0

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

@@ -337,14 +337,16 @@ module GraphQL
337
337
  print_string("union ")
338
338
  print_string(union_type.name)
339
339
  print_directives(union_type.directives)
340
- print_string(" = ")
341
- i = 0
342
- union_type.types.each do |t|
343
- if i > 0
344
- print_string(" | ")
340
+ if union_type.types.any?
341
+ print_string(" = ")
342
+ i = 0
343
+ union_type.types.each do |t|
344
+ if i > 0
345
+ print_string(" | ")
346
+ end
347
+ print_string(t.name)
348
+ i += 1
345
349
  end
346
- print_string(t.name)
347
- i += 1
348
350
  end
349
351
  end
350
352
 
@@ -353,12 +355,14 @@ module GraphQL
353
355
  print_string("enum ")
354
356
  print_string(enum_type.name)
355
357
  print_directives(enum_type.directives)
356
- print_string(" {\n")
357
- enum_type.values.each.with_index do |value, i|
358
- print_description(value, indent: " ", first_in_block: i == 0)
359
- print_enum_value_definition(value)
358
+ if enum_type.values.any?
359
+ print_string(" {\n")
360
+ enum_type.values.each.with_index do |value, i|
361
+ print_description(value, indent: " ", first_in_block: i == 0)
362
+ print_enum_value_definition(value)
363
+ end
364
+ print_string("}")
360
365
  end
361
- print_string("}")
362
366
  end
363
367
 
364
368
  def print_enum_value_definition(enum_value)
@@ -384,6 +384,11 @@ module GraphQL
384
384
  (superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
385
385
  end
386
386
 
387
+ # @return [Boolean] Does this schema have _any_ definition for a type named `type_name`, regardless of visibility?
388
+ def has_defined_type?(type_name)
389
+ own_types.key?(type_name) || introspection_system.types.key?(type_name) || (superclass.respond_to?(:has_defined_type?) ? superclass.has_defined_type?(type_name) : false)
390
+ end
391
+
387
392
  # @api private
388
393
  attr_writer :connections
389
394
 
@@ -939,11 +944,7 @@ module GraphQL
939
944
  end
940
945
 
941
946
  def resolve_type(type, obj, ctx)
942
- if type.kind.object?
943
- type
944
- else
945
- raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
946
- end
947
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{type.name})"
947
948
  end
948
949
  # rubocop:enable Lint/DuplicateMethods
949
950
 
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Testing
4
+ module Helpers
5
+ # @param schema_class [Class<GraphQL::Schema>]
6
+ # @return [Module] A helpers module which always uses the given schema
7
+ def self.for(schema_class)
8
+ Module.new do
9
+ include SchemaHelpers
10
+ @@schema_class_for_helpers = schema_class
11
+ end
12
+ end
13
+
14
+ class Error < GraphQL::Error
15
+ end
16
+
17
+ class TypeNotVisibleError < Error
18
+ def initialize(type_name:)
19
+ message = "`#{type_name}` should be `visible?` this field resolution and `context`, but it was not"
20
+ super(message)
21
+ end
22
+ end
23
+
24
+ class FieldNotVisibleError < Error
25
+ def initialize(type_name:, field_name:)
26
+ message = "`#{type_name}.#{field_name}` should be `visible?` for this resolution, but it was not"
27
+ super(message)
28
+ end
29
+ end
30
+
31
+ class TypeNotDefinedError < Error
32
+ def initialize(type_name:)
33
+ message = "No type named `#{type_name}` is defined; choose another type name or define this type."
34
+ super(message)
35
+ end
36
+ end
37
+
38
+ class FieldNotDefinedError < Error
39
+ def initialize(type_name:, field_name:)
40
+ message = "`#{type_name}` has no field named `#{field_name}`; pick another name or define this field."
41
+ super(message)
42
+ end
43
+ end
44
+
45
+ def run_graphql_field(schema, field_path, object, arguments: {}, context: {})
46
+ type_name, *field_names = field_path.split(".")
47
+ dummy_query = GraphQL::Query.new(schema, context: context)
48
+ query_context = dummy_query.context
49
+ object_type = dummy_query.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
50
+ if object_type
51
+ graphql_result = object
52
+ field_names.each do |field_name|
53
+ inner_object = graphql_result
54
+ graphql_result = object_type.wrap(inner_object, query_context)
55
+ if graphql_result.nil?
56
+ return nil
57
+ end
58
+ visible_field = dummy_query.get_field(object_type, field_name)
59
+ if visible_field
60
+ dummy_query.context.dataloader.run_isolated {
61
+ field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
62
+ field_args = schema.sync_lazy(field_args)
63
+ graphql_result = visible_field.resolve(graphql_result, field_args.keyword_arguments, query_context)
64
+ graphql_result = schema.sync_lazy(graphql_result)
65
+ }
66
+ object_type = visible_field.type.unwrap
67
+ elsif object_type.all_field_definitions.any? { |f| f.graphql_name == field_name }
68
+ raise FieldNotVisibleError.new(field_name: field_name, type_name: type_name)
69
+ else
70
+ raise FieldNotDefinedError.new(type_name: type_name, field_name: field_name)
71
+ end
72
+ end
73
+ graphql_result
74
+ elsif schema.has_defined_type?(type_name)
75
+ raise TypeNotVisibleError.new(type_name: type_name)
76
+ else
77
+ raise TypeNotDefinedError.new(type_name: type_name)
78
+ end
79
+ end
80
+
81
+ def with_resolution_context(schema, type:, object:, context:{})
82
+ resolution_context = ResolutionAssertionContext.new(
83
+ self,
84
+ schema: schema,
85
+ type_name: type,
86
+ object: object,
87
+ context: context
88
+ )
89
+ yield(resolution_context)
90
+ end
91
+
92
+ class ResolutionAssertionContext
93
+ def initialize(test, type_name:, object:, schema:, context:)
94
+ @test = test
95
+ @type_name = type_name
96
+ @object = object
97
+ @schema = schema
98
+ @context = context
99
+ end
100
+
101
+
102
+ def run_graphql_field(field_name, arguments: {})
103
+ if @schema
104
+ @test.run_graphql_field(@schema, "#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
105
+ else
106
+ @test.run_graphql_field("#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
107
+ end
108
+ end
109
+ end
110
+
111
+ module SchemaHelpers
112
+ include Helpers
113
+
114
+ def run_graphql_field(field_path, object, arguments: {}, context: {})
115
+ super(@@schema_class_for_helpers, field_path, object, arguments: arguments, context: context)
116
+ end
117
+
118
+ def with_resolution_context(*args, **kwargs, &block)
119
+ # schema will be added later
120
+ super(nil, *args, **kwargs, &block)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/testing/helpers"
@@ -15,6 +15,7 @@ module GraphQL
15
15
  @query = query
16
16
  end
17
17
 
18
+ # The Ruby parser doesn't call this method (`graphql/c_parser` does.)
18
19
  def lex(query_string:)
19
20
  yield
20
21
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.1.10"
3
+ VERSION = "2.2.0"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -121,3 +121,4 @@ require "graphql/unauthorized_error"
121
121
  require "graphql/unauthorized_field_error"
122
122
  require "graphql/load_application_object_failed_error"
123
123
  require "graphql/deprecation"
124
+ require "graphql/testing"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.10
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-27 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: racc
@@ -309,6 +309,7 @@ files:
309
309
  - lib/graphql/backtrace/tracer.rb
310
310
  - lib/graphql/coercion_error.rb
311
311
  - lib/graphql/dataloader.rb
312
+ - lib/graphql/dataloader/async_dataloader.rb
312
313
  - lib/graphql/dataloader/null_dataloader.rb
313
314
  - lib/graphql/dataloader/request.rb
314
315
  - lib/graphql/dataloader/request_all.rb
@@ -360,7 +361,6 @@ files:
360
361
  - lib/graphql/language/lexer.rb
361
362
  - lib/graphql/language/nodes.rb
362
363
  - lib/graphql/language/parser.rb
363
- - lib/graphql/language/parser.y
364
364
  - lib/graphql/language/printer.rb
365
365
  - lib/graphql/language/sanitized_printer.rb
366
366
  - lib/graphql/language/static_visitor.rb
@@ -553,6 +553,8 @@ files:
553
553
  - lib/graphql/subscriptions/event.rb
554
554
  - lib/graphql/subscriptions/instrumentation.rb
555
555
  - lib/graphql/subscriptions/serialize.rb
556
+ - lib/graphql/testing.rb
557
+ - lib/graphql/testing/helpers.rb
556
558
  - lib/graphql/tracing.rb
557
559
  - lib/graphql/tracing/active_support_notifications_trace.rb
558
560
  - lib/graphql/tracing/active_support_notifications_tracing.rb