Skip to content

Commit

Permalink
fix: abstract classes should generate interface (ExpediaGroup#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
dariuszkuc authored and Saurav Tapader committed May 13, 2019
1 parent cb9a4e7 commit 0878723
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.expedia.graphql.sample.query

import com.expedia.graphql.annotations.GraphQLDescription
import com.expedia.graphql.sample.model.BodyPart
import com.expedia.graphql.sample.model.Animal
import com.expedia.graphql.sample.model.AnimalType
import com.expedia.graphql.sample.model.BodyPart
import com.expedia.graphql.sample.model.Cat
import com.expedia.graphql.sample.model.Dog
import com.expedia.graphql.sample.model.LeftHand
Expand All @@ -30,4 +30,4 @@ class PolymorphicQuery: Query {
"right" -> RightHand(12)
else -> LeftHand("hello world")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal open class TypeBuilder constructor(protected val generator: SchemaGener
kClass.isEnum() -> @Suppress("UNCHECKED_CAST") (generator.enumType(kClass as KClass<Enum<*>>))
kClass.isListType() -> generator.listType(type, inputType)
kClass.isUnion() -> generator.unionType(kClass)
kClass.isInterface() -> generator.interfaceType(kClass)
kClass.isInterface() || kClass.isAbstract -> generator.interfaceType(kClass)
inputType -> generator.inputObjectType(kClass)
else -> generator.objectType(kClass)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlin.reflect.KClass
private typealias SuperclassFilter = (KClass<*>) -> Boolean

private val isPublic: SuperclassFilter = { it.isPublic() }
private val isInterface: SuperclassFilter = { it.isInterface() }
private val isInterface: SuperclassFilter = { it.isInterface() || it.isAbstract }
private val isNotUnion: SuperclassFilter = { it.isUnion().not() }

internal val superclassFilters: List<SuperclassFilter> = listOf(isPublic, isInterface, isNotUnion)
33 changes: 30 additions & 3 deletions src/test/kotlin/com/expedia/graphql/generator/PolymorphicTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.expedia.graphql.TopLevelObject
import com.expedia.graphql.exceptions.InvalidInputFieldTypeException
import com.expedia.graphql.testSchemaConfig
import com.expedia.graphql.toSchema
import graphql.schema.GraphQLInterfaceType
import graphql.schema.GraphQLObjectType
import graphql.schema.GraphQLUnionType
import org.junit.jupiter.api.Assertions.assertThrows
Expand Down Expand Up @@ -35,7 +36,7 @@ internal class PolymorphicTests {
fun `SchemaGenerator can expose an interface and its implementations`() {
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithInterface())), config = testSchemaConfig)

val interfaceType = schema.getType("AnInterface")
val interfaceType = schema.getType("AnInterface") as? GraphQLInterfaceType
assertNotNull(interfaceType)

val implementationType = schema.getObjectType("AnImplementation")
Expand All @@ -60,7 +61,7 @@ internal class PolymorphicTests {

@Test
fun `Object types implementing union and interfaces are only created once`() {
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithInterfaceAnUnion())), config = testSchemaConfig)
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithInterfaceAndUnion())), config = testSchemaConfig)

val carType = schema.getType("Car") as? GraphQLObjectType
assertNotNull(carType)
Expand All @@ -79,6 +80,19 @@ internal class PolymorphicTests {
val personType = schema.getType("Person")
assertNotNull(personType)
}

@Test
fun `Abstract classes should be converted to interfaces`() {
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithAbstract())), config = testSchemaConfig)

val abstractInterface = schema.getType("MyAbstract") as? GraphQLInterfaceType
assertNotNull(abstractInterface)

val classWithBaseAbstractType = schema.getObjectType("MyClass")
assertNotNull(classWithBaseAbstractType)
assertEquals(1, classWithBaseAbstractType.interfaces.size)
assertEquals(classWithBaseAbstractType.interfaces.first(), abstractInterface)
}
}

class QueryWithInterface {
Expand Down Expand Up @@ -128,7 +142,7 @@ data class Arm(
val value: Boolean
) : BodyPart

class QueryWithInterfaceAnUnion {
class QueryWithInterfaceAndUnion {
fun product(): Product = Car("DB9", "black")
}

Expand Down Expand Up @@ -156,3 +170,16 @@ data class Father(
val dadJoke: String,
override val child: Person?
) : Person

class QueryWithAbstract {
fun query(): MyAbstract = MyClass(id = 1, name = "JUnit")

fun queryImplementation(): MyClass = MyClass(id = 1, name = "JUnit_2")
}

@Suppress("UnnecessaryAbstractClass")
abstract class MyAbstract {
abstract val id: Int
}

data class MyClass(override val id: Int, val name: String) : MyAbstract()

0 comments on commit 0878723

Please sign in to comment.