Skip to content

Commit

Permalink
Add a test case for interfaces implementing other interfaces (#2851)
Browse files Browse the repository at this point in the history
* add a test case for interfaces implementing other interfaces

* complexify the test a little bit to test possibelTypes

* fix writing interfaces implemented by interfaces
  • Loading branch information
martinbonnin committed Jan 8, 2021
1 parent 2b9e04b commit dab9902
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ data class GQLInterfaceTypeDefinition(
override fun write(bufferedSink: BufferedSink) {
with(bufferedSink) {
if (description != null) writeUtf8("\"\"\"${GraphQLString.encodeTripleQuoted(description)}\"\"\"\n")
writeUtf8("interface $name ${implementsInterfaces.joinToString(" ")}")
writeUtf8("interface $name")
if (implementsInterfaces.isNotEmpty()) {
writeUtf8(" implements ")
writeUtf8(implementsInterfaces.joinToString(" "))
}
if (directives.isNotEmpty()) {
writeUtf8(" ")
directives.join(bufferedSink)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ internal fun GQLTypeDefinition.possibleTypes(typeDefinitions: Map<String, GQLTyp
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// AUTO-GENERATED FILE. DO NOT MODIFY.
//
// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found.
// It should not be modified by hand.
//
package com.example.interface_on_interface

import com.apollographql.apollo.api.Operation
import com.apollographql.apollo.api.OperationName
import com.apollographql.apollo.api.Query
import com.apollographql.apollo.api.internal.QueryDocumentMinifier
import com.apollographql.apollo.api.internal.ResponseAdapter
import com.example.interface_on_interface.adapter.GetHuman_ResponseAdapter
import kotlin.Double
import kotlin.String
import kotlin.Suppress

@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName",
"RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter", "PropertyName",
"RemoveRedundantQualifierName")
class GetHuman : Query<GetHuman.Data> {
override fun operationId(): String = OPERATION_ID

override fun queryDocument(): String = QUERY_DOCUMENT

override fun variables(): Operation.Variables = Operation.EMPTY_VARIABLES

override fun name(): OperationName = OPERATION_NAME

override fun adapter(): ResponseAdapter<Data> = GetHuman_ResponseAdapter
data class Data(
val human: Human,
val node: Node
) : Operation.Data {
data class Human(
val id: String,
val name: String,
val height: Double
)

interface Node {
val __typename: String

interface Human : Node {
override val __typename: String

val height: Double
}

data class HumanNode(
override val __typename: String,
override val height: Double
) : Node, Human

data class OtherNode(
override val __typename: String
) : Node

companion object {
fun Node.asHuman(): Human? = this as? Human
}
}
}

companion object {
const val OPERATION_ID: String =
"b5ec6431463438b91c2cf1c33eb4b6a1f9e2580b51fcf5150ef3685b9108a12c"

val QUERY_DOCUMENT: String = QueryDocumentMinifier.minify(
"""
|query GetHuman {
| human {
| id
| name
| height
| }
| node {
| __typename
| ... on Human {
| height
| }
| }
|}
""".trimMargin()
)

val OPERATION_NAME: OperationName = object : OperationName {
override fun name(): String {
return "GetHuman"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
query GetHuman {
human {
id
name
height
}
node {
... on Human {
height
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// AUTO-GENERATED FILE. DO NOT MODIFY.
//
// This class was automatically generated by Apollo GraphQL plugin from the GraphQL queries it found.
// It should not be modified by hand.
//
package com.example.interface_on_interface.adapter

import com.apollographql.apollo.api.ResponseField
import com.apollographql.apollo.api.internal.ResponseAdapter
import com.apollographql.apollo.api.internal.ResponseReader
import com.apollographql.apollo.api.internal.ResponseWriter
import com.example.interface_on_interface.GetHuman
import kotlin.Array
import kotlin.Double
import kotlin.String
import kotlin.Suppress

@Suppress("NAME_SHADOWING", "UNUSED_ANONYMOUS_PARAMETER", "LocalVariableName",
"RemoveExplicitTypeArguments", "NestedLambdaShadowedImplicitParameter", "PropertyName",
"RemoveRedundantQualifierName")
object GetHuman_ResponseAdapter : ResponseAdapter<GetHuman.Data> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forObject("human", "human", null, false, null),
ResponseField.forObject("node", "node", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?): GetHuman.Data {
return Data.fromResponse(reader, __typename)
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data) {
Data.toResponse(writer, value)
}

object Data : ResponseAdapter<GetHuman.Data> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forObject("human", "human", null, false, null),
ResponseField.forObject("node", "node", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?): GetHuman.Data {
return reader.run {
var human: GetHuman.Data.Human? = null
var node: GetHuman.Data.Node? = null
while(true) {
when (selectField(RESPONSE_FIELDS)) {
0 -> human = readObject<GetHuman.Data.Human>(RESPONSE_FIELDS[0]) { reader ->
Human.fromResponse(reader)
}
1 -> node = readObject<GetHuman.Data.Node>(RESPONSE_FIELDS[1]) { reader ->
Node.fromResponse(reader)
}
else -> break
}
}
GetHuman.Data(
human = human!!,
node = node!!
)
}
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data) {
writer.writeObject(RESPONSE_FIELDS[0]) { writer ->
Human.toResponse(writer, value.human)
}
writer.writeObject(RESPONSE_FIELDS[1]) { writer ->
Node.toResponse(writer, value.node)
}
}

object Human : ResponseAdapter<GetHuman.Data.Human> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forString("id", "id", null, false, null),
ResponseField.forString("name", "name", null, false, null),
ResponseField.forDouble("height", "height", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?): GetHuman.Data.Human {
return reader.run {
var id: String? = null
var name: String? = null
var height: Double? = null
while(true) {
when (selectField(RESPONSE_FIELDS)) {
0 -> id = readString(RESPONSE_FIELDS[0])
1 -> name = readString(RESPONSE_FIELDS[1])
2 -> height = readDouble(RESPONSE_FIELDS[2])
else -> break
}
}
GetHuman.Data.Human(
id = id!!,
name = name!!,
height = height!!
)
}
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data.Human) {
writer.writeString(RESPONSE_FIELDS[0], value.id)
writer.writeString(RESPONSE_FIELDS[1], value.name)
writer.writeDouble(RESPONSE_FIELDS[2], value.height)
}
}

object Node : ResponseAdapter<GetHuman.Data.Node> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forString("__typename", "__typename", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?): GetHuman.Data.Node {
val typename = __typename ?: reader.readString(RESPONSE_FIELDS[0])
return when(typename) {
"Human" -> HumanNode.fromResponse(reader, typename)
else -> OtherNode.fromResponse(reader, typename)
}
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data.Node) {
when(value) {
is GetHuman.Data.Node.HumanNode -> HumanNode.toResponse(writer, value)
is GetHuman.Data.Node.OtherNode -> OtherNode.toResponse(writer, value)
}
}

object HumanNode : ResponseAdapter<GetHuman.Data.Node.HumanNode> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forString("__typename", "__typename", null, false, null),
ResponseField.forDouble("height", "height", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?):
GetHuman.Data.Node.HumanNode {
return reader.run {
var __typename: String? = __typename
var height: Double? = null
while(true) {
when (selectField(RESPONSE_FIELDS)) {
0 -> __typename = readString(RESPONSE_FIELDS[0])
1 -> height = readDouble(RESPONSE_FIELDS[1])
else -> break
}
}
GetHuman.Data.Node.HumanNode(
__typename = __typename!!,
height = height!!
)
}
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data.Node.HumanNode) {
writer.writeString(RESPONSE_FIELDS[0], value.__typename)
writer.writeDouble(RESPONSE_FIELDS[1], value.height)
}
}

object OtherNode : ResponseAdapter<GetHuman.Data.Node.OtherNode> {
private val RESPONSE_FIELDS: Array<ResponseField> = arrayOf(
ResponseField.forString("__typename", "__typename", null, false, null)
)

override fun fromResponse(reader: ResponseReader, __typename: String?):
GetHuman.Data.Node.OtherNode {
return reader.run {
var __typename: String? = __typename
while(true) {
when (selectField(RESPONSE_FIELDS)) {
0 -> __typename = readString(RESPONSE_FIELDS[0])
else -> break
}
}
GetHuman.Data.Node.OtherNode(
__typename = __typename!!
)
}
}

override fun toResponse(writer: ResponseWriter, value: GetHuman.Data.Node.OtherNode) {
writer.writeString(RESPONSE_FIELDS[0], value.__typename)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
type Query {
human: Human!
node: Node!
}

interface Node {
id: ID!
}

interface Character implements Node {
id: ID!
name: String!
}

type Human implements Character {
id: ID!
name: String!
height: Float!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.apollographql.apollo.compiler

import com.apollographql.apollo.compiler.frontend.GraphQLParser
import com.apollographql.apollo.compiler.frontend.possibleTypes
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import java.io.File

class PossibleTypesTest {
@Test
fun testPossibleTypes() {
val schema = GraphQLParser.parseSchema(File("src/test/sdl/schema.sdl"))

val possibleTypes = schema.typeDefinition("Node").possibleTypes(schema.typeDefinitions)

assertThat(possibleTypes).isEqualTo(setOf("Empire", "Rebellion"))
}
}
21 changes: 21 additions & 0 deletions apollo-compiler/src/test/sdl/schema.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,24 @@ schema {
query: Query
mutation: Mutation
}

interface Node {
id: ID!
}

interface Organization implements Node {
id: ID!
name: String!
}

type Empire implements Organization {
id: ID!
name: String!
emperor: String!
}

type Rebellion implements Organization {
id: ID!
name: String!
emperor: String!
}

0 comments on commit dab9902

Please sign in to comment.