Skip to content

Commit 9c4b7eb

Browse files
author
Robert Mosolgo
authored
Merge pull request #3014 from jturkel/feature/deprecations-from-introspection
Load deprecation reason from introspection results
2 parents eb15f03 + 38b1f23 commit 9c4b7eb

File tree

2 files changed

+132
-125
lines changed

2 files changed

+132
-125
lines changed

lib/graphql/schema/loader.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def define_type(type, type_resolver)
9898
value(
9999
enum_value["name"],
100100
description: enum_value["description"],
101-
deprecation_reason: enum_value["deprecation_reason"],
101+
deprecation_reason: enum_value["deprecationReason"],
102102
)
103103
end
104104
end
@@ -156,6 +156,7 @@ def build_fields(type_defn, fields, type_resolver)
156156
field_hash["name"],
157157
type: type_resolver.call(field_hash["type"]),
158158
description: field_hash["description"],
159+
deprecation_reason: field_hash["deprecationReason"],
159160
null: true,
160161
camelize: false,
161162
) do

spec/graphql/schema/loader_spec.rb

Lines changed: 130 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -2,132 +2,142 @@
22
require "spec_helper"
33

44
describe GraphQL::Schema::Loader do
5+
Boolean = "Boolean"
6+
ID = "ID"
7+
Int = "Int"
8+
59
let(:schema) {
6-
node_type = GraphQL::InterfaceType.define do
7-
name "Node"
10+
node_type = Module.new do
11+
include GraphQL::Schema::Interface
12+
graphql_name "Node"
813

9-
field :id, !types.ID
14+
field :id, ID, null: false
1015
end
1116

12-
choice_type = GraphQL::EnumType.define do
13-
name "Choice"
17+
choice_type = Class.new(GraphQL::Schema::Enum) do
18+
graphql_name "Choice"
1419

1520
value "FOO", value: :foo
16-
value "BAR"
21+
value "BAR", deprecation_reason: "Don't use BAR"
1722
end
1823

19-
sub_input_type = GraphQL::InputObjectType.define do
20-
name "Sub"
21-
input_field :string, types.String
24+
sub_input_type = Class.new(GraphQL::Schema::InputObject) do
25+
graphql_name "Sub"
26+
argument :string, String, required: false
2227
end
2328

24-
big_int_type = GraphQL::ScalarType.define do
25-
name "BigInt"
26-
coerce_input ->(value, _ctx) { value =~ /\d+/ ? Integer(value) : nil }
27-
coerce_result ->(value, _ctx) { value.to_s }
29+
big_int_type = Class.new(GraphQL::Schema::Scalar) do
30+
graphql_name "BigInt"
31+
32+
def self.coerce_input(value, _ctx)
33+
value =~ /\d+/ ? Integer(value) : nil
34+
end
35+
36+
def self.coerce_result(value, _ctx)
37+
value.to_s
38+
end
2839
end
2940

30-
variant_input_type = GraphQL::InputObjectType.define do
31-
name "Varied"
32-
input_field :id, types.ID
33-
input_field :int, types.Int
34-
input_field :bigint, big_int_type, default_value: 2**54
35-
input_field :float, types.Float
36-
input_field :bool, types.Boolean
37-
input_field :enum, choice_type
38-
input_field :sub, types[sub_input_type]
41+
variant_input_type = Class.new(GraphQL::Schema::InputObject) do
42+
graphql_name "Varied"
43+
argument :id, ID, required: false
44+
argument :int, Int, required: false
45+
argument :bigint, big_int_type, required: false, default_value: 2**54
46+
argument :float, Float, required: false
47+
argument :bool, Boolean, required: false
48+
argument :enum, choice_type, required: false
49+
argument :sub, [sub_input_type], required: false
3950
end
4051

41-
variant_input_type_with_nulls = GraphQL::InputObjectType.define do
42-
name "VariedWithNulls"
43-
input_field :id, types.ID, default_value: nil
44-
input_field :int, types.Int, default_value: nil
45-
input_field :bigint, big_int_type, default_value: nil
46-
input_field :float, types.Float, default_value: nil
47-
input_field :bool, types.Boolean, default_value: nil
48-
input_field :enum, choice_type, default_value: nil
49-
input_field :sub, types[sub_input_type], default_value: nil
52+
variant_input_type_with_nulls = Class.new(GraphQL::Schema::InputObject) do
53+
graphql_name "VariedWithNulls"
54+
argument :id, ID, required: false, default_value: nil
55+
argument :int, Int, required: false, default_value: nil
56+
argument :bigint, big_int_type, required: false, default_value: nil
57+
argument :float, Float, required: false, default_value: nil
58+
argument :bool, Boolean, required: false, default_value: nil
59+
argument :enum, choice_type, required: false, default_value: nil
60+
argument :sub, [sub_input_type], required: false, default_value: nil
5061
end
5162

52-
comment_type = GraphQL::ObjectType.define do
53-
name "Comment"
63+
comment_type = Class.new(GraphQL::Schema::Object) do
64+
graphql_name "Comment"
5465
description "A blog comment"
55-
interfaces [node_type]
66+
implements node_type
5667

57-
field :body, !types.String
68+
field :body, String, null: false
5869

59-
field :fieldWithArg, types.Int do
60-
argument :bigint, big_int_type, default_value: 2**54
70+
field :field_with_arg, Int, null: true do
71+
argument :bigint, big_int_type, default_value: 2**54, required: false
6172
end
6273
end
6374

64-
media_type = GraphQL::InterfaceType.define do
65-
name "Media"
75+
media_type = Module.new do
76+
include GraphQL::Schema::Interface
77+
78+
graphql_name "Media"
6679
description "!!!"
67-
field :type, !types.String
80+
field :type, String, null: false
6881
end
6982

70-
video_type = GraphQL::ObjectType.define do
71-
name "Video"
72-
interfaces [media_type]
83+
video_type = Class.new(GraphQL::Schema::Object) do
84+
graphql_name "Video"
85+
implements media_type
7386
end
7487

75-
audio_type = GraphQL::ObjectType.define do
76-
name "Audio"
77-
interfaces [media_type]
88+
audio_type = Class.new(GraphQL::Schema::Object) do
89+
graphql_name "Audio"
90+
implements media_type
7891
end
7992

80-
post_type = GraphQL::ObjectType.define do
81-
name "Post"
93+
post_type = Class.new(GraphQL::Schema::Object) do
94+
graphql_name "Post"
8295
description "A blog post"
8396

84-
field :id, !types.ID
85-
field :title, !types.String
86-
field :body, !types.String
87-
field :comments, types[!comment_type]
88-
field :attachment, media_type
97+
field :id, ID, null: false
98+
field :title, String, null: false
99+
field :summary, String, null: true, deprecation_reason: "Don't use Post.summary"
100+
field :body, String, null: false
101+
field :comments, [comment_type], null: true
102+
field :attachment, media_type, null: true
89103
end
90104

91-
content_type = GraphQL::UnionType.define do
92-
name "Content"
105+
content_type = Class.new(GraphQL::Schema::Union) do
106+
graphql_name "Content"
93107
description "A post or comment"
94-
possible_types [post_type, comment_type]
108+
possible_types post_type, comment_type
95109
end
96110

97-
query_root = GraphQL::ObjectType.define do
98-
name "Query"
111+
query_root = Class.new(GraphQL::Schema::Object) do
112+
graphql_name "Query"
99113
description "The query root of this schema"
100114

101-
field :post do
102-
type post_type
103-
argument :id, !types.ID
104-
argument :varied, variant_input_type, default_value: { id: "123", int: 234, float: 2.3, enum: :foo, sub: [{ string: "str" }] }
105-
argument :variedWithNull, variant_input_type_with_nulls, default_value: { id: nil, int: nil, float: nil, enum: nil, sub: nil, bigint: nil, bool: nil }
106-
argument :variedArray, types[variant_input_type], default_value: [{ id: "123", int: 234, float: 2.3, enum: :foo, sub: [{ string: "str" }] }]
107-
argument :enum, choice_type, default_value: :foo
108-
argument :array, types[!types.String], default_value: ["foo", "bar"]
115+
field :post, post_type, null: true do
116+
argument :id, ID, required: true
117+
argument :varied, variant_input_type, required: false, default_value: { id: "123", int: 234, float: 2.3, enum: :foo, sub: [{ string: "str" }] }
118+
argument :variedWithNull, variant_input_type_with_nulls, required: false, default_value: { id: nil, int: nil, float: nil, enum: nil, sub: nil, bigint: nil, bool: nil }
119+
argument :variedArray, [variant_input_type], required: false, default_value: [{ id: "123", int: 234, float: 2.3, enum: :foo, sub: [{ string: "str" }] }]
120+
argument :enum, choice_type, required: false, default_value: :foo
121+
argument :array, [String], required: false, default_value: ["foo", "bar"]
109122
end
110123

111-
field :content do
112-
type content_type
113-
end
124+
field :content, content_type, null: true
114125
end
115126

116-
ping_mutation = GraphQL::Relay::Mutation.define do
117-
name "Ping"
127+
ping_mutation = Class.new(GraphQL::Schema::RelayClassicMutation) do
128+
graphql_name "Ping"
118129
end
119130

120-
mutation_root = GraphQL::ObjectType.define do
121-
name "Mutation"
122-
field :ping, field: ping_mutation.field
131+
mutation_root = Class.new(GraphQL::Schema::Object) do
132+
graphql_name "Mutation"
133+
field :ping, mutation: ping_mutation
123134
end
124135

125-
GraphQL::Schema.define(
126-
query: query_root,
127-
mutation: mutation_root,
128-
orphan_types: [audio_type, video_type],
129-
resolve_type: ->(a,b,c) { :pass },
130-
)
136+
Class.new(GraphQL::Schema) do
137+
query query_root
138+
mutation mutation_root
139+
orphan_types audio_type, video_type
140+
end
131141
}
132142

133143
let(:schema_json) {
@@ -136,56 +146,53 @@
136146

137147
describe "load" do
138148
def assert_deep_equal(expected_type, actual_type)
139-
assert_equal expected_type.class, actual_type.class
140-
141-
case actual_type
142-
when Array
149+
if actual_type.is_a?(Array)
143150
actual_type.each_with_index do |obj, index|
144151
assert_deep_equal expected_type[index], obj
145152
end
146-
147-
when GraphQL::Schema
148-
assert_equal expected_type.query.name, actual_type.query.name
149-
assert_equal expected_type.directives.keys.sort, actual_type.directives.keys.sort
150-
assert_equal expected_type.types.keys.sort, actual_type.types.keys.sort
151-
assert_deep_equal expected_type.types.values.sort_by(&:name), actual_type.types.values.sort_by(&:name)
152-
153-
when GraphQL::ObjectType, GraphQL::InterfaceType
154-
assert_equal expected_type.name, actual_type.name
153+
elsif actual_type.is_a?(GraphQL::Schema::Field)
154+
assert_equal expected_type.graphql_name, actual_type.graphql_name
155155
assert_equal expected_type.description, actual_type.description
156-
assert_deep_equal expected_type.all_fields.sort_by(&:name), actual_type.all_fields.sort_by(&:name)
157-
158-
when GraphQL::Field
159-
assert_equal expected_type.name, actual_type.name
156+
assert_equal expected_type.deprecation_reason, actual_type.deprecation_reason
157+
assert_deep_equal expected_type.arguments.values.sort_by(&:graphql_name), actual_type.arguments.values.sort_by(&:graphql_name)
158+
elsif actual_type.is_a?(GraphQL::Schema::EnumValue)
159+
assert_equal expected_type.graphql_name, actual_type.graphql_name
160160
assert_equal expected_type.description, actual_type.description
161-
assert_equal expected_type.arguments.keys, actual_type.arguments.keys
162-
assert_deep_equal expected_type.arguments.values, actual_type.arguments.values
163-
164-
when GraphQL::ScalarType
165-
assert_equal expected_type.name, actual_type.name
166-
167-
when GraphQL::EnumType
168-
assert_equal expected_type.name, actual_type.name
169-
assert_equal expected_type.description, actual_type.description
170-
assert_equal expected_type.values.keys, actual_type.values.keys
171-
assert_deep_equal expected_type.values.values, actual_type.values.values
172-
173-
when GraphQL::EnumType::EnumValue
174-
assert_equal expected_type.name, actual_type.name
175-
assert_equal expected_type.description, actual_type.description
176-
177-
when GraphQL::Argument
178-
assert_equal expected_type.name, actual_type.name
161+
assert_equal expected_type.deprecation_reason, actual_type.deprecation_reason
162+
elsif actual_type.is_a?(GraphQL::Schema::Argument)
163+
assert_equal expected_type.graphql_name, actual_type.graphql_name
179164
assert_equal expected_type.description, actual_type.description
180165
assert_deep_equal expected_type.type, actual_type.type
181-
182-
when GraphQL::InputObjectType
183-
assert_equal expected_type.arguments.keys, actual_type.arguments.keys
184-
assert_deep_equal expected_type.arguments.values, actual_type.arguments.values
185-
186-
when GraphQL::NonNullType, GraphQL::ListType
166+
elsif actual_type.is_a?(GraphQL::Schema::NonNull) || actual_type.is_a?(GraphQL::Schema::List)
167+
assert_equal expected_type.class, actual_type.class
187168
assert_deep_equal expected_type.of_type, actual_type.of_type
188-
169+
elsif actual_type < GraphQL::Schema
170+
assert_equal expected_type.query.graphql_name, actual_type.query.graphql_name
171+
assert_equal expected_type.mutation.graphql_name, actual_type.mutation.graphql_name
172+
assert_equal expected_type.directives.keys.sort, actual_type.directives.keys.sort
173+
assert_deep_equal expected_type.types.values.sort_by(&:graphql_name), actual_type.types.values.sort_by(&:graphql_name)
174+
elsif actual_type < GraphQL::Schema::Object
175+
assert_equal expected_type.graphql_name, actual_type.graphql_name
176+
assert_equal expected_type.description, actual_type.description
177+
assert_deep_equal expected_type.interfaces.sort_by(&:graphql_name), actual_type.interfaces.sort_by(&:graphql_name)
178+
assert_deep_equal expected_type.fields.values.sort_by(&:graphql_name), actual_type.fields.values.sort_by(&:graphql_name)
179+
elsif actual_type < GraphQL::Schema::Interface
180+
assert_equal expected_type.graphql_name, actual_type.graphql_name
181+
assert_equal expected_type.description, actual_type.description
182+
assert_deep_equal expected_type.fields.values.sort_by(&:graphql_name), actual_type.fields.values.sort_by(&:graphql_name)
183+
elsif actual_type < GraphQL::Schema::Union
184+
assert_equal expected_type.graphql_name, actual_type.graphql_name
185+
assert_equal expected_type.description, actual_type.description
186+
assert_deep_equal expected_type.possible_types.sort_by(&:graphql_name), actual_type.possible_types.sort_by(&:graphql_name)
187+
elsif actual_type < GraphQL::Schema::Scalar
188+
assert_equal expected_type.graphql_name, actual_type.graphql_name
189+
elsif actual_type < GraphQL::Schema::Enum
190+
assert_equal expected_type.graphql_name, actual_type.graphql_name
191+
assert_equal expected_type.description, actual_type.description
192+
assert_deep_equal expected_type.values.values.sort_by(&:graphql_name), actual_type.values.values.sort_by(&:graphql_name)
193+
elsif actual_type < GraphQL::Schema::InputObject
194+
assert_equal expected_type.graphql_name, actual_type.graphql_name
195+
assert_deep_equal expected_type.arguments.values.sort_by(&:graphql_name), actual_type.arguments.values.sort_by(&:graphql_name)
189196
else
190197
assert_equal expected_type, actual_type
191198
end
@@ -194,8 +201,7 @@ def assert_deep_equal(expected_type, actual_type)
194201
let(:loaded_schema) { GraphQL::Schema.from_introspection(schema_json) }
195202

196203
it "returns the schema" do
197-
assert_instance_of Class, loaded_schema
198-
assert_equal GraphQL::Schema, loaded_schema.superclass
204+
assert_deep_equal(schema, loaded_schema)
199205
end
200206

201207
it "can export the loaded schema" do

0 commit comments

Comments
 (0)