diff --git a/example/src/main/kotlin/com/expedia/graphql/sample/Application.kt b/example/src/main/kotlin/com/expedia/graphql/sample/Application.kt index 2f32a29ae6..a8bf8ee75c 100644 --- a/example/src/main/kotlin/com/expedia/graphql/sample/Application.kt +++ b/example/src/main/kotlin/com/expedia/graphql/sample/Application.kt @@ -4,6 +4,7 @@ import com.expedia.graphql.SchemaGeneratorConfig import com.expedia.graphql.TopLevelObject import com.expedia.graphql.directives.KotlinDirectiveWiringFactory import com.expedia.graphql.execution.KotlinDataFetcherFactoryProvider +import com.expedia.graphql.extensions.print import com.expedia.graphql.hooks.SchemaGeneratorHooks import com.expedia.graphql.sample.datafetchers.CustomDataFetcherFactoryProvider import com.expedia.graphql.sample.datafetchers.SpringDataFetcherFactory @@ -20,7 +21,6 @@ import graphql.execution.AsyncSerialExecutionStrategy import graphql.execution.DataFetcherExceptionHandler import graphql.execution.SubscriptionExecutionStrategy import graphql.schema.GraphQLSchema -import graphql.schema.idl.SchemaPrinter import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -51,23 +51,12 @@ class Application { dataFetcherFactoryProvider = dataFetcherFactoryProvider ) - @Bean - fun schemaPrinter() = SchemaPrinter( - SchemaPrinter.Options.defaultOptions() - .includeScalarTypes(true) - .includeExtendedScalarTypes(true) - .includeIntrospectionTypes(true) - .includeSchemaDefintion(true) - .includeDirectives(true) - ) - @Bean fun schema( queries: List, mutations: List, subscriptions: List, - schemaConfig: SchemaGeneratorConfig, - schemaPrinter: SchemaPrinter + schemaConfig: SchemaGeneratorConfig ): GraphQLSchema { fun List.toTopLevelObjects() = this.map { TopLevelObject(it) @@ -80,7 +69,7 @@ class Application { subscriptions = subscriptions.toTopLevelObjects() ) - logger.info(schemaPrinter.print(schema)) + logger.info(schema.print()) return schema } diff --git a/example/src/main/kotlin/com/expedia/graphql/sample/RoutesConfiguration.kt b/example/src/main/kotlin/com/expedia/graphql/sample/RoutesConfiguration.kt index 5b34a4cf6b..620531effa 100644 --- a/example/src/main/kotlin/com/expedia/graphql/sample/RoutesConfiguration.kt +++ b/example/src/main/kotlin/com/expedia/graphql/sample/RoutesConfiguration.kt @@ -1,10 +1,10 @@ package com.expedia.graphql.sample +import com.expedia.graphql.extensions.print import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.type.MapType import com.fasterxml.jackson.databind.type.TypeFactory import graphql.schema.GraphQLSchema -import graphql.schema.idl.SchemaPrinter import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -21,7 +21,6 @@ import reactor.core.publisher.Mono @Configuration class RoutesConfiguration( val schema: GraphQLSchema, - val schemaPrinter: SchemaPrinter, private val queryHandler: QueryHandler, private val objectMapper: ObjectMapper, @Value("classpath:/graphql-playground.html") private val playgroundHtml: Resource @@ -42,7 +41,7 @@ class RoutesConfiguration( @Bean fun sdlRoute() = router { GET("/sdl") { - ok().contentType(MediaType.TEXT_PLAIN).syncBody(schemaPrinter.print(schema)) + ok().contentType(MediaType.TEXT_PLAIN).syncBody(schema.print()) } } diff --git a/src/main/kotlin/com/expedia/graphql/directives/DeprecatedDirective.kt b/src/main/kotlin/com/expedia/graphql/directives/DeprecatedDirective.kt new file mode 100644 index 0000000000..92b2d42cb4 --- /dev/null +++ b/src/main/kotlin/com/expedia/graphql/directives/DeprecatedDirective.kt @@ -0,0 +1,28 @@ +package com.expedia.graphql.directives + +import graphql.Scalars +import graphql.introspection.Introspection +import graphql.schema.GraphQLArgument +import graphql.schema.GraphQLDirective +import graphql.schema.GraphQLNonNull + +const val DEPRECATED_DIRECTIVE_NAME = "deprecated" + +private val DefaultDeprecatedArgument: GraphQLArgument = GraphQLArgument.newArgument() + .name("reason") + .type(GraphQLNonNull.nonNull(Scalars.GraphQLString)) + .defaultValue("No longer supported") + .build() + +internal val DeprecatedDirective: GraphQLDirective = GraphQLDirective.newDirective() + .name(DEPRECATED_DIRECTIVE_NAME) + .description("Marks the target field/enum value as deprecated") + .argument(DefaultDeprecatedArgument) + .validLocations(Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.ENUM_VALUE) + .build() + +internal fun deprecatedDirectiveWithReason(reason: String): GraphQLDirective = DeprecatedDirective.transform { directive -> + directive.argument(DefaultDeprecatedArgument.transform { arg -> + arg.value(reason) + }) +} diff --git a/src/main/kotlin/com/expedia/graphql/directives/KotlinDirectiveWiringFactory.kt b/src/main/kotlin/com/expedia/graphql/directives/KotlinDirectiveWiringFactory.kt index 025391f1fd..9fb6bd4f96 100644 --- a/src/main/kotlin/com/expedia/graphql/directives/KotlinDirectiveWiringFactory.kt +++ b/src/main/kotlin/com/expedia/graphql/directives/KotlinDirectiveWiringFactory.kt @@ -9,6 +9,11 @@ import graphql.schema.GraphQLDirectiveContainer import graphql.schema.GraphQLFieldDefinition import graphql.schema.GraphQLType +/** + * Default no-op wiring for deprecated directive. + */ +private val defaultDeprecatedWiring = object : KotlinSchemaDirectiveWiring {} + /** * Wiring factory that is used to provide the directives. */ @@ -66,10 +71,16 @@ open class KotlinDirectiveWiringFactory( return modifiedObject } - private fun discoverWiringProvider(directiveName: String, env: KotlinSchemaDirectiveEnvironment): KotlinSchemaDirectiveWiring? = - if (directiveName in manualWiring) { + private fun discoverWiringProvider(directiveName: String, env: KotlinSchemaDirectiveEnvironment): KotlinSchemaDirectiveWiring? { + var wiring = if (directiveName in manualWiring) { manualWiring[directiveName] } else { getSchemaDirectiveWiring(env) } + + if (null == wiring && DEPRECATED_DIRECTIVE_NAME == directiveName) { + wiring = defaultDeprecatedWiring + } + return wiring + } } diff --git a/src/main/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensions.kt b/src/main/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensions.kt new file mode 100644 index 0000000000..aca1774c1d --- /dev/null +++ b/src/main/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensions.kt @@ -0,0 +1,47 @@ +package com.expedia.graphql.extensions + +import com.expedia.graphql.directives.DeprecatedDirective +import graphql.Directives +import graphql.schema.GraphQLSchema +import graphql.schema.idl.SchemaPrinter + +/** + * Prints out SDL representation of a target schema. + * + * @param includeIntrospectionTypes boolean flag indicating whether SDL should include introspection types + * @param includeScalarTypes boolean flag indicating whether SDL should include custom schema scalars + * @param includeExtendedScalarTypes boolean flag indicating whether SDL should include extended scalars (e.g. Long) + * supported by graphql-java, if set will automatically also set the includeScalarTypes flag + * @param includeDefaultSchemaDefinition boolean flag indicating whether SDL should include schema definition if using + * default root type names + * @param includeDirectives boolean flag indicating whether SDL should include directive information + */ +fun GraphQLSchema.print( + includeIntrospectionTypes: Boolean = false, + includeScalarTypes: Boolean = true, + includeExtendedScalarTypes: Boolean = true, + includeDefaultSchemaDefinition: Boolean = true, + includeDirectives: Boolean = true +): String { + val schemaPrinter = SchemaPrinter( + SchemaPrinter.Options.defaultOptions() + .includeIntrospectionTypes(includeIntrospectionTypes) + .includeScalarTypes(includeScalarTypes || includeExtendedScalarTypes) + .includeExtendedScalarTypes(includeExtendedScalarTypes) + .includeSchemaDefintion(includeDefaultSchemaDefinition) + .includeDirectives(includeDirectives) + ) + + var schemaString = schemaPrinter.print(this) + if (includeDirectives) { + // graphql-java SchemaPrinter filters out common directives, below is a workaround to print default built-in directives + val defaultDirectives = arrayOf(Directives.IncludeDirective, Directives.SkipDirective, DeprecatedDirective) + val directivesToString = defaultDirectives.joinToString("\n\n") { directive -> """ + #${directive.description} + directive @${directive.name} on ${directive.validLocations().joinToString(" | ") { loc -> loc.name }} + """.trimIndent() + } + schemaString += "\n" + directivesToString + } + return schemaString +} diff --git a/src/main/kotlin/com/expedia/graphql/generator/state/SchemaGeneratorState.kt b/src/main/kotlin/com/expedia/graphql/generator/state/SchemaGeneratorState.kt index ccbcb5409e..c4d2bac9fc 100644 --- a/src/main/kotlin/com/expedia/graphql/generator/state/SchemaGeneratorState.kt +++ b/src/main/kotlin/com/expedia/graphql/generator/state/SchemaGeneratorState.kt @@ -1,5 +1,7 @@ package com.expedia.graphql.generator.state +import com.expedia.graphql.directives.DeprecatedDirective +import graphql.Directives import graphql.schema.GraphQLDirective import graphql.schema.GraphQLType @@ -9,4 +11,14 @@ internal class SchemaGeneratorState(supportedPackages: List) { val directives = mutableSetOf() fun getValidAdditionalTypes(): List = additionalTypes.filter { cache.doesNotContainGraphQLType(it) } + + init { + // NOTE: @include and @defer query directives are added by graphql-java by default + // adding them explicitly here to keep it consistent with missing deprecated directive + directives.add(Directives.IncludeDirective) + directives.add(Directives.SkipDirective) + + // graphql-kotlin default directives + directives.add(DeprecatedDirective) + } } diff --git a/src/main/kotlin/com/expedia/graphql/generator/types/EnumBuilder.kt b/src/main/kotlin/com/expedia/graphql/generator/types/EnumBuilder.kt index d72af4e904..2a7ea6f313 100644 --- a/src/main/kotlin/com/expedia/graphql/generator/types/EnumBuilder.kt +++ b/src/main/kotlin/com/expedia/graphql/generator/types/EnumBuilder.kt @@ -1,5 +1,6 @@ package com.expedia.graphql.generator.types +import com.expedia.graphql.directives.deprecatedDirectiveWithReason import com.expedia.graphql.generator.SchemaGenerator import com.expedia.graphql.generator.TypeBuilder import com.expedia.graphql.generator.extensions.getDeprecationReason @@ -40,8 +41,11 @@ internal class EnumBuilder(generator: SchemaGenerator) : TypeBuilder(generator) } valueBuilder.description(valueField.getGraphQLDescription()) - valueBuilder.deprecationReason(valueField.getDeprecationReason()) + valueField.getDeprecationReason()?.let { + valueBuilder.deprecationReason(it) + valueBuilder.withDirective(deprecatedDirectiveWithReason(it)) + } return config.hooks.onRewireGraphQLType(valueBuilder.build()).safeCast() } } diff --git a/src/main/kotlin/com/expedia/graphql/generator/types/FunctionBuilder.kt b/src/main/kotlin/com/expedia/graphql/generator/types/FunctionBuilder.kt index e449d10a93..f097233f6b 100644 --- a/src/main/kotlin/com/expedia/graphql/generator/types/FunctionBuilder.kt +++ b/src/main/kotlin/com/expedia/graphql/generator/types/FunctionBuilder.kt @@ -1,5 +1,6 @@ package com.expedia.graphql.generator.types +import com.expedia.graphql.directives.deprecatedDirectiveWithReason import com.expedia.graphql.exceptions.InvalidInputFieldTypeException import com.expedia.graphql.generator.SchemaGenerator import com.expedia.graphql.generator.TypeBuilder @@ -34,6 +35,7 @@ internal class FunctionBuilder(generator: SchemaGenerator) : TypeBuilder(generat fn.getDeprecationReason()?.let { builder.deprecate(it) + builder.withDirective(deprecatedDirectiveWithReason(it)) } generator.directives(fn).forEach { diff --git a/src/main/kotlin/com/expedia/graphql/generator/types/PropertyBuilder.kt b/src/main/kotlin/com/expedia/graphql/generator/types/PropertyBuilder.kt index 798ba7cf14..ccc8731541 100644 --- a/src/main/kotlin/com/expedia/graphql/generator/types/PropertyBuilder.kt +++ b/src/main/kotlin/com/expedia/graphql/generator/types/PropertyBuilder.kt @@ -1,5 +1,6 @@ package com.expedia.graphql.generator.types +import com.expedia.graphql.directives.deprecatedDirectiveWithReason import com.expedia.graphql.generator.SchemaGenerator import com.expedia.graphql.generator.TypeBuilder import com.expedia.graphql.generator.extensions.getPropertyDeprecationReason @@ -22,7 +23,11 @@ internal class PropertyBuilder(generator: SchemaGenerator) : TypeBuilder(generat .description(prop.getPropertyDescription(parentClass)) .name(prop.name) .type(propertyType) - .deprecate(prop.getPropertyDeprecationReason(parentClass)) + + prop.getPropertyDeprecationReason(parentClass)?.let { + fieldBuilder.deprecate(it) + fieldBuilder.withDirective(deprecatedDirectiveWithReason(it)) + } generator.directives(prop).forEach { fieldBuilder.withDirective(it) diff --git a/src/test/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensionsTest.kt b/src/test/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensionsTest.kt new file mode 100644 index 0000000000..c7bc3c0522 --- /dev/null +++ b/src/test/kotlin/com/expedia/graphql/extensions/GraphQLSchemaExtensionsTest.kt @@ -0,0 +1,230 @@ +package com.expedia.graphql.extensions + +import com.expedia.graphql.TopLevelObject +import com.expedia.graphql.annotations.GraphQLDescription +import com.expedia.graphql.annotations.GraphQLDirective +import com.expedia.graphql.annotations.GraphQLID +import com.expedia.graphql.annotations.GraphQLIgnore +import com.expedia.graphql.annotations.GraphQLName +import com.expedia.graphql.getTestSchemaConfigWithMockedDirectives +import com.expedia.graphql.testSchemaConfig +import com.expedia.graphql.toSchema +import graphql.introspection.Introspection +import graphql.schema.GraphQLSchema +import org.junit.jupiter.api.Test +import java.util.UUID +import kotlin.test.assertEquals + +@Suppress("Detekt.TrailingWhitespace", "Detekt.FunctionOnlyReturningConstant", "Detekt.UseDataClass", "Detekt.UnusedPrivateMember") +class GraphQLSchemaExtensionsTest { + + class SimpleQuery { + fun basic(msg: String) = msg + + fun nullable(msg: String?) = msg + } + + @Test + fun `verify print result of a simple schema`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(SimpleQuery())), config = testSchemaConfig) + + val sdl = schema.print(includeDirectives = false).trim() + val expected = """ + schema { + query: Query + } + + type Query { + basic(msg: String!): String! + nullable(msg: String): String + } + """.trimIndent() + assertEquals(expected, sdl) + } + + class RenamedQuery { + fun original(id: Int) = OriginalType(id) + } + + @GraphQLName("RenamedType") + class OriginalType( + val originalProperty: Int + ) + + @Test + fun `verify print result of a schema with renamed fields`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(RenamedQuery())), config = testSchemaConfig) + + val sdl = schema.print(includeDefaultSchemaDefinition = false, includeDirectives = false).trim() + val expected = """ + type Query { + original(id: Int!): RenamedType! + } + + type RenamedType { + originalProperty: Int! + } + """.trimIndent() + assertEquals(expected, sdl) + } + + class QueryWithId { + fun queryById(@GraphQLID id: String) = TypeWithId(id, "junit") + } + + class TypeWithId( + @GraphQLID + val id: String, + val name: String + ) + + @Test + fun `verify print result of a schema with GraphQL ID`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(QueryWithId())), config = testSchemaConfig) + + val sdl = schema.print(includeDefaultSchemaDefinition = false, includeDirectives = false).trim() + val expected = """ + type Query { + queryById(id: String!): TypeWithId! + } + + type TypeWithId { + id: ID! + name: String! + } + """.trimIndent() + assertEquals(expected, sdl) + } + + class QueryWithExcludedFields { + @GraphQLIgnore + fun notPartOfTheSchema() = "ignore me!" + + private fun privateFunction() = "ignored private function" + + fun visible(id: Int) = TypeWithExcludedFields(id, UUID.randomUUID().toString(), UUID.randomUUID().toString()) + } + + class TypeWithExcludedFields( + val id: Int, + @GraphQLIgnore + val hash: String, + private val secret: String + ) + + @Test + fun `verify print result of a schema with ignored elements`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(QueryWithExcludedFields())), config = testSchemaConfig) + + val sdl = schema.print(includeDefaultSchemaDefinition = false, includeDirectives = false).trim() + val expected = """ + type Query { + visible(id: Int!): TypeWithExcludedFields! + } + + type TypeWithExcludedFields { + id: Int! + } + """.trimIndent() + assertEquals(expected, sdl) + } + + class DocumentedQuery { + @GraphQLDescription("documented query") + fun documented(@GraphQLDescription("documented argument") id: Int) = DocumentedType(id) + } + + @GraphQLDescription("documented type") + class DocumentedType( + @GraphQLDescription("documented property") + val id: Int + ) + + @Test + fun `verify print result of a documented schema`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(DocumentedQuery())), config = testSchemaConfig) + + val sdl = schema.print(includeDefaultSchemaDefinition = false, includeDirectives = false).trim() + val expected = """ + #documented type + type DocumentedType { + #documented property + id: Int! + } + + type Query { + #documented query + documented( + #documented argument + id: Int! + ): DocumentedType! + } + """.trimIndent() + assertEquals(expected, sdl) + } + + @GraphQLDirective(locations = [Introspection.DirectiveLocation.FIELD_DEFINITION]) + internal annotation class CustomDirective + + class QueryWithDirectives { + fun echo(msg: String): String = msg + + @CustomDirective + fun withDirective() = "with directive" + + @CustomDirective + @Deprecated(message = "deprecated with directive") + fun deprecatedWithDirective() = "deprecated with directive" + + @Deprecated(message = "unsupported message") + fun deprecatedEcho(msg: String): String = msg + + @Deprecated(message = "unsupported message", replaceWith = ReplaceWith(expression = "echo()")) + fun deprecatedEchoWithReplacement(msg: String): String = msg + + fun simpleEnum(): SimpleEnum = SimpleEnum.ONE + } + + enum class SimpleEnum { + ONE, + @Deprecated("deprecated enum value") + TWO, + @Deprecated("deprecated enum value", replaceWith = ReplaceWith("ONE")) + THREE + } + + @Test + fun `verify print result of a schema with directives`() { + val schema: GraphQLSchema = toSchema(queries = listOf(TopLevelObject(QueryWithDirectives())), config = getTestSchemaConfigWithMockedDirectives()) + + val sdl = schema.print(includeDefaultSchemaDefinition = false).trim() + val expected = """ + directive @customDirective on FIELD_DEFINITION + + type Query { + deprecatedEcho(msg: String!): String! @deprecated(reason : "unsupported message") + deprecatedEchoWithReplacement(msg: String!): String! @deprecated(reason : "unsupported message, replace with echo()") + deprecatedWithDirective: String! @customDirective @deprecated(reason : "deprecated with directive") + echo(msg: String!): String! + simpleEnum: SimpleEnum! + withDirective: String! @customDirective + } + + enum SimpleEnum { + ONE + THREE @deprecated(reason : "deprecated enum value, replace with ONE") + TWO @deprecated(reason : "deprecated enum value") + } + + #Directs the executor to include this field or fragment only when the `if` argument is true + directive @include on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + + #Directs the executor to skip this field or fragment when the `if`'argument is true. + directive @skip on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + + #Marks the target field/enum value as deprecated + directive @deprecated on FIELD_DEFINITION | ENUM_VALUE + """.trimIndent() + assertEquals(expected, sdl) + } +} diff --git a/src/test/kotlin/com/expedia/graphql/generator/types/DirectiveBuilderTest.kt b/src/test/kotlin/com/expedia/graphql/generator/types/DirectiveBuilderTest.kt index 5e6bf7d0fb..572f9a164d 100644 --- a/src/test/kotlin/com/expedia/graphql/generator/types/DirectiveBuilderTest.kt +++ b/src/test/kotlin/com/expedia/graphql/generator/types/DirectiveBuilderTest.kt @@ -2,9 +2,11 @@ package com.expedia.graphql.generator.types import com.expedia.graphql.annotations.GraphQLDescription import com.expedia.graphql.annotations.GraphQLDirective +import com.expedia.graphql.directives.DeprecatedDirective import com.expedia.graphql.generator.SchemaGenerator import com.expedia.graphql.generator.extensions.isTrue import com.expedia.graphql.getTestSchemaConfigWithMockedDirectives +import graphql.Directives import org.junit.jupiter.api.Test import kotlin.reflect.KClass import kotlin.test.assertEquals @@ -87,9 +89,14 @@ internal class DirectiveBuilderTest { @Test fun `directives are not duplicated in the schema`() { + val initialCount = basicGenerator.state.directives.size + assertTrue(basicGenerator.state.directives.contains(Directives.IncludeDirective)) + assertTrue(basicGenerator.state.directives.contains(Directives.SkipDirective)) + assertTrue(basicGenerator.state.directives.contains(DeprecatedDirective)) + basicGenerator.directives(MyClass::simpleDirective) basicGenerator.directives(MyClass::simpleDirective) - assertEquals(1, basicGenerator.state.directives.size) + assertEquals(initialCount + 1, basicGenerator.state.directives.size) } @Test diff --git a/src/test/kotlin/com/expedia/graphql/generator/types/EnumBuilderTest.kt b/src/test/kotlin/com/expedia/graphql/generator/types/EnumBuilderTest.kt index 734aece602..bf88d562b6 100644 --- a/src/test/kotlin/com/expedia/graphql/generator/types/EnumBuilderTest.kt +++ b/src/test/kotlin/com/expedia/graphql/generator/types/EnumBuilderTest.kt @@ -93,13 +93,14 @@ internal class EnumBuilderTest : TypeTestHelper() { } @Test - fun `Enum values can have a single directive`() { + fun `Enum values can have directives`() { val gqlEnum = assertNotNull(builder.enumType(MyTestEnum::class)) - val directives = gqlEnum.values.last().directives - assertEquals(2, directives.size) - assertEquals("simpleDirective", directives.first().name) - assertEquals("customName", directives.last().name) + val enumValuesDirectives = gqlEnum.values.last().directives + assertEquals(3, enumValuesDirectives.size) + assertEquals("simpleDirective", enumValuesDirectives[0].name) + assertEquals("customName", enumValuesDirectives[1].name) + assertEquals("deprecated", enumValuesDirectives[2].name) } @Test diff --git a/src/test/kotlin/com/expedia/graphql/generator/types/FunctionBuilderTest.kt b/src/test/kotlin/com/expedia/graphql/generator/types/FunctionBuilderTest.kt index 4ebb49dde7..cc8ecb07a8 100644 --- a/src/test/kotlin/com/expedia/graphql/generator/types/FunctionBuilderTest.kt +++ b/src/test/kotlin/com/expedia/graphql/generator/types/FunctionBuilderTest.kt @@ -44,12 +44,14 @@ internal class FunctionBuilderTest : TypeTestHelper() { private class Happy { @GraphQLDescription("By bob") - @Deprecated("No more little trees >:|") @FunctionDirective("happy") fun littleTrees() = UUID.randomUUID().toString() fun paint(@GraphQLDescription("brush color") @ArgumentDirective("red") color: String) = color.reversed() + @Deprecated("Should paint instead") + fun sketch(tree: String) = tree + @Deprecated("No saw, just paint", replaceWith = ReplaceWith("paint")) fun saw(tree: String) = tree @@ -82,10 +84,14 @@ internal class FunctionBuilderTest : TypeTestHelper() { @Test fun `test deprecation`() { - val kFunction = Happy::littleTrees + val kFunction = Happy::sketch val result = builder.function(kFunction, "Query") assertTrue(result.isDeprecated) - assertEquals("No more little trees >:|", result.deprecationReason) + assertEquals("Should paint instead", result.deprecationReason) + + val fieldDirectives = result.directives + assertEquals(1, fieldDirectives.size) + assertEquals("deprecated", fieldDirectives.first().name) } @Test diff --git a/src/test/kotlin/com/expedia/graphql/generator/types/PropertyBuilderTest.kt b/src/test/kotlin/com/expedia/graphql/generator/types/PropertyBuilderTest.kt index cd055f0eb5..307341a1b9 100644 --- a/src/test/kotlin/com/expedia/graphql/generator/types/PropertyBuilderTest.kt +++ b/src/test/kotlin/com/expedia/graphql/generator/types/PropertyBuilderTest.kt @@ -33,11 +33,13 @@ internal class PropertyBuilderTest : TypeTestHelper() { internal annotation class PropertyDirective(val arg: String) private class ClassWithProperties { - @GraphQLDescription("The truth") - @Deprecated("It's not a lie") + @GraphQLDescription("It's not a lie") @PropertyDirective("trust me") lateinit var cake: String + @Deprecated("Only cake") + lateinit var dessert: String + @Deprecated("Healthy food is deprecated", replaceWith = ReplaceWith("cake")) lateinit var healthyFood: String @@ -68,11 +70,11 @@ internal class PropertyBuilderTest : TypeTestHelper() { @Test fun `Test deprecation`() { - val prop = ClassWithProperties::cake + val prop = ClassWithProperties::dessert val result = builder.property(prop, ClassWithProperties::class) assertTrue(result.isDeprecated) - assertEquals("It's not a lie", result.deprecationReason) + assertEquals("Only cake", result.deprecationReason) } @Test @@ -89,7 +91,7 @@ internal class PropertyBuilderTest : TypeTestHelper() { val prop = ClassWithProperties::cake val result = builder.property(prop, ClassWithProperties::class) - assertEquals("The truth", result.description) + assertEquals("It's not a lie", result.description) } @Test