graphql 1.8.0.pre2 → 1.8.0.pre3
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 +4 -4
- data/lib/graphql.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +2 -0
- data/lib/graphql/enum_type.rb +1 -1
- data/lib/graphql/field.rb +10 -1
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/introspection.rb +3 -10
- data/lib/graphql/introspection/base_object.rb +15 -0
- data/lib/graphql/introspection/directive_location_enum.rb +11 -7
- data/lib/graphql/introspection/directive_type.rb +23 -16
- data/lib/graphql/introspection/dynamic_fields.rb +11 -0
- data/lib/graphql/introspection/entry_points.rb +29 -0
- data/lib/graphql/introspection/enum_value_type.rb +16 -11
- data/lib/graphql/introspection/field_type.rb +21 -12
- data/lib/graphql/introspection/input_value_type.rb +26 -23
- data/lib/graphql/introspection/schema_field.rb +7 -2
- data/lib/graphql/introspection/schema_type.rb +36 -22
- data/lib/graphql/introspection/type_by_name_field.rb +10 -2
- data/lib/graphql/introspection/type_kind_enum.rb +10 -6
- data/lib/graphql/introspection/type_type.rb +85 -23
- data/lib/graphql/introspection/typename_field.rb +1 -0
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +129 -37
- data/lib/graphql/language/generation.rb +3 -182
- data/lib/graphql/language/nodes.rb +12 -2
- data/lib/graphql/language/parser.rb +63 -55
- data/lib/graphql/language/parser.y +2 -1
- data/lib/graphql/language/printer.rb +351 -0
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/query/arguments.rb +24 -8
- data/lib/graphql/query/context.rb +3 -0
- data/lib/graphql/query/literal_input.rb +4 -1
- data/lib/graphql/railtie.rb +28 -6
- data/lib/graphql/schema.rb +42 -7
- data/lib/graphql/schema/enum.rb +1 -0
- data/lib/graphql/schema/field.rb +26 -5
- data/lib/graphql/schema/field/dynamic_resolve.rb +18 -9
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/introspection_system.rb +93 -0
- data/lib/graphql/schema/late_bound_type.rb +32 -0
- data/lib/graphql/schema/member.rb +21 -1
- data/lib/graphql/schema/member/build_type.rb +8 -6
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/instrumentation.rb +3 -1
- data/lib/graphql/schema/member/list_type_proxy.rb +4 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +4 -0
- data/lib/graphql/schema/object.rb +2 -1
- data/lib/graphql/schema/printer.rb +33 -266
- data/lib/graphql/schema/traversal.rb +74 -6
- data/lib/graphql/schema/validation.rb +3 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/upgrader/member.rb +463 -63
- data/lib/graphql/version.rb +1 -1
- data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
- data/spec/fixtures/upgrader/blame_range.transformed.rb +31 -0
- data/spec/fixtures/upgrader/subscribable.original.rb +51 -0
- data/spec/fixtures/upgrader/subscribable.transformed.rb +46 -0
- data/spec/fixtures/upgrader/type_x.original.rb +35 -0
- data/spec/fixtures/upgrader/type_x.transformed.rb +35 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +729 -296
- data/spec/graphql/language/generation_spec.rb +21 -186
- data/spec/graphql/language/nodes_spec.rb +21 -0
- data/spec/graphql/language/printer_spec.rb +203 -0
- data/spec/graphql/query/arguments_spec.rb +14 -4
- data/spec/graphql/query/context_spec.rb +17 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +13 -4
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/introspection_system_spec.rb +39 -0
- data/spec/graphql/schema/object_spec.rb +12 -1
- data/spec/graphql/schema/printer_spec.rb +14 -14
- data/spec/graphql/tracing/platform_tracing_spec.rb +2 -2
- data/spec/graphql/upgrader/member_spec.rb +274 -62
- data/spec/support/jazz.rb +75 -3
- metadata +38 -9
- data/lib/graphql/introspection/arguments_field.rb +0 -7
- data/lib/graphql/introspection/enum_values_field.rb +0 -18
- data/lib/graphql/introspection/fields_field.rb +0 -13
- data/lib/graphql/introspection/input_fields_field.rb +0 -12
- data/lib/graphql/introspection/interfaces_field.rb +0 -11
- data/lib/graphql/introspection/of_type_field.rb +0 -6
- data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -19,7 +19,7 @@ describe GraphQL::Query::Arguments do
|
|
19
19
|
GraphQL::Query::Arguments.construct_arguments_class(test_input_1)
|
20
20
|
GraphQL::Query::Arguments.construct_arguments_class(test_input_2)
|
21
21
|
arg_values = {a: 1, b: 2, c: { d: 3, e: 4 }}
|
22
|
-
test_input_2.arguments_class.new(arg_values, context: nil)
|
22
|
+
test_input_2.arguments_class.new(arg_values, context: nil, defaults_used: Set.new)
|
23
23
|
}
|
24
24
|
|
25
25
|
it "returns keys as strings, with aliases" do
|
@@ -73,7 +73,7 @@ describe GraphQL::Query::Arguments do
|
|
73
73
|
self.argument_definitions = types
|
74
74
|
end
|
75
75
|
|
76
|
-
new_arguments = args_class.new(transformed_args, context: nil)
|
76
|
+
new_arguments = args_class.new(transformed_args, context: nil, defaults_used: Set.new)
|
77
77
|
expected_hash = {
|
78
78
|
"A" => 1,
|
79
79
|
"B" => 2,
|
@@ -96,7 +96,8 @@ describe GraphQL::Query::Arguments do
|
|
96
96
|
it "wraps input objects, but not other hashes" do
|
97
97
|
args = input_type.arguments_class.new(
|
98
98
|
{a: 1, b: {a: 2}, c: {a: 3}},
|
99
|
-
|
99
|
+
defaults_used: Set.new,
|
100
|
+
context: nil,
|
100
101
|
)
|
101
102
|
assert_kind_of GraphQL::Query::Arguments, args["b"]
|
102
103
|
assert_instance_of Hash, args["c"]
|
@@ -198,6 +199,15 @@ describe GraphQL::Query::Arguments do
|
|
198
199
|
assert_equal({"a" => 1, "b" => 2}, last_args.to_h)
|
199
200
|
end
|
200
201
|
|
202
|
+
it "indicates when default argument values were applied" do
|
203
|
+
schema.execute("{ argTest(a: 1) }")
|
204
|
+
|
205
|
+
last_args = arg_values.last
|
206
|
+
|
207
|
+
assert_equal false, last_args.default_used?('a')
|
208
|
+
assert_equal true, last_args.default_used?('b')
|
209
|
+
end
|
210
|
+
|
201
211
|
it "works from variables" do
|
202
212
|
variables = { "arg" => { "a" => 1, "d" => nil } }
|
203
213
|
schema.execute("query ArgTest($arg: TestInput){ argTest(d: $arg) }", variables: variables)
|
@@ -306,7 +316,7 @@ describe GraphQL::Query::Arguments do
|
|
306
316
|
assert_nil input_object.arguments_class
|
307
317
|
|
308
318
|
GraphQL::Query::Arguments.construct_arguments_class(input_object)
|
309
|
-
args = input_object.arguments_class.new({foo: 3, bar: -90}, context: nil)
|
319
|
+
args = input_object.arguments_class.new({foo: 3, bar: -90}, defaults_used: Set.new, context: nil)
|
310
320
|
|
311
321
|
assert_equal 3, args.foo
|
312
322
|
assert_equal -90, args.bar
|
@@ -243,4 +243,21 @@ TABLE
|
|
243
243
|
assert_equal [expected_err], result["errors"]
|
244
244
|
end
|
245
245
|
end
|
246
|
+
|
247
|
+
describe "custom context class" do
|
248
|
+
it "can be specified" do
|
249
|
+
query_str = '{
|
250
|
+
inspectContext
|
251
|
+
find(id: "Musician/Herbie Hancock") {
|
252
|
+
... on Musician {
|
253
|
+
inspectContext
|
254
|
+
}
|
255
|
+
}
|
256
|
+
}'
|
257
|
+
res = Jazz::Schema.execute(query_str, context: { magic_key: :ignored, normal_key: "normal_value" })
|
258
|
+
expected_values = ["custom_method", "magic_value", "normal_value"]
|
259
|
+
assert_equal expected_values, res["data"]["inspectContext"]
|
260
|
+
assert_equal expected_values, res["data"]["find"]["inspectContext"]
|
261
|
+
end
|
262
|
+
end
|
246
263
|
end
|
@@ -308,7 +308,7 @@ schema {
|
|
308
308
|
}
|
309
309
|
|
310
310
|
type Hello {
|
311
|
-
str(
|
311
|
+
str(bool: Boolean, int: Int): String
|
312
312
|
}
|
313
313
|
SCHEMA
|
314
314
|
|
@@ -505,7 +505,7 @@ type HelloScalars {
|
|
505
505
|
}
|
506
506
|
|
507
507
|
type Mutation {
|
508
|
-
addHelloScalars(
|
508
|
+
addHelloScalars(bool: Boolean, int: Int, str: String): HelloScalars
|
509
509
|
}
|
510
510
|
SCHEMA
|
511
511
|
|
@@ -520,7 +520,7 @@ enum Color {
|
|
520
520
|
}
|
521
521
|
|
522
522
|
type Mutation {
|
523
|
-
hello(
|
523
|
+
hello(color: Color = RED, int: Int, nullDefault: Int = null, str: String): String
|
524
524
|
}
|
525
525
|
|
526
526
|
type Query {
|
@@ -545,7 +545,7 @@ type HelloScalars {
|
|
545
545
|
}
|
546
546
|
|
547
547
|
type Subscription {
|
548
|
-
subscribeHelloScalars(
|
548
|
+
subscribeHelloScalars(bool: Boolean, int: Int, str: String): HelloScalars
|
549
549
|
}
|
550
550
|
SCHEMA
|
551
551
|
|
@@ -603,6 +603,15 @@ type Query {
|
|
603
603
|
|
604
604
|
build_schema_and_compare_output(schema.chop)
|
605
605
|
end
|
606
|
+
|
607
|
+
it 'supports empty types' do
|
608
|
+
schema = <<-SCHEMA
|
609
|
+
type Query {
|
610
|
+
}
|
611
|
+
SCHEMA
|
612
|
+
|
613
|
+
build_schema_and_compare_output(schema.chop)
|
614
|
+
end
|
606
615
|
end
|
607
616
|
|
608
617
|
describe 'Failures' do
|
@@ -14,5 +14,19 @@ describe GraphQL::Schema::Field do
|
|
14
14
|
it "camelizes the field name" do
|
15
15
|
assert_equal 'inspectInput', field.graphql_definition.name
|
16
16
|
end
|
17
|
+
|
18
|
+
describe "description in block" do
|
19
|
+
it "will raise if description is defined both in the argument and in the block" do
|
20
|
+
assert_raises RuntimeError, "You're overriding the description of shouldRaise in the provided block!" do
|
21
|
+
Class.new(Jazz::BaseObject) do
|
22
|
+
graphql_name "JustAName"
|
23
|
+
|
24
|
+
field :should_raise, Jazz::Key, "this should not raise", null: true do
|
25
|
+
description "This should raise"
|
26
|
+
end
|
27
|
+
end.to_graphql
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe GraphQL::Schema::IntrospectionSystem do
|
5
|
+
describe "custom introspection" do
|
6
|
+
it "serves custom fields on types" do
|
7
|
+
res = Jazz::Schema.execute("{ __schema { isJazzy } }")
|
8
|
+
assert_equal true, res["data"]["__schema"]["isJazzy"]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "serves overridden fields on types" do
|
12
|
+
res = Jazz::Schema.execute(%|{ __type(name: "Ensemble") { name } }|)
|
13
|
+
assert_equal "ENSEMBLE", res["data"]["__type"]["name"]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "serves custom entry points" do
|
17
|
+
res = Jazz::Schema.execute("{ __classname }", root_value: Set.new)
|
18
|
+
assert_equal "Set", res["data"]["__classname"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "serves custom dynamic fields" do
|
22
|
+
res = Jazz::Schema.execute("{ nowPlaying { __typename __typenameLength __astNodeClass } }")
|
23
|
+
assert_equal "Ensemble", res["data"]["nowPlaying"]["__typename"]
|
24
|
+
assert_equal 8, res["data"]["nowPlaying"]["__typenameLength"]
|
25
|
+
assert_equal "GraphQL::Language::Nodes::Field", res["data"]["nowPlaying"]["__astNodeClass"]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "doesn't affect other schemas" do
|
29
|
+
res = Dummy::Schema.execute("{ __schema { isJazzy } }")
|
30
|
+
assert_equal 1, res["errors"].length
|
31
|
+
|
32
|
+
res = Dummy::Schema.execute("{ __classname }", root_value: Set.new)
|
33
|
+
assert_equal 1, res["errors"].length
|
34
|
+
|
35
|
+
res = Dummy::Schema.execute("{ ensembles { __typenameLength } }")
|
36
|
+
assert_equal 1, res["errors"].length
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -16,7 +16,7 @@ describe GraphQL::Schema::Object do
|
|
16
16
|
it "inherits fields and interfaces" do
|
17
17
|
new_object_class = Class.new(object_class) do
|
18
18
|
field :newField, String, null: true
|
19
|
-
field :name, String, "The new description", null: true
|
19
|
+
field :name, String, description: "The new description", null: true
|
20
20
|
end
|
21
21
|
|
22
22
|
# one more than the parent class
|
@@ -29,6 +29,17 @@ describe GraphQL::Schema::Object do
|
|
29
29
|
name_field = new_object_class.fields.find { |f| f.name == "name" }
|
30
30
|
assert_equal "The new description", name_field.description
|
31
31
|
end
|
32
|
+
|
33
|
+
it "inherits name and description" do
|
34
|
+
# Manually assign a name since `.name` isn't populated for dynamic classes
|
35
|
+
new_subclass_1 = Class.new(object_class) do
|
36
|
+
graphql_name "NewSubclass"
|
37
|
+
end
|
38
|
+
new_subclass_2 = Class.new(new_subclass_1)
|
39
|
+
assert_equal "NewSubclass", new_subclass_1.graphql_name
|
40
|
+
assert_equal "NewSubclass", new_subclass_2.graphql_name
|
41
|
+
assert_equal object_class.description, new_subclass_2.description
|
42
|
+
end
|
32
43
|
end
|
33
44
|
|
34
45
|
describe ".to_graphql_type" do
|
@@ -136,6 +136,14 @@ schema {
|
|
136
136
|
query: Root
|
137
137
|
}
|
138
138
|
|
139
|
+
# Marks an element of a GraphQL schema as no longer supported.
|
140
|
+
directive @deprecated(
|
141
|
+
# Explains why this element was deprecated, usually also including a suggestion
|
142
|
+
# for how to access supported similar data. Formatted in
|
143
|
+
# [Markdown](https://daringfireball.net/projects/markdown/).
|
144
|
+
reason: String = "No longer supported"
|
145
|
+
) on FIELD_DEFINITION | ENUM_VALUE
|
146
|
+
|
139
147
|
# Directs the executor to include this field or fragment only when the `if` argument is true.
|
140
148
|
directive @include(
|
141
149
|
# Included when true.
|
@@ -148,14 +156,6 @@ directive @skip(
|
|
148
156
|
if: Boolean!
|
149
157
|
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
150
158
|
|
151
|
-
# Marks an element of a GraphQL schema as no longer supported.
|
152
|
-
directive @deprecated(
|
153
|
-
# Explains why this element was deprecated, usually also including a suggestion
|
154
|
-
# for how to access supported similar data. Formatted in
|
155
|
-
# [Markdown](https://daringfireball.net/projects/markdown/).
|
156
|
-
reason: String = "No longer supported"
|
157
|
-
) on FIELD_DEFINITION | ENUM_VALUE
|
158
|
-
|
159
159
|
# A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
|
160
160
|
#
|
161
161
|
# In some cases, you need to provide options to alter GraphQL's execution behavior
|
@@ -345,7 +345,6 @@ schema {
|
|
345
345
|
subscription: Subscription
|
346
346
|
}
|
347
347
|
SCHEMA
|
348
|
-
|
349
348
|
assert_match expected, GraphQL::Schema::Printer.print_schema(custom_schema)
|
350
349
|
end
|
351
350
|
|
@@ -390,7 +389,7 @@ type Audio {
|
|
390
389
|
|
391
390
|
enum Choice {
|
392
391
|
BAR
|
393
|
-
BAZ @deprecated(reason: "Use
|
392
|
+
BAZ @deprecated(reason: "Use "BAR".")
|
394
393
|
FOO
|
395
394
|
WOZ @deprecated
|
396
395
|
}
|
@@ -439,7 +438,7 @@ interface Node {
|
|
439
438
|
type Post {
|
440
439
|
body: String!
|
441
440
|
comments: [Comment!]
|
442
|
-
comments_count: Int! @deprecated(reason: "Use
|
441
|
+
comments_count: Int! @deprecated(reason: "Use "comments".")
|
443
442
|
id: ID!
|
444
443
|
title: String!
|
445
444
|
}
|
@@ -489,7 +488,6 @@ enum Choice {
|
|
489
488
|
}
|
490
489
|
|
491
490
|
type Subscription {
|
492
|
-
|
493
491
|
}
|
494
492
|
|
495
493
|
input Varied {
|
@@ -509,7 +507,9 @@ SCHEMA
|
|
509
507
|
when GraphQL::Argument
|
510
508
|
member.name != "id"
|
511
509
|
else
|
512
|
-
member.deprecation_reason
|
510
|
+
if member.respond_to?(:deprecation_reason)
|
511
|
+
member.deprecation_reason.nil?
|
512
|
+
end
|
513
513
|
end
|
514
514
|
}
|
515
515
|
|
@@ -600,7 +600,7 @@ SCHEMA
|
|
600
600
|
type Post {
|
601
601
|
body: String!
|
602
602
|
comments: [Comment!]
|
603
|
-
comments_count: Int! @deprecated(reason:
|
603
|
+
comments_count: Int! @deprecated(reason: "Use "comments".")
|
604
604
|
id: ID!
|
605
605
|
title: String!
|
606
606
|
}
|
@@ -69,10 +69,10 @@ describe GraphQL::Tracing::PlatformTracing do
|
|
69
69
|
schema.execute(" { tracingScalar { traceNil traceFalse traceTrue } }")
|
70
70
|
expected_trace = [
|
71
71
|
"em",
|
72
|
-
"am",
|
73
72
|
"l",
|
74
73
|
"p",
|
75
74
|
"v",
|
75
|
+
"am",
|
76
76
|
"aq",
|
77
77
|
"eq",
|
78
78
|
"Q.t",
|
@@ -98,10 +98,10 @@ describe GraphQL::Tracing::PlatformTracing do
|
|
98
98
|
schema.execute(" { tracingScalar { traceNil traceFalse traceTrue } }")
|
99
99
|
expected_trace = [
|
100
100
|
"em",
|
101
|
-
"am",
|
102
101
|
"l",
|
103
102
|
"p",
|
104
103
|
"v",
|
104
|
+
"am",
|
105
105
|
"aq",
|
106
106
|
"eq",
|
107
107
|
"Q.t",
|
@@ -11,17 +11,23 @@ describe GraphQL::Upgrader::Member do
|
|
11
11
|
describe 'field arguments' do
|
12
12
|
it 'upgrades' do
|
13
13
|
old = %{argument :status, !TodoStatus, "Restrict items to this status"}
|
14
|
-
new = %{argument :status, TodoStatus, "Restrict items to this status",
|
14
|
+
new = %{argument :status, TodoStatus, "Restrict items to this status", required: true}
|
15
15
|
|
16
|
-
assert_equal upgrade(old)
|
16
|
+
assert_equal new, upgrade(old)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'upgrades the property definition to method' do
|
21
21
|
old = %{field :name, String, property: :name}
|
22
|
-
new = %{field :name, String, method: :name, null:
|
22
|
+
new = %{field :name, String, method: :name, null: true}
|
23
23
|
|
24
|
-
assert_equal upgrade(old)
|
24
|
+
assert_equal new, upgrade(old)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'upgrades the property definition in a block to method' do
|
28
|
+
old = %{field :name, String do\n property :name\nend}
|
29
|
+
new = %{field :name, String, method: :name, null: true}
|
30
|
+
assert_equal new, upgrade(old)
|
25
31
|
end
|
26
32
|
|
27
33
|
describe 'name' do
|
@@ -32,10 +38,23 @@ describe GraphQL::Upgrader::Member do
|
|
32
38
|
end
|
33
39
|
}
|
34
40
|
new = %{
|
35
|
-
class UserType < BaseObject
|
41
|
+
class UserType < Types::BaseObject
|
42
|
+
end
|
43
|
+
}
|
44
|
+
assert_equal new, upgrade(old)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'removes the name field if it can be inferred from the class and under a module' do
|
48
|
+
old = %{
|
49
|
+
Types::UserType = GraphQL::ObjectType.define do
|
50
|
+
name "User"
|
51
|
+
end
|
52
|
+
}
|
53
|
+
new = %{
|
54
|
+
class Types::UserType < Types::BaseObject
|
36
55
|
end
|
37
56
|
}
|
38
|
-
assert_equal upgrade(old)
|
57
|
+
assert_equal new, upgrade(old)
|
39
58
|
end
|
40
59
|
|
41
60
|
it 'upgrades the name into graphql_name if it can\'t be inferred from the class' do
|
@@ -45,11 +64,11 @@ describe GraphQL::Upgrader::Member do
|
|
45
64
|
end
|
46
65
|
}
|
47
66
|
new = %{
|
48
|
-
class TeamType < BaseObject
|
67
|
+
class TeamType < Types::BaseObject
|
49
68
|
graphql_name "User"
|
50
69
|
end
|
51
70
|
}
|
52
|
-
assert_equal upgrade(old)
|
71
|
+
assert_equal new, upgrade(old)
|
53
72
|
|
54
73
|
old = %{
|
55
74
|
UserInterface = GraphQL::InterfaceType.define do
|
@@ -57,111 +76,211 @@ describe GraphQL::Upgrader::Member do
|
|
57
76
|
end
|
58
77
|
}
|
59
78
|
new = %{
|
60
|
-
class UserInterface < BaseInterface
|
79
|
+
class UserInterface < Types::BaseInterface
|
61
80
|
graphql_name "User"
|
62
81
|
end
|
63
82
|
}
|
64
|
-
assert_equal upgrade(old)
|
83
|
+
assert_equal new, upgrade(old)
|
65
84
|
|
66
85
|
old = %{
|
67
|
-
|
86
|
+
UserEnum = GraphQL::EnumType.define do
|
68
87
|
name "User"
|
69
88
|
end
|
70
89
|
}
|
71
90
|
new = %{
|
72
|
-
class
|
91
|
+
class UserEnum < Types::BaseEnum
|
73
92
|
graphql_name "User"
|
74
93
|
end
|
75
94
|
}
|
76
|
-
assert_equal upgrade(old)
|
95
|
+
assert_equal new, upgrade(old)
|
77
96
|
end
|
78
97
|
end
|
79
98
|
|
80
99
|
describe 'definition' do
|
81
100
|
it 'upgrades the .define into class based definition' do
|
82
|
-
old = %{UserType = GraphQL::ObjectType.define do
|
83
|
-
|
84
|
-
|
101
|
+
old = %{UserType = GraphQL::ObjectType.define do
|
102
|
+
end}
|
103
|
+
new = %{class UserType < Types::BaseObject
|
104
|
+
end}
|
105
|
+
assert_equal new, upgrade(old)
|
106
|
+
|
107
|
+
old = %{UserInterface = GraphQL::InterfaceType.define do
|
108
|
+
end}
|
109
|
+
new = %{class UserInterface < Types::BaseInterface
|
110
|
+
end}
|
111
|
+
assert_equal new, upgrade(old)
|
112
|
+
|
113
|
+
old = %{UserUnion = GraphQL::UnionType.define do
|
114
|
+
end}
|
115
|
+
new = %{class UserUnion < Types::BaseUnion
|
116
|
+
end}
|
117
|
+
assert_equal new, upgrade(old)
|
85
118
|
|
86
|
-
old = %{
|
87
|
-
|
88
|
-
|
119
|
+
old = %{UserEnum = GraphQL::EnumType.define do
|
120
|
+
end}
|
121
|
+
new = %{class UserEnum < Types::BaseEnum
|
122
|
+
end}
|
123
|
+
assert_equal new, upgrade(old)
|
89
124
|
|
90
|
-
old = %{
|
91
|
-
|
92
|
-
|
125
|
+
old = %{UserInput = GraphQL::InputObjectType.define do
|
126
|
+
end}
|
127
|
+
new = %{class UserInput < Types::BaseInputObject
|
128
|
+
end}
|
129
|
+
assert_equal new, upgrade(old)
|
93
130
|
|
94
|
-
old = %{
|
95
|
-
|
96
|
-
|
131
|
+
old = %{UserScalar = GraphQL::ScalarType.define do
|
132
|
+
end}
|
133
|
+
new = %{class UserScalar < Types::BaseScalar
|
134
|
+
end}
|
135
|
+
assert_equal new, upgrade(old)
|
97
136
|
end
|
98
137
|
|
99
138
|
it 'upgrades including the module' do
|
100
|
-
old = %{Module::UserType = GraphQL::ObjectType.define do
|
101
|
-
|
102
|
-
|
139
|
+
old = %{Module::UserType = GraphQL::ObjectType.define do
|
140
|
+
end}
|
141
|
+
new = %{class Module::UserType < Types::BaseObject
|
142
|
+
end}
|
143
|
+
assert_equal new, upgrade(old)
|
103
144
|
end
|
104
145
|
end
|
105
146
|
|
106
147
|
describe 'fields' do
|
148
|
+
it 'underscorizes field name' do
|
149
|
+
old = %{field :firstName, !types.String}
|
150
|
+
new = %{field :first_name, String, null: false}
|
151
|
+
assert_equal new, upgrade(old)
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "resolve proc to method" do
|
155
|
+
it "converts @object and @context" do
|
156
|
+
old = %{
|
157
|
+
field :firstName, !types.String do
|
158
|
+
resolve ->(obj, arg, ctx) {
|
159
|
+
ctx.something
|
160
|
+
other_ctx # test combined identifiers
|
161
|
+
|
162
|
+
obj[ctx] + obj
|
163
|
+
obj.given_name
|
164
|
+
}
|
165
|
+
end
|
166
|
+
}
|
167
|
+
new = %{
|
168
|
+
field :first_name, String, null: false
|
169
|
+
|
170
|
+
def first_name
|
171
|
+
@context.something
|
172
|
+
other_ctx # test combined identifiers
|
173
|
+
|
174
|
+
@object[@context] + @object
|
175
|
+
@object.given_name
|
176
|
+
end
|
177
|
+
}
|
178
|
+
assert_equal new, upgrade(old)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "handles `_` var names" do
|
182
|
+
old = %{
|
183
|
+
field :firstName, !types.String do
|
184
|
+
resolve ->(obj, _, _) {
|
185
|
+
obj.given_name
|
186
|
+
}
|
187
|
+
end
|
188
|
+
}
|
189
|
+
new = %{
|
190
|
+
field :first_name, String, null: false
|
191
|
+
|
192
|
+
def first_name
|
193
|
+
@object.given_name
|
194
|
+
end
|
195
|
+
}
|
196
|
+
assert_equal new, upgrade(old)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "creates **arguments if necessary" do
|
200
|
+
old = %{
|
201
|
+
field :firstName, !types.String do
|
202
|
+
argument :ctx, types.String, default_value: "abc"
|
203
|
+
resolve ->(obj, args, ctx) {
|
204
|
+
args[:ctx]
|
205
|
+
}
|
206
|
+
end
|
207
|
+
}
|
208
|
+
new = %{
|
209
|
+
field :first_name, String, null: false do
|
210
|
+
argument :ctx, String, default_value: "abc", required: false
|
211
|
+
end
|
212
|
+
|
213
|
+
def first_name(**args)
|
214
|
+
args[:ctx]
|
215
|
+
end
|
216
|
+
}
|
217
|
+
assert_equal new, upgrade(old)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
107
222
|
it 'upgrades to the new definition' do
|
108
223
|
old = %{field :name, !types.String}
|
109
224
|
new = %{field :name, String, null: false}
|
110
|
-
assert_equal upgrade(old)
|
225
|
+
assert_equal new, upgrade(old)
|
111
226
|
|
112
227
|
old = %{field :name, !types.String, "description", method: :name}
|
113
228
|
new = %{field :name, String, "description", method: :name, null: false}
|
114
|
-
assert_equal upgrade(old)
|
229
|
+
assert_equal new, upgrade(old)
|
115
230
|
|
116
231
|
old = %{field :name, -> { !types.String }}
|
117
|
-
new = %{field :name,
|
118
|
-
assert_equal upgrade(old)
|
232
|
+
new = %{field :name, String, null: false}
|
233
|
+
assert_equal new, upgrade(old)
|
119
234
|
|
120
235
|
old = %{connection :name, Name.connection_type, "names"}
|
121
|
-
new = %{field :name, Name.connection_type, "names", null:
|
122
|
-
assert_equal upgrade(old)
|
236
|
+
new = %{field :name, Name.connection_type, "names", null: true, connection: true}
|
237
|
+
assert_equal new, upgrade(old)
|
123
238
|
|
124
239
|
old = %{connection :name, !Name.connection_type, "names"}
|
125
240
|
new = %{field :name, Name.connection_type, "names", null: false, connection: true}
|
126
|
-
assert_equal upgrade(old)
|
241
|
+
assert_equal new, upgrade(old)
|
127
242
|
|
128
243
|
old = %{field :names, types[types.String]}
|
129
|
-
new = %{field :names, [String], null:
|
130
|
-
assert_equal upgrade(old)
|
244
|
+
new = %{field :names, [String], null: true}
|
245
|
+
assert_equal new, upgrade(old)
|
131
246
|
|
132
247
|
old = %{field :names, !types[types.String]}
|
133
248
|
new = %{field :names, [String], null: false}
|
134
|
-
assert_equal upgrade(old)
|
249
|
+
assert_equal new, upgrade(old)
|
135
250
|
|
136
251
|
old = %{
|
137
252
|
field :name, types.String do
|
138
253
|
end
|
139
254
|
}
|
140
255
|
new = %{
|
141
|
-
field :name, String, null:
|
142
|
-
end
|
256
|
+
field :name, String, null: true
|
143
257
|
}
|
144
|
-
assert_equal upgrade(old)
|
258
|
+
assert_equal new, upgrade(old)
|
145
259
|
|
146
260
|
old = %{
|
147
261
|
field :name, !types.String do
|
262
|
+
description "abc"
|
263
|
+
end
|
264
|
+
|
265
|
+
field :name2, !types.Int do
|
266
|
+
description "def"
|
148
267
|
end
|
149
268
|
}
|
150
269
|
new = %{
|
151
|
-
field :name, String, null: false
|
152
|
-
|
270
|
+
field :name, String, description: "abc", null: false
|
271
|
+
|
272
|
+
field :name2, Integer, description: "def", null: false
|
153
273
|
}
|
154
|
-
assert_equal upgrade(old)
|
274
|
+
assert_equal new, upgrade(old)
|
155
275
|
|
156
276
|
old = %{
|
157
277
|
field :name, -> { !types.String } do
|
158
278
|
end
|
159
279
|
}
|
160
280
|
new = %{
|
161
|
-
field :name,
|
162
|
-
end
|
281
|
+
field :name, String, null: false
|
163
282
|
}
|
164
|
-
assert_equal upgrade(old)
|
283
|
+
assert_equal new, upgrade(old)
|
165
284
|
|
166
285
|
old = %{
|
167
286
|
field :name do
|
@@ -169,21 +288,25 @@ describe GraphQL::Upgrader::Member do
|
|
169
288
|
end
|
170
289
|
}
|
171
290
|
new = %{
|
172
|
-
field :name,
|
173
|
-
end
|
291
|
+
field :name, String, null: true
|
174
292
|
}
|
175
|
-
assert_equal upgrade(old)
|
293
|
+
assert_equal new, upgrade(old)
|
176
294
|
|
177
295
|
old = %{
|
178
296
|
field :name do
|
179
297
|
type !String
|
180
298
|
end
|
299
|
+
|
300
|
+
field :name2 do
|
301
|
+
type !String
|
302
|
+
end
|
181
303
|
}
|
182
304
|
new = %{
|
183
|
-
field :name, String, null: false
|
184
|
-
|
305
|
+
field :name, String, null: false
|
306
|
+
|
307
|
+
field :name2, String, null: false
|
185
308
|
}
|
186
|
-
assert_equal upgrade(old)
|
309
|
+
assert_equal new, upgrade(old)
|
187
310
|
|
188
311
|
old = %{
|
189
312
|
field :name, -> { types.String },
|
@@ -191,10 +314,9 @@ describe GraphQL::Upgrader::Member do
|
|
191
314
|
end
|
192
315
|
}
|
193
316
|
new = %{
|
194
|
-
field :name,
|
195
|
-
end
|
317
|
+
field :name, String, "newline description", null: true
|
196
318
|
}
|
197
|
-
assert_equal upgrade(old)
|
319
|
+
assert_equal new, upgrade(old)
|
198
320
|
|
199
321
|
old = %{
|
200
322
|
field :name, -> { !types.String },
|
@@ -202,10 +324,9 @@ describe GraphQL::Upgrader::Member do
|
|
202
324
|
end
|
203
325
|
}
|
204
326
|
new = %{
|
205
|
-
field :name,
|
206
|
-
end
|
327
|
+
field :name, String, "newline description", null: false
|
207
328
|
}
|
208
|
-
assert_equal upgrade(old)
|
329
|
+
assert_equal new, upgrade(old)
|
209
330
|
|
210
331
|
old = %{
|
211
332
|
field :name, String,
|
@@ -213,10 +334,101 @@ describe GraphQL::Upgrader::Member do
|
|
213
334
|
end
|
214
335
|
}
|
215
336
|
new = %{
|
216
|
-
field :name, String, field: SomeField, null:
|
217
|
-
|
337
|
+
field :name, String, field: SomeField, null: true
|
338
|
+
}
|
339
|
+
assert_equal new, upgrade(old)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
describe 'multi-line field with property/method' do
|
344
|
+
it 'upgrades without breaking syntax' do
|
345
|
+
old = %{
|
346
|
+
field :is_example_field, types.Boolean,
|
347
|
+
property: :example_field?
|
348
|
+
}
|
349
|
+
new = %{
|
350
|
+
field :is_example_field, Boolean, null: true
|
351
|
+
method: :example_field?
|
352
|
+
}
|
353
|
+
|
354
|
+
assert_equal new, upgrade(old)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
describe 'multi-line connection with property/method' do
|
359
|
+
it 'upgrades without breaking syntax' do
|
360
|
+
old = %{
|
361
|
+
connection :example_connection, -> { ExampleConnectionType },
|
362
|
+
property: :example_connections
|
363
|
+
}
|
364
|
+
new = %{
|
365
|
+
field :example_connection, ExampleConnectionType, null: true, connection: true
|
366
|
+
method: :example_connections
|
367
|
+
}
|
368
|
+
|
369
|
+
assert_equal new, upgrade(old)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe 'input_field' do
|
374
|
+
it 'upgrades to argument' do
|
375
|
+
old = %{input_field :id, !types.ID}
|
376
|
+
new = %{argument :id, ID, required: true}
|
377
|
+
assert_equal new, upgrade(old)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
describe 'implements' do
|
382
|
+
it 'upgrades interfaces to implements' do
|
383
|
+
old = %{
|
384
|
+
interfaces [Types::SearchableType, Types::CommentableType]
|
385
|
+
interfaces [Types::ShareableType]
|
386
|
+
}
|
387
|
+
new = %{
|
388
|
+
implements Types::SearchableType
|
389
|
+
implements Types::CommentableType
|
390
|
+
implements Types::ShareableType
|
391
|
+
}
|
392
|
+
assert_equal new, upgrade(old)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
describe "fixtures" do
|
397
|
+
class ActiveRecordTypeToClassTransform < GraphQL::Upgrader::Transform
|
398
|
+
def initialize
|
399
|
+
@find_pattern = /^( +)([a-zA-Z_0-9:]*) = define_active_record_type\(-> ?\{ ?:{0,2}([a-zA-Z_0-9:]*) ?\} ?\) do/
|
400
|
+
@replace_pattern = "\\1class \\2 < Platform::Objects::Base\n\\1 model_name \"\\3\""
|
401
|
+
end
|
402
|
+
|
403
|
+
def apply(input_text)
|
404
|
+
input_text.sub(@find_pattern, @replace_pattern)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def custom_upgrade(original_text)
|
409
|
+
# Replace the default one with a custom one:
|
410
|
+
type_transforms = GraphQL::Upgrader::Member::DEFAULT_TYPE_TRANSFORMS.map { |t|
|
411
|
+
if t == GraphQL::Upgrader::TypeDefineToClassTransform
|
412
|
+
GraphQL::Upgrader::TypeDefineToClassTransform.new(base_class_pattern: "Platform::\\2s::Base")
|
413
|
+
else
|
414
|
+
t
|
415
|
+
end
|
218
416
|
}
|
219
|
-
|
417
|
+
|
418
|
+
type_transforms.unshift(ActiveRecordTypeToClassTransform)
|
419
|
+
upgrader = GraphQL::Upgrader::Member.new(original_text, type_transforms: type_transforms)
|
420
|
+
upgrader.upgrade
|
421
|
+
end
|
422
|
+
|
423
|
+
original_files = Dir.glob("spec/fixtures/upgrader/*.original.rb")
|
424
|
+
original_files.each do |original_file|
|
425
|
+
transformed_file = original_file.sub(".original.", ".transformed.")
|
426
|
+
it "transforms #{original_file} -> #{transformed_file}" do
|
427
|
+
original_text = File.read(original_file)
|
428
|
+
expected_text = File.read(transformed_file)
|
429
|
+
transformed_text = custom_upgrade(original_text)
|
430
|
+
assert_equal(expected_text, transformed_text)
|
431
|
+
end
|
220
432
|
end
|
221
433
|
end
|
222
434
|
end
|