Skip to content

Interface type can have non-empty interface lists #481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
77 changes: 77 additions & 0 deletions src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
}
Expand Down