Skip to content
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

Add a test case for interfaces implementing other interfaces #2851

Merged
merged 3 commits into from
Jan 8, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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!
}