From 2842c43ecdfef6c3b8a7d5999fb40753b7c94218 Mon Sep 17 00:00:00 2001 From: Marcos Paulo Belasco de Almeida Date: Fri, 14 Apr 2023 12:14:53 +0200 Subject: [PATCH] feat: add support for contact object (#208) * feat: add support for contact object Closes #88 * docs: add documentation on how to define contacts --- README.md | 4 ++++ .../restdocs/apispec/gradle/OpenApi3Task.kt | 9 +++++++- .../apispec/gradle/OpenApiExtension.kt | 9 ++++++++ .../gradle/RestdocsOpenApi3TaskTest.kt | 23 +++++++++++++++++++ .../apispec/openapi3/OpenApi3Generator.kt | 11 ++++++--- .../apispec/openapi3/OpenApi3GeneratorTest.kt | 5 +++- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0b9ba7fa..17010619 100644 --- a/README.md +++ b/README.md @@ -483,6 +483,10 @@ openapi3 { title = 'My API title' version = '1.0.1' format = 'yaml' + contact = { + name = 'John Doe' + email = 'john.doe@email.com' + } separatePublicApi = true outputFileNamePrefix = 'my-api-spec' oauth2SecuritySchemeDefinition = { diff --git a/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApi3Task.kt b/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApi3Task.kt index 4b290029..d19d396e 100644 --- a/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApi3Task.kt +++ b/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApi3Task.kt @@ -2,6 +2,7 @@ package com.epages.restdocs.apispec.gradle import com.epages.restdocs.apispec.model.ResourceModel import com.epages.restdocs.apispec.openapi3.OpenApi3Generator +import io.swagger.v3.oas.models.info.Contact import io.swagger.v3.oas.models.servers.Server import org.gradle.api.tasks.Input import org.gradle.api.tasks.Optional @@ -12,9 +13,14 @@ open class OpenApi3Task : OpenApiBaseTask() { @Optional var servers: List = listOf() + @Input + @Optional + var contact: Contact? = null + fun applyExtension(extension: OpenApi3Extension) { super.applyExtension(extension) servers = extension.servers + contact = extension.contact } override fun generateSpecification(resourceModels: List): String { @@ -26,7 +32,8 @@ open class OpenApi3Task : OpenApiBaseTask() { tagDescriptions = tagDescriptions, version = apiVersion, oauth2SecuritySchemeDefinition = oauth2SecuritySchemeDefinition, - format = format + format = format, + contact = contact ) } } diff --git a/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApiExtension.kt b/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApiExtension.kt index d508ff35..93d36eee 100644 --- a/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApiExtension.kt +++ b/restdocs-api-spec-gradle-plugin/src/main/kotlin/com/epages/restdocs/apispec/gradle/OpenApiExtension.kt @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.fasterxml.jackson.module.kotlin.readValue import groovy.lang.Closure +import io.swagger.v3.oas.models.info.Contact import io.swagger.v3.oas.models.servers.Server import org.gradle.api.Project import java.io.File @@ -63,6 +64,7 @@ open class OpenApi3Extension(project: Project) : OpenApiBaseExtension(project) { override var outputFileNamePrefix = "openapi3" private var _servers: List = mutableListOf(Server().apply { url = "http://localhost" }) + private var _contact: Contact? = null val servers get() = _servers @@ -79,6 +81,13 @@ open class OpenApi3Extension(project: Project) : OpenApiBaseExtension(project) { _servers = serversActions.map { project.configure(Server(), it) as Server } } + val contact + get() = _contact + + fun setContact(contact: Closure) { + _contact = project.configure(Contact(), contact) as Contact + } + companion object { const val name = "openapi3" } diff --git a/restdocs-api-spec-gradle-plugin/src/test/kotlin/com/epages/restdocs/apispec/gradle/RestdocsOpenApi3TaskTest.kt b/restdocs-api-spec-gradle-plugin/src/test/kotlin/com/epages/restdocs/apispec/gradle/RestdocsOpenApi3TaskTest.kt index 2f4ca7bf..fa7ef77d 100644 --- a/restdocs-api-spec-gradle-plugin/src/test/kotlin/com/epages/restdocs/apispec/gradle/RestdocsOpenApi3TaskTest.kt +++ b/restdocs-api-spec-gradle-plugin/src/test/kotlin/com/epages/restdocs/apispec/gradle/RestdocsOpenApi3TaskTest.kt @@ -37,6 +37,18 @@ class RestdocsOpenApi3TaskTest : RestdocsOpenApiTaskTestBase() { thenSingleServerContainedInOutput() } + @Test + fun `should run openapi task with contact`() { + givenBuildFileWithOpenApiClosureWithContact() + givenResourceSnippet() + + whenPluginExecuted() + + thenApiSpecTaskSuccessful() + thenOutputFileFound() + thenContactContainedInOutput() + } + @Test fun `should run openapi task with single server string`() { givenBuildFileWithOpenApiClosureWithSingleServerString() @@ -67,6 +79,12 @@ class RestdocsOpenApi3TaskTest : RestdocsOpenApiTaskTestBase() { } } + private fun thenContactContainedInOutput() { + with(outputFileContext()) { + then(read("info.contact.name")).isEqualTo("Test Contact") + } + } + private fun thenHeaderWithDefaultValuesContainedInOutput() { with(outputFileContext()) { then(read("paths./products/{id}.get.parameters[1].name")).isEqualTo("one") @@ -86,6 +104,10 @@ class RestdocsOpenApi3TaskTest : RestdocsOpenApiTaskTestBase() { givenBuildFileWithOpenApiClosure("server", """{ url = 'http://some.api' }""") } + fun givenBuildFileWithOpenApiClosureWithContact() { + givenBuildFileWithOpenApiClosure("contact", """{ name = 'Test Contact' }""") + } + override fun givenBuildFileWithOpenApiClosure() { givenBuildFileWithOpenApiClosure( "servers", @@ -136,6 +158,7 @@ class RestdocsOpenApi3TaskTest : RestdocsOpenApiTaskTestBase() { baseBuildFile() + """ openapi3 { servers = [ { url = "http://some.api" } ] + contact = { name = "Test Contact" } title = '$title' description = '$description' tagDescriptionsPropertiesFile = "tagDescriptions.yaml" diff --git a/restdocs-api-spec-openapi3-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3Generator.kt b/restdocs-api-spec-openapi3-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3Generator.kt index 4e812956..3481d151 100644 --- a/restdocs-api-spec-openapi3-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3Generator.kt +++ b/restdocs-api-spec-openapi3-generator/src/main/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3Generator.kt @@ -23,6 +23,7 @@ import io.swagger.v3.oas.models.PathItem import io.swagger.v3.oas.models.Paths import io.swagger.v3.oas.models.examples.Example import io.swagger.v3.oas.models.headers.Header +import io.swagger.v3.oas.models.info.Contact import io.swagger.v3.oas.models.info.Info import io.swagger.v3.oas.models.media.BooleanSchema import io.swagger.v3.oas.models.media.Content @@ -51,7 +52,8 @@ object OpenApi3Generator { description: String? = null, tagDescriptions: Map = emptyMap(), version: String = "1.0.0", - oauth2SecuritySchemeDefinition: Oauth2Configuration? = null + oauth2SecuritySchemeDefinition: Oauth2Configuration? = null, + contact: Contact? = null ): OpenAPI { return OpenAPI().apply { @@ -60,6 +62,7 @@ object OpenApi3Generator { this.title = title this.description = description this.version = version + this.contact = contact } this.tags( tagDescriptions.map { @@ -86,7 +89,8 @@ object OpenApi3Generator { tagDescriptions: Map = emptyMap(), version: String = "1.0.0", oauth2SecuritySchemeDefinition: Oauth2Configuration? = null, - format: String + format: String, + contact: Contact? = null ) = ApiSpecificationWriter.serialize( format, @@ -97,7 +101,8 @@ object OpenApi3Generator { description = description, tagDescriptions = tagDescriptions, version = version, - oauth2SecuritySchemeDefinition = oauth2SecuritySchemeDefinition + oauth2SecuritySchemeDefinition = oauth2SecuritySchemeDefinition, + contact = contact ) ) diff --git a/restdocs-api-spec-openapi3-generator/src/test/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3GeneratorTest.kt b/restdocs-api-spec-openapi3-generator/src/test/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3GeneratorTest.kt index cd669e55..dd3d83fe 100644 --- a/restdocs-api-spec-openapi3-generator/src/test/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3GeneratorTest.kt +++ b/restdocs-api-spec-openapi3-generator/src/test/kotlin/com/epages/restdocs/apispec/openapi3/OpenApi3GeneratorTest.kt @@ -18,6 +18,7 @@ import com.jayway.jsonpath.JsonPath import com.jayway.jsonpath.Option import io.swagger.parser.OpenAPIParser import io.swagger.parser.models.ParseOptions +import io.swagger.v3.oas.models.info.Contact import io.swagger.v3.oas.models.servers.Server import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test @@ -518,6 +519,7 @@ class OpenApi3GeneratorTest { then(openApiJsonPathContext.read("info.title")).isEqualTo("API") then(openApiJsonPathContext.read("info.description")).isEqualTo("API Description") then(openApiJsonPathContext.read("info.version")).isEqualTo("1.0.0") + then(openApiJsonPathContext.read("info.contact.name")).isEqualTo("Test Contact") } private fun thenTagFieldsPresent() { @@ -578,7 +580,8 @@ class OpenApi3GeneratorTest { ), format = "json", description = "API Description", - tagDescriptions = mapOf("tag1" to "tag1 description", "tag2" to "tag2 description") + tagDescriptions = mapOf("tag1" to "tag1 description", "tag2" to "tag2 description"), + contact = Contact().apply { name = "Test Contact" } ) println(openApiSpecJsonString)