Skip to content

Commit 7674a59

Browse files
committed
Give super-method behavior its own tests
1 parent 6c2bbe1 commit 7674a59

File tree

4 files changed

+128
-13
lines changed

4 files changed

+128
-13
lines changed

lib/graphql/schema/field.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def resolve_field_method(obj, ruby_kwargs, ctx)
262262
end
263263
else
264264
raise <<-ERR
265-
Failed to implement #{ctx.irep_node.owner_type.name}.#{ctx.field.name}, tried:
265+
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
266266
267267
- `#{obj.class}##{@method_sym}`, which did not exist
268268
- `#{obj.object.class}##{@method_sym}`, which did not exist
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# frozen_string_literal: true
2+
require "spec_helper"
3+
4+
describe GraphQL::Schema::Member::HasFields do
5+
module SuperTest
6+
class BaseObject < GraphQL::Schema::Object
7+
end
8+
9+
module BaseInterface
10+
include GraphQL::Schema::Interface
11+
end
12+
13+
module InterfaceWithFloatField
14+
include BaseInterface
15+
field :float, Float, null: false
16+
def float
17+
# This should call the default implementation
18+
super * 0.5
19+
end
20+
end
21+
22+
module SubInterfaceWithFloatField
23+
include InterfaceWithFloatField
24+
def float
25+
# This should call `InterfaceWithFloatField#float`
26+
super * 0.1
27+
end
28+
end
29+
30+
class ObjectWithFloatField < BaseObject
31+
implements InterfaceWithFloatField
32+
end
33+
34+
class ObjectWithSubFloatField < BaseObject
35+
implements SubInterfaceWithFloatField
36+
end
37+
38+
module InterfaceWithStringField
39+
include BaseInterface
40+
field :string, String, null: false
41+
def string
42+
# Return a literal value to ensure this method was called
43+
"here's a string"
44+
end
45+
end
46+
47+
class ObjectWithStringField < BaseObject
48+
implements InterfaceWithStringField
49+
def string
50+
# This should call to `InterfaceWithStringField#string`
51+
super.upcase
52+
end
53+
end
54+
55+
class SubObjectWithStringField < ObjectWithStringField
56+
def string
57+
# This should call to `ObjectWithStringField#string`
58+
super.reverse
59+
end
60+
end
61+
62+
class Query < BaseObject
63+
field :int, Integer, null: false
64+
def int
65+
# This should call default resolution
66+
super * 2
67+
end
68+
69+
field :string1, ObjectWithStringField, null: false
70+
alias :string1 :object
71+
72+
field :string2, SubObjectWithStringField, null: false
73+
alias :string2 :object
74+
75+
field :float1, ObjectWithFloatField, null: false
76+
alias :float1 :object
77+
78+
field :float2, ObjectWithSubFloatField, null: false
79+
alias :float2 :object
80+
end
81+
82+
class Schema < GraphQL::Schema
83+
query(Query)
84+
end
85+
end
86+
87+
describe "Calling super in field methods" do
88+
# Test that calling `super` in field methods "works", which means:
89+
# - If there is a super method in the user-created hierarchy (either a class or module), it is called
90+
# This is tested by putting random transformations in method bodies,
91+
# then asserting that they are called.
92+
# - If there's no user-defined super method, it calls the built-in default behavior
93+
# This is tested by putting values in the `root_value` hash.
94+
# The default behavior is to fetch hash values by key, so we assert that
95+
# those values are subject to the specified transformations.
96+
97+
describe "Object methods" do
98+
it "may call super to default implementation" do
99+
res = SuperTest::Schema.execute("{ int }", root_value: { int: 4 })
100+
assert_equal 8, res["data"]["int"]
101+
end
102+
103+
it "may call super to interface method" do
104+
res = SuperTest::Schema.execute(" { string1 { string } }", root_value: {})
105+
assert_equal "HERE'S A STRING", res["data"]["string1"]["string"]
106+
end
107+
108+
it "may call super to superclass method" do
109+
res = SuperTest::Schema.execute(" { string2 { string } }", root_value: {})
110+
assert_equal "GNIRTS A S'EREH", res["data"]["string2"]["string"]
111+
end
112+
end
113+
114+
describe "Interface methods" do
115+
it "may call super to interface method" do
116+
res = SuperTest::Schema.execute(" { float1 { float } }", root_value: { float: 6.0 })
117+
assert_equal 3.0, res["data"]["float1"]["float"]
118+
end
119+
120+
it "may call super to superclass method" do
121+
res = SuperTest::Schema.execute(" { float2 { float } }", root_value: { float: 6.0 })
122+
assert_in_delta 0.001, 0.3, res["data"]["float2"]["float"]
123+
end
124+
end
125+
end
126+
end

spec/graphql/schema/object_spec.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@
5454
GRAPHQL
5555
res = Jazz::Schema.execute(query_str)
5656
ensemble = res["data"]["hashyEnsemble"]
57-
# This also tests `super` in an interface field
58-
assert_equal ["Jerry Garcia", "Phil Lesh"], ensemble["musicians"].map { |m| m["name"] }
57+
assert_equal ["Jerry Garcia"], ensemble["musicians"].map { |m| m["name"] }
5958
assert_equal "May 5, 1965", ensemble["formedAt"]
6059
end
6160

spec/support/jazz.rb

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,6 @@ def upcase_name
169169
module HasMusicians
170170
include BaseInterface
171171
field :musicians, "[Jazz::Musician]", null: false
172-
173-
def musicians
174-
# Test that super works
175-
super + [Models::Musician.new("Phil Lesh")]
176-
end
177172
end
178173

179174

@@ -312,11 +307,6 @@ def self.resolve_type(object, context)
312307

313308
class HashKeyTest < BaseObject
314309
field :falsey, Boolean, null: false
315-
316-
def falsey
317-
# test that super can be used in objects
318-
super
319-
end
320310
end
321311

322312
# Another new-style definition, with method overrides

0 commit comments

Comments
 (0)