Repository: graphql-java-kickstart/graphql-java-tools
Pull request #481 (2021-02-15 19:08:25)

Interface type can have non-empty interface lists
## Checklist
<!-- Change [ ] to [x] to indicate you acknowledge the check. -->
- [x] Pull requests follows the [contribution guide](https://github.com/graphql-java-kickstart/graphql-java-tools/wiki/Contribution-guide)
- [x] New or modified functionality is covered by tests

## Description
Since interfaces can now implement other interfaces the `interfaces` list of interfaces should not always be empty when creating the `GraphQLInterfaceType` in `createInterfaceObject`. The test-case failed before, but should be considered valid in my eyes.



Patch:
diff --git a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
index c93fcca..ee1d217 100644
--- a/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
+++ b/src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
@@ -234,6 +234,11 @@ class SchemaParser internal constructor(
             builder.field { field -> createField(field, fieldDefinition, inputObjects) }
         }
 
+        interfaceDefinition.implements.forEach { implementsDefinition ->
+            val interfaceName = (implementsDefinition as TypeName).name
+            builder.withInterface(GraphQLTypeReference(interfaceName))
+        }
+
         return schemaGeneratorDirectiveHelper.onInterface(builder.build(), schemaDirectiveParameters)
     }
 


Test patch:
diff --git a/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt b/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
index 06854b6..3b6c378 100644
--- a/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
+++ b/src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
@@ -1,6 +1,8 @@
 package graphql.kickstart.tools
 
 import graphql.kickstart.tools.resolver.FieldResolverError
+import graphql.schema.GraphQLInterfaceType
+import graphql.schema.GraphQLObjectType
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -402,6 +404,81 @@ class SchemaParserTest {
             .makeExecutableSchema()
     }
 
+    @Test
+    fun `interface implementing an interface should have non-empty interface list`() {
+        val schema = SchemaParser.newParser()
+            .schemaString(
+                """
+                interface Trait {
+                    id: ID!
+                }
+                interface MammalTrait implements Trait {
+                    id: ID!
+                }
+                type PoodleTrait implements Trait & MammalTrait {
+                    id: ID!
+                }
+
+                interface Animal {
+                    id: ID!
+                    traits: [Trait]
+                }
+                interface Dog implements Animal {
+                    id: ID!
+                    traits: [MammalTrait]
+                }
+                type Poodle implements Animal & Dog {
+                    id: ID!
+                    traits: [PoodleTrait]
+                }
+
+                type Query { test: [Poodle] }
+                """)
+            .resolvers(MultiLevelInterfaceResolver())
+            .build()
+            .makeExecutableSchema()
+        val traitInterface = schema.getType("Trait") as GraphQLInterfaceType
+        val animalInterface = schema.getType("Animal") as GraphQLInterfaceType
+        val mammalTraitInterface = schema.getType("MammalTrait") as GraphQLInterfaceType
+        val dogInterface = schema.getType("Dog") as GraphQLInterfaceType
+        val poodleObject = schema.getType("Poodle") as GraphQLObjectType
+        val poodleTraitObject = schema.getType("PoodleTrait") as GraphQLObjectType
+
+        assert(poodleObject.interfaces.containsAll(listOf(dogInterface, animalInterface)))
+        assert(poodleTraitObject.interfaces.containsAll(listOf(mammalTraitInterface, traitInterface)))
+        assert(dogInterface.interfaces.contains(animalInterface))
+        assert(mammalTraitInterface.interfaces.contains(traitInterface))
+        assert(traitInterface.definition.implements.isEmpty())
+        assert(animalInterface.definition.implements.isEmpty())
+    }
+
+    class MultiLevelInterfaceResolver : GraphQLQueryResolver {
+        fun test(): List<Poodle> = listOf()
+
+        interface Trait {
+            var id: String
+        }
+
+        interface MammalTrait : Trait {
+            override var id: String
+        }
+
+        interface PoodleTrait : MammalTrait {
+            override var id: String
+        }
+
+        abstract class Animal<T : Trait> {
+            var id: String? = null
+            abstract var traits: List<T>
+        }
+
+        abstract class Dog<T : MammalTrait> : Animal<T>() {
+            abstract override var traits: List<T>
+        }
+
+        class Poodle(override var traits: List<PoodleTrait>) : Dog<PoodleTrait>()
+    }
+
     enum class EnumType {
         TEST
     }