graphql 1.7.2 → 1.7.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2fb4d91df18b66c7d1c4a9c712ee771aedb00655
4
- data.tar.gz: c787072c016f6995c4742f086cabe05d6d8c931b
3
+ metadata.gz: '08e688c4046aa3130fe9f427f810356abc25abfc'
4
+ data.tar.gz: d2896b9042f2bab1dffd256551082168aa52288d
5
5
  SHA512:
6
- metadata.gz: 58bee87006d10dfc306e17733770d899a93113c5836e30bba8443330afd2131d49e1a35a24606e20a69762b16450a0b779c7cd5dba03b46d70fa880f7e3b560c
7
- data.tar.gz: 6369f05cdb38c7d960abab0bd927794f122ac7d82e8c8c422d044ede6d5f099ccd28c532f044ae69a8b89af97306866720996ae1591142e8f9e93bfea89a0b24
6
+ metadata.gz: 624eb16565591d5df45dc69df9dc5cc7fa6b97ca9ff4d3745427df47e979a15e889458689f1e52d9f8a553b0974f738cb2cff703d1fc98dcc25cfbffee36f408
7
+ data.tar.gz: 0421334ac91f05b8a0adf48199b811eb81efbcfd4a0c543bf3ff58248e9db3c4c1ba036d5cbeffca69fcb12e10d07e88fa0cf9896cbfd081b884da5d62f5aa8c
@@ -43,7 +43,7 @@ module GraphQL
43
43
  when GraphQL::Execution::Lazy
44
44
  "(unresolved)"
45
45
  else
46
- obj.inspect
46
+ "#{obj.inspect}"
47
47
  end
48
48
  end
49
49
  end
@@ -87,7 +87,7 @@ module GraphQL
87
87
  rows << [
88
88
  "#{position}",
89
89
  "#{field_name}#{field_alias ? " as #{field_alias}" : ""}",
90
- ctx.object.inspect,
90
+ "#{ctx.object.inspect}",
91
91
  ctx.irep_node.arguments.to_h.inspect,
92
92
  Backtrace::InspectResult.inspect(top && @override_value ? @override_value : ctx.value),
93
93
  ]
@@ -107,7 +107,7 @@ module GraphQL
107
107
  rows << [
108
108
  "#{position}",
109
109
  "#{op_type}#{op_name ? " #{op_name}" : ""}",
110
- query.root_value.inspect,
110
+ "#{query.root_value.inspect}",
111
111
  query.variables.to_h.inspect,
112
112
  Backtrace::InspectResult.inspect(query.context.value),
113
113
  ]
@@ -96,7 +96,7 @@ module GraphQL
96
96
  end
97
97
  end
98
98
 
99
- arguments_class.instantiate_arguments(input_values)
99
+ arguments_class.new(input_values)
100
100
  end
101
101
 
102
102
  # @api private
@@ -1,48 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  class Query
4
- class StaticArguments
5
- attr_reader :argument_definitions
6
-
7
- def initialize(argument_definitions:)
8
- @argument_definitions = argument_definitions
9
- end
10
-
11
- def instantiate_arguments(values)
12
- arg_class.new(values, argument_definitions: argument_definitions)
13
- end
14
-
15
- private
16
-
17
- def arg_class
18
- @arg_class ||= begin
19
- klass = Class.new(GraphQL::Query::Arguments).instance_exec(self) do |static_arguments|
20
- static_arguments.argument_definitions.each do |_arg_name, arg_definition|
21
- expose_as = arg_definition.expose_as.to_s
22
-
23
- # Don't define a helper method if it would override something.
24
- if instance_methods.include?(expose_as)
25
- warn(
26
- "Unable to define a helper for argument with name '#{expose_as}' "\
27
- "as this is a reserved name. If you're using an argument such as "\
28
- "`argument #{expose_as}`, consider renaming this argument.`"
29
- )
30
- next
31
- end
32
-
33
- define_method(expose_as) do
34
- self[expose_as]
35
- end
36
- end
37
-
38
- self
39
- end
40
-
41
- klass
42
- end
43
- end
44
- end
45
-
46
4
  # Read-only access to values, normalizing all keys to strings
47
5
  #
48
6
  # {Arguments} recursively wraps the input in {Arguments} instances.
@@ -50,8 +8,32 @@ module GraphQL
50
8
  extend GraphQL::Delegate
51
9
 
52
10
  def self.construct_arguments_class(argument_owner)
53
- arguments_class = GraphQL::Query::StaticArguments.new(argument_definitions: argument_owner.arguments)
54
- argument_owner.arguments_class = arguments_class
11
+ argument_definitions = argument_owner.arguments
12
+ argument_owner.arguments_class = Class.new(self) do
13
+ self.argument_definitions = argument_definitions
14
+
15
+ def initialize(values)
16
+ super(values, argument_definitions: self.class.argument_definitions)
17
+ end
18
+
19
+ argument_definitions.each do |_arg_name, arg_definition|
20
+ expose_as = arg_definition.expose_as.to_s
21
+
22
+ # Don't define a helper method if it would override something.
23
+ if instance_methods.include?(expose_as)
24
+ warn(
25
+ "Unable to define a helper for argument with name '#{expose_as}' "\
26
+ "as this is a reserved name. If you're using an argument such as "\
27
+ "`argument #{expose_as}`, consider renaming this argument.`"
28
+ )
29
+ next
30
+ end
31
+
32
+ define_method(expose_as) do
33
+ self[expose_as]
34
+ end
35
+ end
36
+ end
55
37
  end
56
38
 
57
39
  def initialize(values, argument_definitions:)
@@ -105,6 +87,10 @@ module GraphQL
105
87
 
106
88
  NO_ARGS = self.new({}, argument_definitions: [])
107
89
 
90
+ class << self
91
+ attr_accessor :argument_definitions
92
+ end
93
+
108
94
  private
109
95
 
110
96
  class ArgumentValue
@@ -129,7 +115,7 @@ module GraphQL
129
115
  wrap_value(value, arg_defn_type.of_type)
130
116
  when GraphQL::InputObjectType
131
117
  if value.is_a?(Hash)
132
- self.class.new(value, argument_definitions: arg_defn_type.arguments)
118
+ arg_defn_type.arguments_class.new(value)
133
119
  else
134
120
  value
135
121
  end
@@ -105,7 +105,7 @@ module GraphQL
105
105
  end
106
106
  end
107
107
 
108
- argument_owner.arguments_class.instantiate_arguments(values_hash)
108
+ argument_owner.arguments_class.new(values_hash)
109
109
  end
110
110
  end
111
111
  end
@@ -140,6 +140,10 @@ module GraphQL
140
140
  raise NotImplementedError, "must return a cursor for this object/connection pair"
141
141
  end
142
142
 
143
+ def inspect
144
+ "#<GraphQL::Relay::Connection @parent=#{@parent.inspect} @arguments=#{@arguments.to_h.inspect}>"
145
+ end
146
+
143
147
  private
144
148
 
145
149
  # Return a sanitized `arguments[arg_name]` (don't allow negatives)
@@ -4,7 +4,7 @@ module GraphQL
4
4
  # Mostly an internal concern.
5
5
  #
6
6
  # Wraps an object as a `node`, and exposes a connection-specific `cursor`.
7
- class Edge < GraphQL::ObjectType
7
+ class Edge
8
8
  attr_reader :node, :connection
9
9
  def initialize(node, connection)
10
10
  @node = node
@@ -18,6 +18,10 @@ module GraphQL
18
18
  def parent
19
19
  @parent ||= connection.parent
20
20
  end
21
+
22
+ def inspect
23
+ "#<GraphQL::Relay::Edge (#{parent.inspect} => #{node.inspect})>"
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -104,10 +104,13 @@ module GraphQL
104
104
  end
105
105
 
106
106
  def visit_field_on_type(type_defn, field_defn, dynamic_field: false)
107
- instrumented_field_defn = @field_instrumenters.reduce(field_defn) do |defn, inst|
108
- inst.instrument(type_defn, defn)
109
- end
110
- if !dynamic_field
107
+ if dynamic_field
108
+ # Don't apply instrumentation to dynamic fields since they're shared constants
109
+ instrumented_field_defn = field_defn
110
+ else
111
+ instrumented_field_defn = @field_instrumenters.reduce(field_defn) do |defn, inst|
112
+ inst.instrument(type_defn, defn)
113
+ end
111
114
  @instrumented_field_map[type_defn.name][instrumented_field_defn.name] = instrumented_field_defn
112
115
  end
113
116
  @type_reference_map[instrumented_field_defn.type.unwrap.name] << instrumented_field_defn
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.7.2"
3
+ VERSION = "1.7.3"
4
4
  end
@@ -16,11 +16,25 @@ describe GraphQL::Backtrace do
16
16
  end
17
17
  end
18
18
 
19
+ class ErrorAnalyzer
20
+ def call(_memo, visit_type, irep_node)
21
+ if irep_node.name == "raiseError"
22
+ raise GraphQL::AnalysisError, "this should not be wrapped by a backtrace, but instead, returned to the client"
23
+ end
24
+ end
25
+ end
26
+
27
+ class NilInspectObject
28
+ # Oops, this is evil, but it happens and we should handle it.
29
+ def inspect; nil; end
30
+ end
31
+
19
32
  let(:resolvers) {
20
33
  {
21
34
  "Query" => {
22
35
  "field1" => Proc.new { :something },
23
36
  "field2" => Proc.new { :something },
37
+ "nilInspect" => Proc.new { NilInspectObject.new },
24
38
  },
25
39
  "Thing" => {
26
40
  "listField" => Proc.new { :not_a_list },
@@ -36,6 +50,7 @@ describe GraphQL::Backtrace do
36
50
  type Query {
37
51
  field1: Thing
38
52
  field2: OtherThing
53
+ nilInspect: Thing
39
54
  }
40
55
 
41
56
  type Thing {
@@ -49,6 +64,7 @@ describe GraphQL::Backtrace do
49
64
  GRAPHQL
50
65
  GraphQL::Schema.from_definition(defn, default_resolve: resolvers).redefine {
51
66
  lazy_resolve(LazyError, :raise_err)
67
+ query_analyzer(ErrorAnalyzer.new)
52
68
  }
53
69
  }
54
70
 
@@ -103,7 +119,7 @@ describe GraphQL::Backtrace do
103
119
  assert_includes err.message, rendered_table
104
120
  # The message includes the original error message
105
121
  assert_includes err.message, "This is broken: Boom"
106
- assert_includes err.message, "spec/graphql/backtrace_spec.rb:27", "It includes the original backtrace"
122
+ assert_includes err.message, "spec/graphql/backtrace_spec.rb:41", "It includes the original backtrace"
107
123
  assert_includes err.message, "more lines"
108
124
  end
109
125
 
@@ -133,6 +149,26 @@ describe GraphQL::Backtrace do
133
149
  ].join("\n")
134
150
  assert_includes err.message, rendered_table
135
151
  end
152
+
153
+ it "returns analysis errors to the client" do
154
+ res = schema.execute("query raiseError { __typename }")
155
+ assert_equal "this should not be wrapped by a backtrace, but instead, returned to the client", res["errors"].first["message"]
156
+ end
157
+
158
+ it "always stringifies the #inspect response" do
159
+ err = assert_raises(GraphQL::Backtrace::TracedError) {
160
+ schema.execute("query { nilInspect { raiseField(message: \"pop!\") } }")
161
+ }
162
+
163
+ rendered_table = [
164
+ 'Loc | Field | Object | Arguments | Result',
165
+ '1:22 | Thing.raiseField | | {"message"=>"pop!"} | #<RuntimeError: This is broken: pop!>',
166
+ '1:9 | Query.nilInspect | nil | {} | {}',
167
+ '1:1 | query | nil | {} | {}',
168
+ ].join("\n")
169
+
170
+ assert_includes(err.message, rendered_table)
171
+ end
136
172
  end
137
173
 
138
174
  # This will get brittle when execution code moves between files
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Introspection::TypeByNameField do
5
+ describe "after instrumentation" do
6
+ # Just make sure it returns a new object, not the original field
7
+ class DupInstrumenter
8
+ def self.instrument(t, f)
9
+ f.redefine {
10
+ resolve ->(o, a, c) { :no_op }
11
+ }
12
+ end
13
+ end
14
+
15
+ class ArgAnalyzer
16
+ def call(_, _, node)
17
+ if node.ast_node.is_a?(GraphQL::Language::Nodes::Field)
18
+ node.arguments
19
+ end
20
+ end
21
+ end
22
+
23
+ let(:instrumented_schema) {
24
+ # This was probably assigned earlier in the test suite, but to simulate an application, clear it.
25
+ GraphQL::Introspection::TypeByNameField.arguments_class = nil
26
+
27
+ Dummy::Schema.redefine {
28
+ instrument(:field, DupInstrumenter)
29
+ query_analyzer(ArgAnalyzer.new)
30
+ }
31
+ }
32
+
33
+ it "still works with __type" do
34
+ res = instrumented_schema.execute("{ __type(name: \"X\") { name } }")
35
+ assert_equal({"data"=>{"__type"=>nil}}, res)
36
+ end
37
+ end
38
+ end
@@ -90,13 +90,15 @@ describe GraphQL::Query::Arguments do
90
90
  argument :b, test_input_type
91
91
  argument :c, types.Int # will be a hash
92
92
  end
93
+ GraphQL::Query::Arguments.construct_arguments_class(test_input_type)
94
+ test_input_type
93
95
  }
94
96
  it "wraps input objects, but not other hashes" do
95
97
  args = GraphQL::Query::Arguments.new(
96
98
  {a: 1, b: {a: 2}, c: {a: 3}},
97
99
  argument_definitions: input_type.arguments
98
100
  )
99
- assert_instance_of GraphQL::Query::Arguments, args["b"]
101
+ assert_kind_of GraphQL::Query::Arguments, args["b"]
100
102
  assert_instance_of Hash, args["c"]
101
103
  end
102
104
  end
@@ -304,7 +306,7 @@ describe GraphQL::Query::Arguments do
304
306
  assert_equal nil, input_object.arguments_class
305
307
 
306
308
  GraphQL::Query::Arguments.construct_arguments_class(input_object)
307
- args = input_object.arguments_class.instantiate_arguments({foo: 3, bar: -90})
309
+ args = input_object.arguments_class.new({foo: 3, bar: -90})
308
310
 
309
311
  assert_equal 3, args.foo
310
312
  assert_equal -90, args.bar
@@ -49,6 +49,17 @@ describe GraphQL::Relay::BaseConnection do
49
49
  end
50
50
  end
51
51
 
52
+ describe "#inspect" do
53
+ it "inspects nicely" do
54
+ args = {
55
+ first: 1,
56
+ last: -1,
57
+ }
58
+ conn = GraphQL::Relay::BaseConnection.new([], args, context: context)
59
+ assert_equal "#<GraphQL::Relay::Connection @parent=nil @arguments={:first=>1, :last=>-1}>", conn.inspect
60
+ end
61
+ end
62
+
52
63
  describe "#encode / #decode" do
53
64
  module ReverseEncoder
54
65
  module_function
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Relay::Edge do
5
+ it "inspects nicely" do
6
+ connection = OpenStruct.new(parent: "Parent")
7
+ edge = GraphQL::Relay::Edge.new("Node", connection)
8
+ assert_equal '#<GraphQL::Relay::Edge ("Parent" => "Node")>', edge.inspect
9
+ end
10
+ end
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: 1.7.2
4
+ version: 1.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-20 00:00:00.000000000 Z
11
+ date: 2017-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -568,6 +568,7 @@ files:
568
568
  - spec/graphql/introspection/input_value_type_spec.rb
569
569
  - spec/graphql/introspection/introspection_query_spec.rb
570
570
  - spec/graphql/introspection/schema_type_spec.rb
571
+ - spec/graphql/introspection/type_by_name_field_spec.rb
571
572
  - spec/graphql/introspection/type_type_spec.rb
572
573
  - spec/graphql/language/definition_slice_spec.rb
573
574
  - spec/graphql/language/equality_spec.rb
@@ -593,6 +594,7 @@ files:
593
594
  - spec/graphql/relay/connection_instrumentation_spec.rb
594
595
  - spec/graphql/relay/connection_resolve_spec.rb
595
596
  - spec/graphql/relay/connection_type_spec.rb
597
+ - spec/graphql/relay/edge_spec.rb
596
598
  - spec/graphql/relay/mutation_spec.rb
597
599
  - spec/graphql/relay/node_spec.rb
598
600
  - spec/graphql/relay/page_info_spec.rb
@@ -728,6 +730,7 @@ test_files:
728
730
  - spec/graphql/introspection/input_value_type_spec.rb
729
731
  - spec/graphql/introspection/introspection_query_spec.rb
730
732
  - spec/graphql/introspection/schema_type_spec.rb
733
+ - spec/graphql/introspection/type_by_name_field_spec.rb
731
734
  - spec/graphql/introspection/type_type_spec.rb
732
735
  - spec/graphql/language/definition_slice_spec.rb
733
736
  - spec/graphql/language/equality_spec.rb
@@ -753,6 +756,7 @@ test_files:
753
756
  - spec/graphql/relay/connection_instrumentation_spec.rb
754
757
  - spec/graphql/relay/connection_resolve_spec.rb
755
758
  - spec/graphql/relay/connection_type_spec.rb
759
+ - spec/graphql/relay/edge_spec.rb
756
760
  - spec/graphql/relay/mutation_spec.rb
757
761
  - spec/graphql/relay/node_spec.rb
758
762
  - spec/graphql/relay/page_info_spec.rb