Skip to content

388 fix optional argument handling #404

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 3 commits into from
May 21, 2020
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 @@ -92,11 +92,10 @@ internal class MethodFieldResolver(
}

if (value == null && isOptional) {
if (environment.containsArgument(definition.name)) {
return@add Optional.empty<Any>()
} else {
if (options.inputArgumentOptionalDetectOmission && !environment.containsArgument(definition.name)) {
return@add null
}
return@add Optional.empty<Any>()
}

if (value != null
Expand Down
21 changes: 18 additions & 3 deletions src/main/kotlin/graphql/kickstart/tools/SchemaParserOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ data class SchemaParserOptions internal constructor(
val allowUnimplementedResolvers: Boolean,
val objectMapperProvider: PerFieldObjectMapperProvider,
val proxyHandlers: List<ProxyHandler>,
val inputArgumentOptionalDetectOmission: Boolean,
val preferGraphQLResolver: Boolean,
val introspectionEnabled: Boolean,
val coroutineContextProvider: CoroutineContextProvider,
Expand All @@ -50,6 +51,7 @@ data class SchemaParserOptions internal constructor(
private var allowUnimplementedResolvers = false
private var objectMapperProvider: PerFieldObjectMapperProvider = PerFieldConfiguringObjectMapperProvider()
private val proxyHandlers: MutableList<ProxyHandler> = mutableListOf(Spring4AopProxyHandler(), GuiceAopProxyHandler(), JavassistProxyHandler(), WeldProxyHandler())
private var inputArgumentOptionalDetectOmission = false
private var preferGraphQLResolver = false
private var introspectionEnabled = true
private var coroutineContextProvider: CoroutineContextProvider? = null
Expand Down Expand Up @@ -80,6 +82,10 @@ data class SchemaParserOptions internal constructor(
this.allowUnimplementedResolvers = allowUnimplementedResolvers
}

fun inputArgumentOptionalDetectOmission(inputArgumentOptionalDetectOmission: Boolean) = this.apply {
this.inputArgumentOptionalDetectOmission = inputArgumentOptionalDetectOmission
}

fun preferGraphQLResolver(preferGraphQLResolver: Boolean) = this.apply {
this.preferGraphQLResolver = preferGraphQLResolver
}
Expand Down Expand Up @@ -146,9 +152,18 @@ data class SchemaParserOptions internal constructor(
genericWrappers
}

return SchemaParserOptions(contextClass, wrappers, allowUnimplementedResolvers, objectMapperProvider,
proxyHandlers, preferGraphQLResolver, introspectionEnabled, coroutineContextProvider,
typeDefinitionFactories, fieldVisibility
return SchemaParserOptions(
contextClass,
wrappers,
allowUnimplementedResolvers,
objectMapperProvider,
proxyHandlers,
inputArgumentOptionalDetectOmission,
preferGraphQLResolver,
introspectionEnabled,
coroutineContextProvider,
typeDefinitionFactories,
fieldVisibility
)
}
}
Expand Down
96 changes: 93 additions & 3 deletions src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,101 @@ import org.junit.Test
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.util.*

class MethodFieldResolverTest {

@Test
fun shouldHandleScalarTypesAsMethodInputArgument() {
fun `should handle Optional type as method input argument`() {
val schema = SchemaParser.newParser()
.schemaString("""
type Query {
testValue(input: String): String
testOmitted(input: String): String
testNull(input: String): String
}
"""
)
.scalars(customScalarType)
.resolvers(object : GraphQLQueryResolver {
fun testValue(input: Optional<String>) = input.toString()
fun testOmitted(input: Optional<String>) = input.toString()
fun testNull(input: Optional<String>) = input.toString()
})
.build()
.makeExecutableSchema()

val gql = GraphQL.newGraphQL(schema).build()

val result = gql
.execute(ExecutionInput.newExecutionInput()
.query("""
query {
testValue(input: "test-value")
testOmitted
testNull(input: null)
}
""")
.context(Object())
.root(Object()))

val expected = mapOf(
"testValue" to "Optional[test-value]",
"testOmitted" to "Optional.empty",
"testNull" to "Optional.empty"
)

Assert.assertEquals(expected, result.getData())
}

@Test
fun `should handle Optional type as method input argument with omission detection`() {
val schema = SchemaParser.newParser()
.schemaString("""
type Query {
testValue(input: String): String
testOmitted(input: String): String
testNull(input: String): String
}
"""
)
.scalars(customScalarType)
.resolvers(object : GraphQLQueryResolver {
fun testValue(input: Optional<String>) = input.toString()
fun testOmitted(input: Optional<String>?) = input.toString()
fun testNull(input: Optional<String>) = input.toString()
})
.options(SchemaParserOptions.newOptions()
.inputArgumentOptionalDetectOmission(true)
.build())
.build()
.makeExecutableSchema()

val gql = GraphQL.newGraphQL(schema).build()

val result = gql
.execute(ExecutionInput.newExecutionInput()
.query("""
query {
testValue(input: "test-value")
testOmitted
testNull(input: null)
}
""")
.context(Object())
.root(Object()))

val expected = mapOf(
"testValue" to "Optional[test-value]",
"testOmitted" to "null",
"testNull" to "Optional.empty"
)

Assert.assertEquals(expected, result.getData())
}

@Test
fun `should handle scalar types as method input argument`() {
val schema = SchemaParser.newParser()
.schemaString("""
scalar CustomScalar
Expand Down Expand Up @@ -47,7 +137,7 @@ class MethodFieldResolverTest {
}

@Test
fun shouldHandleListsOfScalarTypes() {
fun `should handle lists of scalar types`() {
val schema = SchemaParser.newParser()
.schemaString("""
scalar CustomScalar
Expand Down Expand Up @@ -80,7 +170,7 @@ class MethodFieldResolverTest {
}

@Test
fun shouldHandleProxies() {
fun `should handle proxies`() {
val invocationHandler = object : InvocationHandler {
override fun invoke(proxy: Any, method: Method, args: Array<out Any>): Any {
return when (method.name) {
Expand Down