graphql 1.8.0.pre1 → 1.8.0.pre2

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/loader_generator.rb +1 -1
  4. data/lib/generators/graphql/mutation_generator.rb +6 -1
  5. data/lib/generators/graphql/templates/function.erb +2 -2
  6. data/lib/generators/graphql/templates/loader.erb +2 -2
  7. data/lib/graphql.rb +1 -0
  8. data/lib/graphql/execution.rb +1 -0
  9. data/lib/graphql/execution/instrumentation.rb +82 -0
  10. data/lib/graphql/execution/multiplex.rb +11 -28
  11. data/lib/graphql/field.rb +5 -0
  12. data/lib/graphql/internal_representation/node.rb +1 -1
  13. data/lib/graphql/language.rb +1 -0
  14. data/lib/graphql/language/document_from_schema_definition.rb +185 -0
  15. data/lib/graphql/language/lexer.rb +3 -3
  16. data/lib/graphql/language/lexer.rl +2 -2
  17. data/lib/graphql/language/token.rb +9 -2
  18. data/lib/graphql/query.rb +4 -0
  19. data/lib/graphql/railtie.rb +83 -0
  20. data/lib/graphql/relay/relation_connection.rb +13 -18
  21. data/lib/graphql/schema.rb +6 -0
  22. data/lib/graphql/schema/argument.rb +1 -1
  23. data/lib/graphql/schema/build_from_definition.rb +2 -0
  24. data/lib/graphql/schema/field.rb +5 -2
  25. data/lib/graphql/schema/input_object.rb +2 -2
  26. data/lib/graphql/schema/member.rb +10 -0
  27. data/lib/graphql/schema/member/build_type.rb +8 -0
  28. data/lib/graphql/schema/member/instrumentation.rb +3 -3
  29. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +6 -4
  30. data/lib/graphql/tracing.rb +1 -0
  31. data/lib/graphql/tracing/data_dog_tracing.rb +45 -0
  32. data/lib/graphql/tracing/platform_tracing.rb +20 -7
  33. data/lib/graphql/upgrader/member.rb +111 -0
  34. data/lib/graphql/upgrader/schema.rb +37 -0
  35. data/lib/graphql/version.rb +1 -1
  36. data/readme.md +1 -1
  37. data/spec/dummy/app/channels/graphql_channel.rb +22 -1
  38. data/spec/dummy/log/development.log +239 -0
  39. data/spec/dummy/log/test.log +204 -0
  40. data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
  41. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  42. data/spec/generators/graphql/function_generator_spec.rb +26 -0
  43. data/spec/generators/graphql/loader_generator_spec.rb +24 -0
  44. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  45. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  46. data/spec/graphql/base_type_spec.rb +12 -0
  47. data/spec/graphql/boolean_type_spec.rb +3 -3
  48. data/spec/graphql/execution/execute_spec.rb +1 -1
  49. data/spec/graphql/execution/instrumentation_spec.rb +165 -0
  50. data/spec/graphql/execution/multiplex_spec.rb +1 -1
  51. data/spec/graphql/float_type_spec.rb +2 -2
  52. data/spec/graphql/id_type_spec.rb +1 -1
  53. data/spec/graphql/input_object_type_spec.rb +2 -2
  54. data/spec/graphql/int_type_spec.rb +2 -2
  55. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  56. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  57. data/spec/graphql/language/document_from_schema_definition_spec.rb +337 -0
  58. data/spec/graphql/language/lexer_spec.rb +12 -1
  59. data/spec/graphql/language/parser_spec.rb +1 -1
  60. data/spec/graphql/query/arguments_spec.rb +3 -3
  61. data/spec/graphql/query/variables_spec.rb +1 -1
  62. data/spec/graphql/query_spec.rb +4 -4
  63. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  64. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  65. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  66. data/spec/graphql/relay/mutation_spec.rb +3 -3
  67. data/spec/graphql/relay/relation_connection_spec.rb +58 -0
  68. data/spec/graphql/schema/build_from_definition_spec.rb +14 -0
  69. data/spec/graphql/schema/field_spec.rb +5 -1
  70. data/spec/graphql/schema/instrumentation_spec.rb +39 -0
  71. data/spec/graphql/schema/validation_spec.rb +1 -1
  72. data/spec/graphql/schema/warden_spec.rb +11 -11
  73. data/spec/graphql/schema_spec.rb +8 -1
  74. data/spec/graphql/string_type_spec.rb +3 -3
  75. data/spec/graphql/subscriptions_spec.rb +1 -1
  76. data/spec/graphql/tracing/platform_tracing_spec.rb +59 -0
  77. data/spec/graphql/upgrader/member_spec.rb +222 -0
  78. data/spec/graphql/upgrader/schema_spec.rb +82 -0
  79. data/spec/support/dummy/schema.rb +19 -0
  80. data/spec/support/jazz.rb +14 -14
  81. data/spec/support/star_wars/data.rb +1 -2
  82. metadata +18 -2
@@ -126,7 +126,7 @@ describe GraphQL::Execution::Multiplex do
126
126
  "before multiplex 1",
127
127
  "before multiplex 2",
128
128
  "before Q1", "before Q2", "before Q3",
129
- "after Q1", "after Q2", "after Q3",
129
+ "after Q3", "after Q2", "after Q1",
130
130
  "after multiplex 2",
131
131
  "after multiplex 1",
132
132
  ], checks
@@ -9,8 +9,8 @@ describe GraphQL::FLOAT_TYPE do
9
9
  end
10
10
 
11
11
  it "rejects other types" do
12
- assert_equal nil, GraphQL::FLOAT_TYPE.coerce_isolated_input("55")
13
- assert_equal nil, GraphQL::FLOAT_TYPE.coerce_isolated_input(true)
12
+ assert_nil GraphQL::FLOAT_TYPE.coerce_isolated_input("55")
13
+ assert_nil GraphQL::FLOAT_TYPE.coerce_isolated_input(true)
14
14
  end
15
15
  end
16
16
  end
@@ -26,7 +26,7 @@ describe GraphQL::ID_TYPE do
26
26
  let(:query_string) { %|query getMilk { cow: milk(id: 1.0) { id } }| }
27
27
 
28
28
  it "doesn't allow other types" do
29
- assert_equal nil, result["data"]
29
+ assert_nil result["data"]
30
30
  assert_equal 1, result["errors"].length
31
31
  end
32
32
  end
@@ -251,7 +251,7 @@ describe GraphQL::InputObjectType do
251
251
  assert_equal 'Test', result['a']
252
252
 
253
253
  assert result.key?('b')
254
- assert_equal nil, result['b']
254
+ assert_nil result['b']
255
255
 
256
256
  assert_equal "Test", result['c']
257
257
  end
@@ -264,7 +264,7 @@ describe GraphQL::InputObjectType do
264
264
  assert_equal 1, result['b']
265
265
 
266
266
  assert result.key?('c')
267
- assert_equal nil, result['c']
267
+ assert_nil result['c']
268
268
  end
269
269
 
270
270
  it "omitted arguments are not returned" do
@@ -9,8 +9,8 @@ describe GraphQL::INT_TYPE do
9
9
  end
10
10
 
11
11
  it "rejects other types" do
12
- assert_equal nil, GraphQL::INT_TYPE.coerce_isolated_input("55")
13
- assert_equal nil, GraphQL::INT_TYPE.coerce_isolated_input(true)
12
+ assert_nil GraphQL::INT_TYPE.coerce_isolated_input("55")
13
+ assert_nil GraphQL::INT_TYPE.coerce_isolated_input(true)
14
14
  end
15
15
  end
16
16
  end
@@ -110,7 +110,7 @@ describe GraphQL::InternalRepresentation::Rewrite do
110
110
 
111
111
  it "groups selections by object types which they apply to" do
112
112
  doc = rewrite_result.operation_definitions["getPlant"]
113
- assert_equal nil, doc.definition
113
+ assert_nil doc.definition
114
114
 
115
115
  plant_scoped_selection = doc.scoped_children[schema.types["Query"]]["plant"]
116
116
  assert_equal ["Fruit", "Nut", "Plant"], plant_scoped_selection.scoped_children.keys.map(&:name).sort
@@ -132,7 +132,7 @@ describe GraphQL::InternalRepresentation::Rewrite do
132
132
 
133
133
  it "tracks parent nodes" do
134
134
  doc = rewrite_result.operation_definitions["getPlant"]
135
- assert_equal nil, doc.parent
135
+ assert_nil doc.parent
136
136
 
137
137
  plant_selection = doc.typed_children[schema.types["Query"]]["plant"]
138
138
  assert_equal doc, plant_selection.parent
@@ -37,6 +37,7 @@ describe GraphQL::Introspection::SchemaType do
37
37
  {"name"=>"milk"},
38
38
  {"name"=>"root"},
39
39
  {"name"=>"searchDairy"},
40
+ {"name"=>"tracingScalar"},
40
41
  {"name"=>"valueWithExecutionError"},
41
42
  ]
42
43
  },
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Language::DocumentFromSchemaDefinition do
5
+ let(:schema_idl) { <<-GRAPHQL
6
+ type QueryType {
7
+ foo: Foo
8
+ }
9
+
10
+ type Foo implements Bar {
11
+ one: Type
12
+ two(argument: InputType!): Type
13
+ three(argument: InputType, other: String): Int
14
+ four(argument: String = "string"): String
15
+ five(argument: [String] = ["string", "string"]): String
16
+ six(argument: String): Type
17
+ }
18
+
19
+ interface Bar {
20
+ one: Type
21
+ four(argument: String = "string"): String
22
+ }
23
+
24
+ type Type {
25
+ a: String
26
+ }
27
+
28
+ input InputType {
29
+ key: String!
30
+ answer: Int = 42
31
+ }
32
+
33
+ type MutationType {
34
+ a(input: InputType): String
35
+ }
36
+
37
+ # Scalar description
38
+ scalar CustomScalar
39
+
40
+ enum Site {
41
+ DESKTOP
42
+ MOBILE
43
+ }
44
+
45
+ union Union = Type | QueryType
46
+
47
+ schema {
48
+ query: QueryType
49
+ mutation: MutationType
50
+ }
51
+ GRAPHQL
52
+ }
53
+
54
+ let(:expected_complete_idl) { <<-GRAPHQL
55
+ # Represents `true` or `false` values.
56
+ scalar Boolean
57
+
58
+ # Represents textual data as UTF-8 character sequences. This type is most often
59
+ # used by GraphQL to represent free-form human-readable text.
60
+ scalar String
61
+
62
+ # The fundamental unit of any GraphQL Schema is the type. There are many kinds of
63
+ # types in GraphQL as represented by the `__TypeKind` enum.
64
+ #
65
+ # Depending on the kind of a type, certain fields describe information about that
66
+ # type. Scalar types provide no information beyond a name and description, while
67
+ # Enum types provide their values. Object and Interface types provide the fields
68
+ # they describe. Abstract types, Union and Interface, provide the Object types
69
+ # possible at runtime. List and NonNull types compose other types.
70
+ type __Type {
71
+ kind: __TypeKind!
72
+ name: String
73
+ description: String
74
+ fields(includeDeprecated: Boolean = false): [__Field!]
75
+ interfaces: [__Type!]
76
+ possibleTypes: [__Type!]
77
+ enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
78
+ inputFields: [__InputValue!]
79
+ ofType: __Type
80
+ }
81
+
82
+ # An enum describing what kind of type a given `__Type` is.
83
+ enum __TypeKind {
84
+ # Indicates this type is a scalar.
85
+ SCALAR
86
+
87
+ # Indicates this type is an object. `fields` and `interfaces` are valid fields.
88
+ OBJECT
89
+
90
+ # Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.
91
+ INTERFACE
92
+
93
+ # Indicates this type is a union. `possibleTypes` is a valid field.
94
+ UNION
95
+
96
+ # Indicates this type is an enum. `enumValues` is a valid field.
97
+ ENUM
98
+
99
+ # Indicates this type is an input object. `inputFields` is a valid field.
100
+ INPUT_OBJECT
101
+
102
+ # Indicates this type is a list. `ofType` is a valid field.
103
+ LIST
104
+
105
+ # Indicates this type is a non-null. `ofType` is a valid field.
106
+ NON_NULL
107
+ }
108
+
109
+ # Object and Interface types are described by a list of Fields, each of which has
110
+ # a name, potentially a list of arguments, and a return type.
111
+ type __Field {
112
+ name: String!
113
+ description: String
114
+ args: [__InputValue!]!
115
+ type: __Type!
116
+ isDeprecated: Boolean!
117
+ deprecationReason: String
118
+ }
119
+
120
+ # Arguments provided to Fields or Directives and the input fields of an
121
+ # InputObject are represented as Input Values which describe their type and
122
+ # optionally a default value.
123
+ type __InputValue {
124
+ name: String!
125
+ description: String
126
+ type: __Type!
127
+
128
+ # A GraphQL-formatted string representing the default value for this input value.
129
+ defaultValue: String
130
+ }
131
+
132
+ # One possible value for a given Enum. Enum values are unique values, not a
133
+ # placeholder for a string or numeric value. However an Enum value is returned in
134
+ # a JSON response as a string.
135
+ type __EnumValue {
136
+ name: String!
137
+ description: String
138
+ isDeprecated: Boolean!
139
+ deprecationReason: String
140
+ }
141
+
142
+ type QueryType {
143
+ foo: Foo
144
+ }
145
+
146
+ type Foo implements Bar {
147
+ one: Type
148
+ two(argument: InputType!): Type
149
+ three(argument: InputType, other: String): Int
150
+ four(argument: String = "string"): String
151
+ five(argument: [String] = ["string", "string"]): String
152
+ six(argument: String): Type
153
+ }
154
+
155
+ interface Bar {
156
+ one: Type
157
+ four(argument: String = "string"): String
158
+ }
159
+
160
+ type Type {
161
+ a: String
162
+ }
163
+
164
+ input InputType {
165
+ key: String!
166
+ answer: Int = 42
167
+ }
168
+
169
+ # Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
170
+ scalar Int
171
+
172
+ type MutationType {
173
+ a(input: InputType): String
174
+ }
175
+
176
+ # A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
177
+ # available types and directives on the server, as well as the entry points for
178
+ # query, mutation, and subscription operations.
179
+ type __Schema {
180
+ # A list of all types supported by this server.
181
+ types: [__Type!]!
182
+
183
+ # The type that query operations will be rooted at.
184
+ queryType: __Type!
185
+
186
+ # If this server supports mutation, the type that mutation operations will be rooted at.
187
+ mutationType: __Type
188
+
189
+ # If this server support subscription, the type that subscription operations will be rooted at.
190
+ subscriptionType: __Type
191
+
192
+ # A list of all directives supported by this server.
193
+ directives: [__Directive!]!
194
+ }
195
+
196
+ # A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
197
+ #
198
+ # In some cases, you need to provide options to alter GraphQL's execution behavior
199
+ # in ways field arguments will not suffice, such as conditionally including or
200
+ # skipping a field. Directives provide this by describing additional information
201
+ # to the executor.
202
+ type __Directive {
203
+ name: String!
204
+ description: String
205
+ locations: [__DirectiveLocation!]!
206
+ args: [__InputValue!]!
207
+ onOperation: Boolean!
208
+ onFragment: Boolean!
209
+ onField: Boolean!
210
+ }
211
+
212
+ # A Directive can be adjacent to many parts of the GraphQL language, a
213
+ # __DirectiveLocation describes one such possible adjacencies.
214
+ enum __DirectiveLocation {
215
+ # Location adjacent to a query operation.
216
+ QUERY
217
+
218
+ # Location adjacent to a mutation operation.
219
+ MUTATION
220
+
221
+ # Location adjacent to a subscription operation.
222
+ SUBSCRIPTION
223
+
224
+ # Location adjacent to a field.
225
+ FIELD
226
+
227
+ # Location adjacent to a fragment definition.
228
+ FRAGMENT_DEFINITION
229
+
230
+ # Location adjacent to a fragment spread.
231
+ FRAGMENT_SPREAD
232
+
233
+ # Location adjacent to an inline fragment.
234
+ INLINE_FRAGMENT
235
+
236
+ # Location adjacent to a schema definition.
237
+ SCHEMA
238
+
239
+ # Location adjacent to a scalar definition.
240
+ SCALAR
241
+
242
+ # Location adjacent to an object type definition.
243
+ OBJECT
244
+
245
+ # Location adjacent to a field definition.
246
+ FIELD_DEFINITION
247
+
248
+ # Location adjacent to an argument definition.
249
+ ARGUMENT_DEFINITION
250
+
251
+ # Location adjacent to an interface definition.
252
+ INTERFACE
253
+
254
+ # Location adjacent to a union definition.
255
+ UNION
256
+
257
+ # Location adjacent to an enum definition.
258
+ ENUM
259
+
260
+ # Location adjacent to an enum value definition.
261
+ ENUM_VALUE
262
+
263
+ # Location adjacent to an input object type definition.
264
+ INPUT_OBJECT
265
+
266
+ # Location adjacent to an input object field definition.
267
+ INPUT_FIELD_DEFINITION
268
+ }
269
+
270
+ # Represents signed double-precision fractional values as specified by [IEEE
271
+ # 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
272
+ scalar Float
273
+
274
+ # Represents a unique identifier that is Base64 obfuscated. It is often used to
275
+ # refetch an object or as key for a cache. The ID type appears in a JSON response
276
+ # as a String; however, it is not intended to be human-readable. When expected as
277
+ # an input type, any string (such as `"VXNlci0xMA=="`) or integer (such as `4`)
278
+ # input value will be accepted as an ID.
279
+ scalar ID
280
+
281
+ # Scalar description
282
+ scalar CustomScalar
283
+
284
+ enum Site {
285
+ DESKTOP
286
+ MOBILE
287
+ }
288
+
289
+ union Union = Type | QueryType
290
+
291
+ directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
292
+
293
+ directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
294
+
295
+ # Marks an element of a GraphQL schema as no longer supported.
296
+ directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE
297
+
298
+ schema {
299
+ query: QueryType
300
+ mutation: MutationType
301
+ }
302
+ GRAPHQL
303
+ }
304
+
305
+ let(:subject) { GraphQL::Language::DocumentFromSchemaDefinition }
306
+
307
+ describe "#document" do
308
+ it "returns the document AST from the given schema" do
309
+ schema = GraphQL::Schema.from_definition(schema_idl)
310
+ document = subject.new(schema).document
311
+
312
+ expected_document = GraphQL.parse(expected_complete_idl)
313
+
314
+ assert equivalent_node?(expected_document, document)
315
+ end
316
+ end
317
+
318
+ private
319
+
320
+ def equivalent_node?(expected, node)
321
+ return false unless expected.is_a?(node.class)
322
+
323
+ if expected.respond_to?(:children) && expected.respond_to?(:scalars)
324
+ children_equal = node.children.all? do |child|
325
+ expected.children.find { |expected_child| equivalent_node?(expected_child, child) }
326
+ end
327
+
328
+ scalars_equal = node.children.all? do |child|
329
+ expected.children.find { |expected_child| equivalent_node?(expected_child, child) }
330
+ end
331
+
332
+ children_equal && scalars_equal
333
+ else
334
+ expected == node
335
+ end
336
+ end
337
+ end
@@ -40,7 +40,18 @@ describe GraphQL::Language::Lexer do
40
40
 
41
41
  it "clears the previous_token between runs" do
42
42
  tok_2 = subject.tokenize(query_string)
43
- assert_equal nil, tok_2[0].prev_token
43
+ assert_nil tok_2[0].prev_token
44
+ end
45
+
46
+ it "counts string position properly" do
47
+ tokens = subject.tokenize('{ a(b: "c")}')
48
+ str_token = tokens[5]
49
+ assert_equal :STRING, str_token.name
50
+ assert_equal "c", str_token.value
51
+ assert_equal 8, str_token.col
52
+ assert_equal '(STRING "c" [1:8])', str_token.inspect
53
+ rparen_token = tokens[6]
54
+ assert_equal '(RPAREN ")" [1:10])', rparen_token.inspect
44
55
  end
45
56
  end
46
57
  end
@@ -16,7 +16,7 @@ describe GraphQL::Language::Parser do
16
16
 
17
17
  it "creates an anonymous fragment definition" do
18
18
  assert fragment.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
19
- assert_equal nil, fragment.name
19
+ assert_nil fragment.name
20
20
  assert_equal 1, fragment.selections.length
21
21
  assert_equal "NestedType", fragment.type.name
22
22
  assert_equal 1, fragment.directives.length