@@ -224,6 +224,122 @@ class Query < GraphQL::Schema::Object
224224 end
225225 end
226226
227+ describe "transitive implemention of same interface twice" do
228+ class TransitiveInterfaceSchema < GraphQL ::Schema
229+ module Node
230+ include GraphQL ::Schema ::Interface
231+ field :id , ID
232+
233+ def id ; "id" ; end
234+ end
235+
236+ module Named
237+ include GraphQL ::Schema ::Interface
238+ implements Node
239+ field :name , String
240+
241+ def name ; "name" ; end
242+ end
243+
244+ module Timestamped
245+ include GraphQL ::Schema ::Interface
246+ implements Node
247+ field :timestamp , String
248+
249+ def timestamp ; "ts" ; end
250+ end
251+
252+ class BaseObject < GraphQL ::Schema ::Object
253+ implements Named
254+ implements Timestamped
255+ end
256+
257+ class Thing < BaseObject
258+ implements Named
259+ implements Timestamped
260+ end
261+
262+ class Query < GraphQL ::Schema ::Object
263+ field :thing , Thing
264+ def thing
265+ { }
266+ end
267+ end
268+
269+ query ( Query )
270+ end
271+
272+ it "allows running queries on transitive interfaces" do
273+ result = TransitiveInterfaceSchema . execute ( "{ thing { id name timestamp } }" )
274+
275+ thing = result . dig ( "data" , "thing" )
276+
277+ assert_equal "id" , thing [ "id" ]
278+ assert_equal "name" , thing [ "name" ]
279+ assert_equal "ts" , thing [ "timestamp" ]
280+
281+ result2 = TransitiveInterfaceSchema . execute ( <<-GRAPHQL )
282+ {
283+ thing {
284+ ...on Node { id }
285+ ...on Named {
286+ nid: id name
287+ ...on Node { nnid: id }
288+ }
289+ ... on Timestamped { tid: id timestamp }
290+ }
291+ }
292+ GRAPHQL
293+
294+ thing2 = result2 . dig ( "data" , "thing" )
295+
296+ assert_equal "id" , thing2 [ "id" ]
297+ assert_equal "id" , thing2 [ "nid" ]
298+ assert_equal "id" , thing2 [ "tid" ]
299+ assert_equal "name" , thing2 [ "name" ]
300+ assert_equal "ts" , thing2 [ "timestamp" ]
301+ end
302+
303+ it "has the right structure" do
304+ expected_schema = <<-SCHEMA
305+ interface Named implements Node {
306+ id: ID
307+ name: String
308+ }
309+
310+ interface Node {
311+ id: ID
312+ }
313+
314+ type Query {
315+ thing: Thing
316+ }
317+
318+ type Thing implements Named & Node & Timestamped {
319+ id: ID
320+ name: String
321+ timestamp: String
322+ }
323+
324+ interface Timestamped implements Node {
325+ id: ID
326+ timestamp: String
327+ }
328+ SCHEMA
329+ assert_equal expected_schema , TransitiveInterfaceSchema . to_definition
330+ end
331+
332+ it "only lists each implemented interface once when introspecting" do
333+ introspection = TransitiveInterfaceSchema . as_json
334+ thing_type = introspection . dig ( "data" , "__schema" , "types" ) . find do |type |
335+ type [ "name" ] == "Thing"
336+ end
337+ interfaces_names = thing_type [ "interfaces" ] . map { |i | i [ "name" ] } . sort
338+
339+ assert_equal interfaces_names , [ "Named" , "Node" , "Timestamped" ]
340+ end
341+ end
342+
227343 describe "migrated legacy tests" do
228344 let ( :interface ) { Dummy ::Edible }
229345
0 commit comments