graphql 1.8.0.pre1 → 1.8.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
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