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

[client] support optional input for kotlinx serialization #1250

Merged
merged 2 commits into from
Aug 30, 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
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

package com.expediagroup.graphql.client.jackson

import com.expediagroup.graphql.client.jackson.data.EmptyInputQuery
import com.expediagroup.graphql.client.jackson.data.EnumQuery
import com.expediagroup.graphql.client.jackson.data.FirstQuery
import com.expediagroup.graphql.client.jackson.data.InputListQuery
import com.expediagroup.graphql.client.jackson.data.InputQuery
import com.expediagroup.graphql.client.jackson.data.OptionalInputQuery
import com.expediagroup.graphql.client.jackson.data.OtherQuery
Expand All @@ -30,6 +30,7 @@ import com.expediagroup.graphql.client.jackson.types.JacksonGraphQLError
import com.expediagroup.graphql.client.jackson.types.JacksonGraphQLResponse
import com.expediagroup.graphql.client.jackson.types.JacksonGraphQLSourceLocation
import com.expediagroup.graphql.client.jackson.types.OptionalInput
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.junit.jupiter.api.Test
import java.util.UUID
Expand All @@ -38,39 +39,44 @@ import kotlin.test.assertEquals
class GraphQLClientJacksonSerializerTest {

private val testMapper = jacksonObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT)
private val serializer = GraphQLClientJacksonSerializer(testMapper)

@Test
fun `verify we can serialize GraphQLClientRequest`() {
val testQuery = FirstQuery(FirstQuery.Variables(input = 1.0f))
val expected =
"""{
| "query": "FIRST_QUERY",
| "operationName": "FirstQuery",
| "variables": { "input": 1.0 }
| "variables" : {
| "input" : 1.0
| },
| "query" : "FIRST_QUERY",
| "operationName" : "FirstQuery"
|}
""".trimMargin()

val result = serializer.serialize(testQuery)
assertEquals(testMapper.readTree(expected), testMapper.readTree(result))
val serialized = serializer.serialize(testQuery)
assertEquals(expected, serialized)
}

@Test
fun `verify we can serialize batch GraphQLClientRequest`() {
val queries = listOf(FirstQuery(FirstQuery.Variables(input = 1.0f)), OtherQuery())
val expected =
"""[{
| "query": "FIRST_QUERY",
| "operationName": "FirstQuery",
| "variables": { "input": 1.0 }
|},{
| "query": "OTHER_QUERY",
| "operationName": "OtherQuery"
|}]
"""[ {
| "variables" : {
| "input" : 1.0
| },
| "query" : "FIRST_QUERY",
| "operationName" : "FirstQuery"
|}, {
| "query" : "OTHER_QUERY",
| "operationName" : "OtherQuery"
|} ]
""".trimMargin()

val result = serializer.serialize(queries)
assertEquals(testMapper.readTree(expected), testMapper.readTree(result))
val serialized = serializer.serialize(queries)
assertEquals(expected, serialized)
}

@Test
Expand Down Expand Up @@ -173,16 +179,19 @@ class GraphQLClientJacksonSerializerTest {
fun `verify we can serialize custom scalars`() {
val randomUUID = UUID.randomUUID()
val scalarQuery = ScalarQuery(variables = ScalarQuery.Variables(alias = "1234", custom = com.expediagroup.graphql.client.jackson.data.scalars.UUID(randomUUID)))
val rawQuery =
val expected =
"""{
| "query": "SCALAR_QUERY",
| "operationName": "ScalarQuery",
| "variables": { "alias": "1234", "custom": "$randomUUID" }
| "variables" : {
| "alias" : "1234",
| "custom" : "$randomUUID"
| },
| "query" : "SCALAR_QUERY",
| "operationName" : "ScalarQuery"
|}
""".trimMargin()

val serialized = serializer.serialize(scalarQuery)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
assertEquals(expected, serialized)
}

@Test
Expand Down Expand Up @@ -217,16 +226,18 @@ class GraphQLClientJacksonSerializerTest {
@Test
fun `verify we can serialize enums with custom names`() {
val query = EnumQuery(variables = EnumQuery.Variables(enum = TestEnum.THREE))
val rawQuery =
val expected =
"""{
| "query": "ENUM_QUERY",
| "operationName": "EnumQuery",
| "variables": { "enum": "three" }
| "variables" : {
| "enum" : "three"
| },
| "query" : "ENUM_QUERY",
| "operationName" : "EnumQuery"
|}
""".trimMargin()

val serialized = serializer.serialize(query)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
assertEquals(expected, serialized)
}

@Test
Expand All @@ -242,83 +253,69 @@ class GraphQLClientJacksonSerializerTest {

@Test
fun `verify we can serialize optional inputs`() {
val query = InputQuery(
variables = InputQuery.Variables(
val query = OptionalInputQuery(
variables = OptionalInputQuery.Variables(
requiredInput = 123,
optionalIntInput = OptionalInput.Defined(123),
optionalStringInput = OptionalInput.Defined(null)
// optionalBooleanInput = OptionalInput.Undefined // use default
)
)
val rawQuery =
val expected =
"""{
| "query": "INPUT_QUERY",
| "operationName": "InputQuery",
| "variables": {
| "requiredInput": 123,
| "optionalIntInput": 123,
| "optionalStringInput": null
| }
| "variables" : {
| "requiredInput" : 123,
| "optionalIntInput" : 123,
| "optionalStringInput" : null
| },
| "query" : "OPTIONAL_INPUT_QUERY",
| "operationName" : "OptionalInputQuery"
|}
""".trimMargin()

val serialized = serializer.serialize(query)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
assertEquals(expected, serialized)
}

@Test
fun `verify list serialization`() {
val query = InputListQuery(
variables = InputListQuery.Variables(
nonNullableIds = listOf("ABC")
fun `verify serialization of null values and empty collections`() {
val query = InputQuery(
variables = InputQuery.Variables(
requiredInput = 123,
// nullableId = null, // use default
nullableListNullableElements = listOf(null),
nullableListNonNullableElements = null, // same as default
nullableElementList = listOf("foo", null),
nonNullableElementList = listOf()
)
)
val rawQuery =
"""{
| "query": "INPUT_LIST_QUERY",
| "operationName": "InputListQuery",
| "variables": {
| "nonNullableIds": ["ABC"]
| }
|}
""".trimMargin()

val expected = """{
| "variables" : {
| "requiredInput" : 123,
| "nullableListNullableElements" : [ null ],
| "nullableElementList" : [ "foo", null ],
| "nonNullableElementList" : [ ]
| },
| "query" : "INPUT_QUERY",
| "operationName" : "InputQuery"
|}""".trimMargin()
val serialized = serializer.serialize(query)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
assertEquals(expected, serialized)
}

@Test
fun `verify nullable list serialization`() {
val query = InputListQuery(
variables = InputListQuery.Variables(
nullableIds = listOf("XYZ", null),
nullableIdList = null,
nonNullableIds = listOf()
)
fun `verify serialization of empty variables`() {
val query = EmptyInputQuery(
variables = EmptyInputQuery.Variables()
)
val rawQuery =
"""{
| "query": "INPUT_LIST_QUERY",
| "operationName": "InputListQuery",
| "variables": {
| "nullableIds": ["XYZ", null],
| "nonNullableIds": []
| }
|}
""".trimMargin()
val serialized = serializer.serialize(query)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
}

@Test
fun `verify unspecified optional input serialization results in empty variables`() {
val query = OptionalInputQuery(variables = OptionalInputQuery.Variables())
val rawQuery =
"""{
| "query": "OPTIONAL_INPUT_QUERY",
| "operationName": "OptionalInputQuery",
| "variables": {}
|}
""".trimMargin()
val expected = """{
| "variables" : { },
| "query" : "EMPTY_INPUT_QUERY",
| "operationName" : "EmptyInputQuery"
|}""".trimMargin()
val serialized = serializer.serialize(query)
assertEquals(testMapper.readTree(rawQuery), testMapper.readTree(serialized))
assertEquals(expected, serialized)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,23 @@
package com.expediagroup.graphql.client.jackson.data

import com.expediagroup.graphql.client.types.GraphQLClientRequest
import kotlin.String
import kotlin.collections.List
import kotlin.reflect.KClass

class InputListQuery(
class EmptyInputQuery(
override val variables: Variables
) : GraphQLClientRequest<InputListQuery.Result> {
override val query: String = "INPUT_LIST_QUERY"
) : GraphQLClientRequest<EmptyInputQuery.Result> {

override val operationName: String = "InputListQuery"
override val query: String = "EMPTY_INPUT_QUERY"

override val operationName: String = "EmptyInputQuery"

override fun responseType(): KClass<Result> = Result::class

data class Variables(
val nullableIds: List<String?>? = null,
val nullableIdList: List<String>? = null,
val nonNullableIds: List<String>
val nullable: Int? = null
)

data class Result(
val inputListQuery: String?
val stringResult: String
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@

package com.expediagroup.graphql.client.jackson.data

import com.expediagroup.graphql.client.jackson.types.OptionalInput
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import kotlin.String
import kotlin.collections.List
import kotlin.reflect.KClass

class InputQuery(
Expand All @@ -31,12 +32,14 @@ class InputQuery(

data class Variables(
val requiredInput: Int,
val optionalIntInput: OptionalInput<Int> = OptionalInput.Undefined,
val optionalStringInput: OptionalInput<String> = OptionalInput.Undefined,
val optionalBooleanInput: OptionalInput<Boolean> = OptionalInput.Undefined
val nullableId: Int? = null,
val nullableListNullableElements: List<String?>? = null,
val nullableListNonNullableElements: List<String>? = null,
val nullableElementList: List<String?>,
val nonNullableElementList: List<String>
)

data class Result(
val stringResult: String
val inputListQuery: String?
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.expediagroup.graphql.client.jackson.data

import com.expediagroup.graphql.client.jackson.types.OptionalInput
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import kotlin.reflect.KClass

Expand All @@ -29,7 +30,10 @@ class OptionalInputQuery(
override fun responseType(): KClass<Result> = Result::class

data class Variables(
val optional: String? = null
val requiredInput: Int,
val optionalIntInput: OptionalInput<Int> = OptionalInput.Undefined,
val optionalStringInput: OptionalInput<String> = OptionalInput.Undefined,
val optionalBooleanInput: OptionalInput<Boolean> = OptionalInput.Undefined
)

data class Result(
Expand Down
3 changes: 2 additions & 1 deletion clients/graphql-kotlin-client-serialization/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ tasks {
limit {
counter = "INSTRUCTION"
value = "COVEREDRATIO"
minimum = "0.73".toBigDecimal()
// increase it when https://github.com/Kotlin/kotlinx.serialization/issues/961 is resolved
minimum = "0.70".toBigDecimal()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ class GraphQLClientKotlinxSerializer(private val jsonBuilder: JsonBuilder.() ->
apply(jsonBuilder)
classDiscriminator = "__typename"
coerceInputValues = true
// encodeDefaults = false // need this for optional
encodeDefaults = true
encodeDefaults = false
}

override fun serialize(request: GraphQLClientRequest<*>): String = json.encodeToString(requestSerializer(request), request)
Expand Down
Loading