diff --git a/.github/workflows/deploy-to-mavencentral.yaml b/.github/workflows/deploy-to-mavencentral.yaml
index 8f93096..10347b9 100644
--- a/.github/workflows/deploy-to-mavencentral.yaml
+++ b/.github/workflows/deploy-to-mavencentral.yaml
@@ -11,7 +11,7 @@ on:
MAVEN_CENTRAL_PASSWORD:
required: true
jobs:
- publish-to-maven-central:
+ publish-to-mavencentral:
runs-on: ubuntu-latest
steps:
- name: GitHub 리포지토리 체크아웃
diff --git a/README.md b/README.md
index a54a73f..8161b23 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
# 📝 Documentify
+[](http://kotlinlang.org)

[](https://opensource.org/licenses/Apache-2.0)
@@ -35,7 +36,7 @@ fun setUp(provider: RestDocumentationContextProvider) {
```
You can also set up the test environment with an application context or an auto-configured MockMvc (or WebTestClient).
-`Mvc Example`
+`MVC Example`
```kotlin
webApplicationContext(provider, context)
mockMvc(provider, mockMvc)
@@ -77,11 +78,29 @@ fun documentationGetApi() {
}
```
+Additional validation of the mock response generated during the tests for document creation is also possible.
+```kotlin
+@Test
+fun documentationGetApi() {
+ documentation("test-get-api") {
+ information {
+ summary("test get api")
+ description("this is test get api")
+ tag("test")
+ }
+ requestLine(Method.GET, "/api/test/{path}")
+ responseBody {
+ field("testField", "test", "test")
+ }
+ }.expect(jsonPath("$testField").value("test"))
+}
+```
+
### Generate OpenAPI Specification
After setting up the test environment and writing the test code, run the test.
The OpenAPI specification document will be generated in the `build/generated-snippets` directory.
-First, apply documentify plugin to your `build.gradle.kts` file:
+First, apply documentify plugin to your `build.gradle.kts` file *(need gradle plugin portal)*:
```kotlin
plugins {
id("io.github.bgmsound.documentify") version "${version}"
@@ -112,3 +131,6 @@ you can also create Postman collection by running the following command:
## Documentify Development Story
If you want to check out the development story of Documentify, please refer to the [blog post](https://bgmsound.medium.com/documentify-선언형-rest-docs-dsl-제작기-0a09f651be2c).
+
+## License
+documentify is Open Source software released under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.html).
diff --git a/build.gradle.kts b/build.gradle.kts
index 33e39e7..a3babed 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -19,7 +19,7 @@ version = extra["project.version.id"] as String
val publicModulePathSet = setOf(
rootProject.projects.documentifyProject.documentifyCore.identityPath.path,
- rootProject.projects.documentifyProject.documentifyPlugin.identityPath.path,
+ rootProject.projects.documentifyProject.documentifyGradlePlugin.identityPath.path,
rootProject.projects.documentifyProject.documentifyMvc.identityPath.path,
rootProject.projects.documentifyProject.documentifyReactive.identityPath.path,
rootProject.projects.documentifyStarters.documentifyStarterMvc.identityPath.path,
@@ -67,7 +67,7 @@ subprojects {
configure {
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
- val artifactId = name.replace("-plugin", ".gradle.plugin")
+ val artifactId = name.replace("-gradle-plugin", ".gradle.plugin")
val projectGroup = property("project.group").toString()
val projectName = property("project.name").toString()
val projectVersion = property("project.version.id").toString()
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentEmitter.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentEmitter.kt
index 54f5037..b394cfd 100644
--- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentEmitter.kt
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentEmitter.kt
@@ -10,8 +10,9 @@ import org.springframework.restdocs.snippet.Snippet
abstract class AbstractDocumentEmitter(
protected val provider: RestDocumentationContextProvider,
- protected val documentSpec: DocumentSpec
-) {
+ protected val documentSpec: DocumentSpec,
+ protected val sampleAggregator: DocumentSpecSampleAggregator = DefaultDocumentSpecSampleAggregator
+) : DocumentEmitter {
protected fun ResponseSpec.buildResource(index: Int): Snippet {
val resourceBuilder = ResourceSnippetParameters.builder()
if (documentSpec.tags.isNotEmpty()) {
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentResult.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentResult.kt
new file mode 100644
index 0000000..1e54ae6
--- /dev/null
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentResult.kt
@@ -0,0 +1,48 @@
+package io.github.bgmsound.documentify.core.emitter
+
+import io.github.bgmsound.documentify.core.specification.element.field.Field
+import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
+
+abstract class AbstractDocumentResult : DocumentResult {
+ abstract fun validateJsonPath(jsonResultMatcher: JsonResultMatcher)
+
+ override fun validateWith(responseSpec: ResponseSpec) {
+ val matchers = aggregateMatchers(responseSpec.fields)
+ if (matchers.isEmpty()) {
+ return
+ }
+ matchers.forEach { matcher ->
+ validateJsonPath(matcher)
+ }
+ }
+
+ private fun aggregateMatchers(fields: List): List {
+ return fields.filter {
+ it.hasSample() || it.canHaveChild() || !it.isIgnored()
+ }.flatMap {
+ it.aggregateMatchers()
+ }
+ }
+
+ private fun Field.aggregateMatchers(): List {
+ if (isIgnored()) {
+ return emptyList()
+ }
+ if (!hasSample() && !canHaveChild()) {
+ return emptyList()
+ }
+ val matchers = mutableListOf()
+ if (hasSample()) {
+ val jsonPath = StringBuilder("$.${path}").apply {
+ if (isArray()) {
+ append("[*]")
+ }
+ }.toString().replace("[]", "[*]")
+ matchers.add(JsonResultMatcher.of(jsonPath, sample))
+ } else if (childFields().isNotEmpty()) {
+ val childMatchers = aggregateMatchers(childFields())
+ matchers.addAll(childMatchers)
+ }
+ return matchers
+ }
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt
similarity index 54%
rename from documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt
rename to documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt
index 92a0244..3a7e7c7 100644
--- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt
@@ -3,16 +3,26 @@ package io.github.bgmsound.documentify.core.emitter
import io.github.bgmsound.documentify.core.specification.element.SpecElement
import io.github.bgmsound.documentify.core.specification.element.field.Field
-object SpecElementSampleAssociater {
- fun List.associatedFieldSample(): Map {
- return filter {
+object DefaultDocumentSpecSampleAggregator : DocumentSpecSampleAggregator {
+ @Suppress("UNCHECKED_CAST")
+ override fun aggregate(specElements: List): Map {
+ if (specElements.isEmpty()) {
+ return emptyMap()
+ }
+ if (!specElements.isField()) {
+ return specElements.associate {
+ it.key to it.sample
+ }
+ }
+ val fieldElements = specElements as List
+ return fieldElements.filter {
it.hasSample() || it.canHaveChild() || !it.isIgnored()
}.associate {
- it.associatedSample()
+ it.aggregateSample()
}
}
- fun Field.associatedSample(): Pair {
+ private fun Field.aggregateSample(): Pair {
if (isIgnored()) {
throw IllegalStateException("can't associate ignored field $key")
}
@@ -25,7 +35,7 @@ object SpecElementSampleAssociater {
if (childFields().isEmpty()) {
throw IllegalStateException("Field $key must have child fields")
}
- val sample = childFields().associate { it.associatedSample() }
+ val sample = childFields().associate { it.aggregateSample() }
if (isArray()) {
listOf(sample)
} else {
@@ -34,9 +44,9 @@ object SpecElementSampleAssociater {
}
}
- fun List.associatedSample(): Map {
- return associate {
- it.key to it.sample
+ private fun List.isField(): Boolean {
+ return all {
+ it is Field
}
}
}
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentEmitter.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentEmitter.kt
new file mode 100644
index 0000000..a1d909e
--- /dev/null
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentEmitter.kt
@@ -0,0 +1,3 @@
+package io.github.bgmsound.documentify.core.emitter
+
+interface DocumentEmitter
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentResult.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentResult.kt
new file mode 100644
index 0000000..a079c4f
--- /dev/null
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentResult.kt
@@ -0,0 +1,9 @@
+package io.github.bgmsound.documentify.core.emitter
+
+import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
+
+interface DocumentResult {
+
+ fun validateWith(responseSpec: ResponseSpec)
+
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentSpecSampleAggregator.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentSpecSampleAggregator.kt
new file mode 100644
index 0000000..43e4970
--- /dev/null
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentSpecSampleAggregator.kt
@@ -0,0 +1,9 @@
+package io.github.bgmsound.documentify.core.emitter
+
+import io.github.bgmsound.documentify.core.specification.element.SpecElement
+
+interface DocumentSpecSampleAggregator{
+
+ fun aggregate(specElements: List) : Map
+
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/FieldJsonMatcherAssociater.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/FieldJsonMatcherAssociater.kt
deleted file mode 100644
index 827b084..0000000
--- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/FieldJsonMatcherAssociater.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.github.bgmsound.documentify.core.emitter
-
-import io.github.bgmsound.documentify.core.specification.element.field.Field
-
-object FieldJsonMatcherAssociater {
- fun List.associatedMatchers(): List> {
- return filter {
- it.hasSample() || it.canHaveChild() || !it.isIgnored()
- }.flatMap {
- it.associatedMatchers()
- }
- }
-
- fun Field.associatedMatchers(): List> {
- if (isIgnored()) {
- return emptyList()
- }
- if (!hasSample() && !canHaveChild()) {
- return emptyList()
- }
- val matchers = mutableListOf>()
- if (hasSample()) {
- val jsonPath = StringBuilder("$.${path}").apply {
- if (isArray()) {
- append("[*]")
- }
- }.toString().replace("[]", "[*]")
- matchers.add(jsonPath to sample)
- } else if (childFields().isNotEmpty()) {
- val childMatchers = childFields().associatedMatchers()
- matchers.addAll(childMatchers)
- }
- return matchers
- }
-}
\ No newline at end of file
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/JsonResultMatcher.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/JsonResultMatcher.kt
new file mode 100644
index 0000000..ac59634
--- /dev/null
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/JsonResultMatcher.kt
@@ -0,0 +1,10 @@
+package io.github.bgmsound.documentify.core.emitter
+
+data class JsonResultMatcher(
+ val jsonPath: String,
+ val expectedValue: Any
+) {
+ companion object {
+ fun of(path: String, expectedValue: Any) = JsonResultMatcher(path, expectedValue)
+ }
+}
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/AbstractStandaloneContextEnvironment.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/AbstractStandaloneContextEnvironment.kt
index 375958a..a971f43 100644
--- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/AbstractStandaloneContextEnvironment.kt
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/AbstractStandaloneContextEnvironment.kt
@@ -6,10 +6,10 @@ import com.fasterxml.jackson.databind.ObjectMapper
abstract class AbstractStandaloneContextEnvironment> : StandaloneContextEnvironment, AbstractDocumentContextEnvironment() {
protected val controllers: MutableList = mutableListOf()
protected val controllerAdvices: MutableList = mutableListOf()
- protected var objectMapper: ObjectMapper? = null
+ protected var codec: ObjectMapper? = null
- override fun objectMapper(objectMapper: ObjectMapper): T {
- this.objectMapper = objectMapper
+ override fun codec(codec: ObjectMapper): T {
+ this.codec = codec
return this as T
}
diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/StandaloneContextEnvironment.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/StandaloneContextEnvironment.kt
index 56594ee..38123de 100644
--- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/StandaloneContextEnvironment.kt
+++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/environment/StandaloneContextEnvironment.kt
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
interface StandaloneContextEnvironment> : DocumentContextEnvironment {
- fun objectMapper(objectMapper: ObjectMapper): T
+ fun codec(codec: ObjectMapper): T
fun controller(controller: Any): T
diff --git a/documentify-project/documentify-plugin/build.gradle.kts b/documentify-project/documentify-gradle-plugin/build.gradle.kts
similarity index 93%
rename from documentify-project/documentify-plugin/build.gradle.kts
rename to documentify-project/documentify-gradle-plugin/build.gradle.kts
index eda82ef..5abdf12 100644
--- a/documentify-project/documentify-plugin/build.gradle.kts
+++ b/documentify-project/documentify-gradle-plugin/build.gradle.kts
@@ -10,7 +10,7 @@ gradlePlugin {
plugins {
register("documentify") {
id = "io.github.bgmsound.documentify"
- implementationClass = "io.github.bgmsound.documentify.plugin.DocumentifyPlugin"
+ implementationClass = "io.github.bgmsound.documentify.gradle.plugin.DocumentifyPlugin"
displayName = "Documentify"
description = "easy and powerful API documentation tool for spring restdocs"
}
diff --git a/documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/DocumentifyPlugin.kt b/documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/DocumentifyPlugin.kt
similarity index 85%
rename from documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/DocumentifyPlugin.kt
rename to documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/DocumentifyPlugin.kt
index 3b4c62a..4f84367 100644
--- a/documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/DocumentifyPlugin.kt
+++ b/documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/DocumentifyPlugin.kt
@@ -1,4 +1,4 @@
-package io.github.bgmsound.documentify.plugin
+package io.github.bgmsound.documentify.gradle.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
diff --git a/documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/extensions/DocumentifyExtension.kt b/documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/extensions/DocumentifyExtension.kt
new file mode 100644
index 0000000..fce1180
--- /dev/null
+++ b/documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/extensions/DocumentifyExtension.kt
@@ -0,0 +1,4 @@
+package io.github.bgmsound.documentify.gradle.plugin.extensions
+
+interface DocumentifyExtension {
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/Documentify.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/Documentify.kt
index 871d311..a514274 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/Documentify.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/Documentify.kt
@@ -2,6 +2,7 @@ package io.github.bgmsound.documentify.mvc
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.mvc.emitter.EmitterFactory
+import io.github.bgmsound.documentify.mvc.emitter.MvcDocumentEmitter
import io.github.bgmsound.documentify.mvc.environment.MockMvcContextEnvironment.Companion.mockMvcEnvironment
import io.github.bgmsound.documentify.mvc.environment.StandaloneMvcContextEnvironment
import io.github.bgmsound.documentify.mvc.environment.WebApplicationContextEnvironment.Companion.webApplicationContextEnvironment
@@ -15,24 +16,31 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver
@ExtendWith(RestDocumentationExtension::class)
abstract class Documentify {
private lateinit var provider: RestDocumentationContextProvider
- private lateinit var documentContextEnvironment: MvcDocumentContextEnvironment
+ private lateinit var environment: MvcDocumentContextEnvironment
+ private var customEmitter: MvcDocumentEmitter? = null
fun documentation(
name: String,
specCustomizer: DocumentSpec.() -> Unit
): ValidatableMockResponse {
val documentSpec = DocumentSpec(name).also { specCustomizer(it) }
- val emitter = EmitterFactory.createMvcEmitter(provider, documentSpec, documentContextEnvironment)
+ val emitter = customEmitter ?: EmitterFactory.of(provider, documentSpec, environment)
return emitter.emit()
}
+ fun emitter(
+ customEmitter: MvcDocumentEmitter
+ ) {
+ this.customEmitter = customEmitter
+ }
+
fun mockMvc(
provider: RestDocumentationContextProvider,
mockMvc: MockMvc
) {
this.provider = provider
- documentContextEnvironment = mockMvcEnvironment(mockMvc)
+ environment = mockMvcEnvironment(mockMvc)
}
fun standalone(
@@ -40,7 +48,7 @@ abstract class Documentify {
standaloneContext: StandaloneMvcContextEnvironment
) {
this.provider = provider
- documentContextEnvironment = standaloneContext
+ environment = standaloneContext
}
fun standalone(
@@ -71,7 +79,7 @@ abstract class Documentify {
provider: RestDocumentationContextProvider,
context: WebApplicationContext
) {
- documentContextEnvironment = webApplicationContextEnvironment(provider, context)
+ environment = webApplicationContextEnvironment(provider, context)
this.provider = provider
}
}
\ No newline at end of file
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockMvcResponseAdapter.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockMvcResponseAdapter.kt
index b836e6a..e996ec1 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockMvcResponseAdapter.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockMvcResponseAdapter.kt
@@ -14,17 +14,17 @@ class ValidatableMockMvcResponseAdapter private constructor(
return this
}
- fun status(status: HttpStatus): ValidatableMockResponse {
+ override fun status(status: HttpStatus): ValidatableMockResponse {
restAssuredMockResponse.statusCode(status.value())
return this
}
- fun apply(handler: ResultHandler, vararg additionalHandlers: ResultHandler): ValidatableMockResponse {
+ override fun apply(handler: ResultHandler, vararg additionalHandlers: ResultHandler): ValidatableMockResponse {
restAssuredMockResponse.apply(handler, *additionalHandlers)
return this
}
- fun assertThat(matcher: ResultMatcher): ValidatableMockResponse {
+ override fun assertThat(matcher: ResultMatcher): ValidatableMockResponse {
restAssuredMockResponse.assertThat(matcher)
return this
}
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockResponse.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockResponse.kt
index a0c5d84..5e436a5 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockResponse.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/ValidatableMockResponse.kt
@@ -1,9 +1,17 @@
package io.github.bgmsound.documentify.mvc
+import org.springframework.http.HttpStatus
+import org.springframework.test.web.servlet.ResultHandler
import org.springframework.test.web.servlet.ResultMatcher
interface ValidatableMockResponse {
fun expect(matcher: ResultMatcher): ValidatableMockResponse
+ fun status(status: HttpStatus): ValidatableMockResponse
+
+ fun apply(handler: ResultHandler, vararg additionalHandlers: ResultHandler): ValidatableMockResponse
+
+ fun assertThat(matcher: ResultMatcher): ValidatableMockResponse
+
}
\ No newline at end of file
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AbstractMvcDocumentEmitter.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AbstractMvcDocumentEmitter.kt
index f3ed1a8..903ebce 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AbstractMvcDocumentEmitter.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AbstractMvcDocumentEmitter.kt
@@ -4,6 +4,7 @@ import io.github.bgmsound.documentify.core.emitter.AbstractDocumentEmitter
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.mvc.ValidatableMockMvcResponseAdapter
import io.github.bgmsound.documentify.mvc.ValidatableMockResponse
+import io.github.bgmsound.documentify.mvc.emitter.MvcDocumentResult.Companion.validateWith
import io.restassured.module.mockmvc.response.ValidatableMockMvcResponse
import org.springframework.restdocs.RestDocumentationContextProvider
@@ -12,10 +13,11 @@ abstract class AbstractMvcDocumentEmitter(
documentSpec: DocumentSpec
) : AbstractDocumentEmitter(provider, documentSpec), MvcDocumentEmitter {
override fun emit(): ValidatableMockResponse {
- val mockResponseSpec = emitDocument()
+ val documentResult = ValidatableMockMvcResponseAdapter.of(emitDocument())
+ documentResult.validateWith(documentSpec.response)
emitAlternativeResponseDocument()
- return ValidatableMockMvcResponseAdapter.of(mockResponseSpec)
+ return documentResult
}
abstract fun emitDocument(): ValidatableMockMvcResponse
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AlternativeMvcResponseDocumentController.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AlternativeMvcResponseDocumentController.kt
index ff7871d..75d3476 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AlternativeMvcResponseDocumentController.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AlternativeMvcResponseDocumentController.kt
@@ -6,39 +6,34 @@ import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/**")
class AlternativeMvcResponseDocumentController private constructor(
- private val status: Int,
- private val response: Any
+ status: Int,
+ response: Any
) {
+ private val response = response as? ResponseEntity<*> ?: ResponseEntity.status(status).body(response)
+
@GetMapping
fun get(): Any {
- return response()
+ return response
}
@PostMapping
fun post(): Any {
- return response()
+ return response
}
@PutMapping
fun put(): Any {
- return response()
+ return response
}
@DeleteMapping
fun delete(): Any {
- return response()
+ return response
}
@PatchMapping
fun patch(): Any {
- return response()
- }
-
- private fun response(): Any {
- if (response is ResponseEntity<*>) {
- return response
- }
- return ResponseEntity.status(status).body(response)
+ return response
}
companion object {
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/EmitterFactory.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/EmitterFactory.kt
index 61a05f2..c1d0241 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/EmitterFactory.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/EmitterFactory.kt
@@ -5,7 +5,7 @@ import io.github.bgmsound.documentify.mvc.MvcDocumentContextEnvironment
import org.springframework.restdocs.RestDocumentationContextProvider
object EmitterFactory {
- fun createMvcEmitter(
+ fun of(
provider: RestDocumentationContextProvider,
documentSpec: DocumentSpec,
environment: MvcDocumentContextEnvironment
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/MvcDocumentResult.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/MvcDocumentResult.kt
new file mode 100644
index 0000000..b6dbefe
--- /dev/null
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/MvcDocumentResult.kt
@@ -0,0 +1,34 @@
+package io.github.bgmsound.documentify.mvc.emitter
+
+import io.github.bgmsound.documentify.core.emitter.AbstractDocumentResult
+import io.github.bgmsound.documentify.core.emitter.JsonResultMatcher
+import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
+import io.github.bgmsound.documentify.mvc.ValidatableMockResponse
+import org.hamcrest.Matchers
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
+
+class MvcDocumentResult(
+ private val actualResponse: ValidatableMockResponse
+) : AbstractDocumentResult() {
+ override fun validateJsonPath(jsonResultMatcher: JsonResultMatcher) {
+ val jsonPath = jsonResultMatcher.jsonPath
+ val value = jsonResultMatcher.expectedValue
+
+ if (jsonPath.endsWith("[*]")) {
+ if (value !is List<*>) {
+ throw IllegalArgumentException("sample value type must be List")
+ }
+ actualResponse.expect(jsonPath(jsonPath.substringBeforeLast("[*]")).value(Matchers.containsInAnyOrder(*value.toTypedArray())))
+ } else if (jsonPath.contains("[*]") && !jsonPath.endsWith("[*]")) {
+ actualResponse.expect(jsonPath(jsonPath).value(Matchers.hasItem(value)))
+ } else {
+ actualResponse.expect(jsonPath(jsonPath).value(value))
+ }
+ }
+
+ companion object {
+ fun ValidatableMockResponse.validateWith(responseSpec: ResponseSpec) {
+ MvcDocumentResult(this).validateWith(responseSpec)
+ }
+ }
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt
index fc0ba85..9a86e33 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt
@@ -1,9 +1,6 @@
package io.github.bgmsound.documentify.mvc.emitter
import com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document
-import io.github.bgmsound.documentify.core.emitter.FieldJsonMatcherAssociater.associatedMatchers
-import io.github.bgmsound.documentify.core.emitter.SpecElementSampleAssociater.associatedFieldSample
-import io.github.bgmsound.documentify.core.emitter.SpecElementSampleAssociater.associatedSample
import io.github.bgmsound.documentify.core.specification.schema.Method
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.mvc.MvcDocumentContextEnvironment
@@ -12,11 +9,9 @@ import io.restassured.module.mockmvc.RestAssuredMockMvc.given
import io.restassured.module.mockmvc.response.MockMvcResponse
import io.restassured.module.mockmvc.response.ValidatableMockMvcResponse
import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification
-import org.hamcrest.Matchers
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration
import org.springframework.restdocs.operation.preprocess.Preprocessors.*
-import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder
@@ -31,6 +26,11 @@ class RestAssuredMvcDocumentEmitter(
override fun emitDocument(): ValidatableMockMvcResponse {
val snippets = documentSpec.build()
+ val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables)
+ val sampleQueryParameters = sampleAggregator.aggregate(documentSpec.request.queryParameters)
+ val sampleHeaders = sampleAggregator.aggregate(documentSpec.request.headers)
+ val sampleFields = sampleAggregator.aggregate(documentSpec.request.fields)
+
val documentResultHandler = document(
documentSpec.name,
preprocessRequest(prettyPrint(), *requestPreprocessors),
@@ -40,10 +40,10 @@ class RestAssuredMvcDocumentEmitter(
val requestSpecification: MockMvcRequestSpecification = given().mockMvc(mockMvc)
val response = requestSpecification
.log().all()
- .pathParams(documentSpec.request.pathVariables.associatedSample())
- .queryParams(documentSpec.request.queryParameters.associatedSample())
- .headers(documentSpec.request.headers.associatedSample())
- .bodyIfExists(documentSpec.request.fields.associatedFieldSample())
+ .pathParams(samplePathVariables)
+ .queryParams(sampleQueryParameters)
+ .headers(sampleHeaders)
+ .bodyIfExists(sampleFields)
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.request()
@@ -53,23 +53,23 @@ class RestAssuredMvcDocumentEmitter(
.assertThat()
.apply(documentResultHandler)
.statusCode(documentSpec.response.statusCode)
- .validateExpectPayload()
}
override fun emitAlternativeResponseDocument() {
documentSpec.otherResponses.forEachIndexed { index, response ->
+ val sampleResponseFields = sampleAggregator.aggregate(response.fields)
val api = AlternativeMvcResponseDocumentController.new(
response.statusCode,
- response.fields.associatedFieldSample()
+ sampleResponseFields
)
val mockMvc = MockMvcBuilders
.standaloneSetup(api)
.apply(documentationConfiguration(provider))
.build()
val requestSpecification: MockMvcRequestSpecification = given().mockMvc(mockMvc)
-
+ val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables)
requestSpecification
- .pathParams(documentSpec.request.pathVariables.associatedSample())
+ .pathParams(samplePathVariables)
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.request()
@@ -103,21 +103,4 @@ class RestAssuredMvcDocumentEmitter(
Method.DELETE -> delete(documentSpec.request.url)
}
}
-
- private fun ValidatableMockMvcResponse.validateExpectPayload(): ValidatableMockMvcResponse {
- val matchers = documentSpec.response.fields.associatedMatchers()
- for ((key, value) in matchers) {
- if (key.endsWith("[*]")) {
- if (value !is List<*>) {
- throw IllegalArgumentException("sample value type must be List")
- }
- expect(jsonPath(key.substringBeforeLast("[*]")).value(Matchers.containsInAnyOrder(*value.toTypedArray())))
- } else if (key.contains("[*]") && !key.endsWith("[*]")) {
- expect(jsonPath(key).value(Matchers.hasItem(value)))
- } else {
- expect(jsonPath(key).value(value))
- }
- }
- return this
- }
}
\ No newline at end of file
diff --git a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/environment/StandaloneMvcContextEnvironment.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/environment/StandaloneMvcContextEnvironment.kt
index 970e2bd..d36d5d6 100644
--- a/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/environment/StandaloneMvcContextEnvironment.kt
+++ b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/environment/StandaloneMvcContextEnvironment.kt
@@ -36,8 +36,8 @@ class StandaloneMvcContextEnvironment private constructor(
.setControllerAdvice(*controllerAdvices.toTypedArray())
.setCustomArgumentResolvers(*argumentResolvers.toTypedArray())
.apply(documentationConfiguration(provider))
- .apply { if (objectMapper != null) {
- val objectMapper = objectMapper!!
+ .apply { if (codec != null) {
+ val objectMapper = codec!!
setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper))
}}
.build()
diff --git a/documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/extensions/DocumentifyExtension.kt b/documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/extensions/DocumentifyExtension.kt
deleted file mode 100644
index 3acc69e..0000000
--- a/documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/extensions/DocumentifyExtension.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.github.bgmsound.documentify.plugin.extensions
-
-interface DocumentifyExtension {
-}
\ No newline at end of file
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/Documentify.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/Documentify.kt
index 87d0a06..55582c1 100644
--- a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/Documentify.kt
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/Documentify.kt
@@ -2,6 +2,7 @@ package io.github.bgmsound.documentify.reactive
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.reactive.emitter.EmitterFactory
+import io.github.bgmsound.documentify.reactive.emitter.ReactiveDocumentEmitter
import io.github.bgmsound.documentify.reactive.environment.ApplicationContextEnvironment.Companion.applicationContextEnvironment
import io.github.bgmsound.documentify.reactive.environment.StandaloneReactiveContextEnvironment
import io.github.bgmsound.documentify.reactive.environment.StandaloneReactiveContextEnvironment.Companion.standaloneEnvironment
@@ -16,24 +17,31 @@ import org.springframework.web.reactive.result.method.HandlerMethodArgumentResol
@ExtendWith(RestDocumentationExtension::class)
abstract class Documentify {
private lateinit var provider: RestDocumentationContextProvider
- private lateinit var documentContextEnvironment: ReactiveDocumentContextEnvironment
+ private lateinit var environment: ReactiveDocumentContextEnvironment
+ private var customEmitter: ReactiveDocumentEmitter? = null
suspend fun documentation(
name: String,
specCustomizer: DocumentSpec.() -> Unit
): WebTestClient.BodyContentSpec {
val documentSpec = DocumentSpec(name).also { specCustomizer(it) }
- val emitter = EmitterFactory.createReactiveEmitter(provider, documentSpec, documentContextEnvironment)
+ val emitter = customEmitter ?: EmitterFactory.of(provider, documentSpec, environment)
return emitter.emit()
}
+ fun emitter(
+ customEmitter: ReactiveDocumentEmitter
+ ) {
+ this.customEmitter = customEmitter
+ }
+
fun webTestClient(
provider: RestDocumentationContextProvider,
webTestClient: WebTestClient
) {
this.provider = provider
- documentContextEnvironment = webTestClientEnvironment(provider, webTestClient)
+ environment = webTestClientEnvironment(provider, webTestClient)
}
fun standalone(
@@ -41,7 +49,7 @@ abstract class Documentify {
standaloneContext: StandaloneReactiveContextEnvironment
) {
this.provider = provider
- documentContextEnvironment = standaloneContext
+ environment = standaloneContext
}
fun standalone(
@@ -70,6 +78,6 @@ abstract class Documentify {
applicationContext: ApplicationContext
) {
this.provider = provider
- documentContextEnvironment = applicationContextEnvironment(provider, applicationContext)
+ environment = applicationContextEnvironment(provider, applicationContext)
}
}
\ No newline at end of file
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/AbstractReactiveDocumentEmitter.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/AbstractReactiveDocumentEmitter.kt
index b149b3f..6bd7e72 100644
--- a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/AbstractReactiveDocumentEmitter.kt
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/AbstractReactiveDocumentEmitter.kt
@@ -2,6 +2,7 @@ package io.github.bgmsound.documentify.reactive.emitter
import io.github.bgmsound.documentify.core.emitter.AbstractDocumentEmitter
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
+import io.github.bgmsound.documentify.reactive.emitter.ReactiveDocumentResult.Companion.validateWith
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec
@@ -13,6 +14,7 @@ abstract class AbstractReactiveDocumentEmitter(
override suspend fun emit(): BodyContentSpec {
val validatableDocumentResponse = emitDocument()
emitAlternativeResponseDocument()
+ validatableDocumentResponse.validateWith(documentSpec.response)
return validatableDocumentResponse
}
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/EmitterFactory.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/EmitterFactory.kt
index 01fb288..4587a82 100644
--- a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/EmitterFactory.kt
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/EmitterFactory.kt
@@ -5,7 +5,7 @@ import io.github.bgmsound.documentify.reactive.ReactiveDocumentContextEnvironmen
import org.springframework.restdocs.RestDocumentationContextProvider
object EmitterFactory {
- fun createReactiveEmitter(
+ fun of(
provider: RestDocumentationContextProvider,
documentSpec: DocumentSpec,
environment: ReactiveDocumentContextEnvironment
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/ReactiveDocumentResult.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/ReactiveDocumentResult.kt
new file mode 100644
index 0000000..76f9229
--- /dev/null
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/ReactiveDocumentResult.kt
@@ -0,0 +1,33 @@
+package io.github.bgmsound.documentify.reactive.emitter
+
+import io.github.bgmsound.documentify.core.emitter.AbstractDocumentResult
+import io.github.bgmsound.documentify.core.emitter.JsonResultMatcher
+import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
+import org.hamcrest.Matchers
+import org.springframework.test.web.reactive.server.WebTestClient
+
+class ReactiveDocumentResult(
+ private val actualResponse: WebTestClient.BodyContentSpec
+) : AbstractDocumentResult() {
+ override fun validateJsonPath(jsonResultMatcher: JsonResultMatcher) {
+ val jsonPath = jsonResultMatcher.jsonPath
+ val value = jsonResultMatcher.expectedValue
+
+ if (jsonPath.endsWith("[*]")) {
+ if (value !is List<*>) {
+ throw IllegalArgumentException("sample value type must be List")
+ }
+ actualResponse.jsonPath(jsonPath.substringBeforeLast("[*]")).value(Matchers.containsInAnyOrder(*value.toTypedArray()))
+ } else if (jsonPath.contains("[*]") && !jsonPath.endsWith("[*]")) {
+ actualResponse.jsonPath(jsonPath).value(Matchers.hasItem(value))
+ } else {
+ actualResponse.jsonPath(jsonPath).value(Matchers.equalToObject(value))
+ }
+ }
+
+ companion object {
+ fun WebTestClient.BodyContentSpec.validateWith(responseSpec: ResponseSpec) {
+ ReactiveDocumentResult(this).validateWith(responseSpec)
+ }
+ }
+}
\ No newline at end of file
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/WebTestClientReactiveDocumentEmitter.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/WebTestClientReactiveDocumentEmitter.kt
index 36df2ac..e0171fa 100644
--- a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/WebTestClientReactiveDocumentEmitter.kt
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/WebTestClientReactiveDocumentEmitter.kt
@@ -1,13 +1,9 @@
package io.github.bgmsound.documentify.reactive.emitter
-import io.github.bgmsound.documentify.core.emitter.FieldJsonMatcherAssociater.associatedMatchers
-import io.github.bgmsound.documentify.core.emitter.SpecElementSampleAssociater.associatedFieldSample
-import io.github.bgmsound.documentify.core.emitter.SpecElementSampleAssociater.associatedSample
import io.github.bgmsound.documentify.core.specification.schema.Method
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.reactive.ReactiveDocumentContextEnvironment
-import org.hamcrest.Matchers
import org.springframework.http.HttpMethod
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.operation.preprocess.Preprocessors.*
@@ -30,13 +26,17 @@ class WebTestClientReactiveDocumentEmitter(
override suspend fun emitDocument(): BodyContentSpec {
val snippets = documentSpec.build()
+ val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables)
+ val sampleHeaders = sampleAggregator.aggregate(documentSpec.request.headers)
+ val sampleFields = sampleAggregator.aggregate(documentSpec.request.fields)
+
return webTestClient
.method(method())
- .uri(uri(), documentSpec.request.pathVariables.associatedSample())
+ .uri(requestUri, samplePathVariables)
.headers { headers ->
- headers.addAll(documentSpec.request.headers.associatedSample().toMultiValueMap())
+ headers.addAll(sampleHeaders.toMultiValueMap())
}
- .bodyIfExist(documentSpec.request.fields.associatedSample())
+ .bodyIfExist(sampleFields)
.exchange()
.expectStatus()
.isEqualTo(documentSpec.response.statusCode)
@@ -52,24 +52,25 @@ class WebTestClientReactiveDocumentEmitter(
*snippets.toTypedArray()
)
)
- .validateExpectPayload()
}
override suspend fun emitAlternativeResponseDocument() {
documentSpec.otherResponses.forEachIndexed { index, response ->
+ val sampleResponseFields = sampleAggregator.aggregate(response.fields)
val api = AlternativeReactiveResponseDocumentController.new(
response.statusCode,
- response.fields.associatedFieldSample()
+ sampleResponseFields
)
val webTestClient = WebTestClient
.bindToController(api)
.configureClient()
.filter(WebTestClientRestDocumentation.documentationConfiguration(provider))
.build()
+
+ val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables)
webTestClient
.method(method())
- .uri(uri(), documentSpec.request.pathVariables.associatedSample())
- .bodyIfExist(documentSpec.request.fields.associatedSample())
+ .uri(requestUri, samplePathVariables)
.exchange()
.expectStatus()
.isEqualTo(response.statusCode)
@@ -86,6 +87,18 @@ class WebTestClientReactiveDocumentEmitter(
}
}
+ private val requestUri get(): String {
+ return StringBuilder().apply {
+ append(documentSpec.request.url)
+ if (documentSpec.request.queryParameters.isNotEmpty()) {
+ append("?")
+ append(documentSpec.request.queryParameters.joinToString("&") { parameter ->
+ "${parameter.key}=${parameter.sample}"
+ })
+ }
+ }.toString()
+ }
+
private fun RequestBodySpec.bodyIfExist(
fields: Map,
): WebTestClient.RequestHeadersSpec<*> = if (fields.isEmpty()) {
@@ -111,33 +124,4 @@ class WebTestClientReactiveDocumentEmitter(
}
return linkedMultiValueMap
}
-
- private fun uri(): String {
- return StringBuilder().apply {
- append(documentSpec.request.url)
- if (documentSpec.request.queryParameters.isNotEmpty()) {
- append("?")
- append(documentSpec.request.queryParameters.joinToString("&") { parameter ->
- "${parameter.key}=${parameter.sample}"
- })
- }
- }.toString()
- }
-
- private fun BodyContentSpec.validateExpectPayload(): BodyContentSpec {
- val matchers = documentSpec.response.fields.associatedMatchers()
- for ((key, value) in matchers) {
- if (key.endsWith("[*]")) {
- if (value !is List<*>) {
- throw IllegalArgumentException("sample value type must be List")
- }
- jsonPath(key.substringBeforeLast("[*]")).value(Matchers.containsInAnyOrder(*value.toTypedArray()))
- } else if (key.contains("[*]") && !key.endsWith("[*]")) {
- jsonPath(key).value(Matchers.hasItem(value))
- } else {
- jsonPath(key).value(Matchers.equalToObject(value))
- }
- }
- return this
- }
}
diff --git a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/environment/StandaloneReactiveContextEnvironment.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/environment/StandaloneReactiveContextEnvironment.kt
index 9fc3e5f..6b9220d 100644
--- a/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/environment/StandaloneReactiveContextEnvironment.kt
+++ b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/environment/StandaloneReactiveContextEnvironment.kt
@@ -40,13 +40,13 @@ class StandaloneReactiveContextEnvironment private constructor(
.argumentResolvers { configurer ->
configurer.addCustomResolver(*argumentResolvers.toTypedArray())
}
- .httpMessageCodecs { configurer -> if (objectMapper != null) {
- val objectMapper = objectMapper!!
+ .httpMessageCodecs { configurer -> if (codec != null) {
+ val objectMapper = codec!!
configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON))
configurer.defaultCodecs().jackson2JsonEncoder(Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON))
}}
.configureClient()
- .include(objectMapper)
+ .include(codec)
.filter(WebTestClientRestDocumentation.documentationConfiguration(provider))
.build()
}
diff --git a/documentify-sample/build.gradle.kts b/documentify-sample/build.gradle.kts
index 40938e6..a1e2c2d 100644
--- a/documentify-sample/build.gradle.kts
+++ b/documentify-sample/build.gradle.kts
@@ -1,5 +1,5 @@
plugins {
- id("io.github.bgmsound.documentify") version "1.2.4" apply false
+ id("io.github.bgmsound.documentify") version "1.2.5" apply false
}
subprojects {
diff --git a/documentify-sample/mvc-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/mvc/documentation/SnakeSampleDocs.kt b/documentify-sample/mvc-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/mvc/documentation/SnakeSampleDocs.kt
index a1394f1..c8e0a58 100644
--- a/documentify-sample/mvc-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/mvc/documentation/SnakeSampleDocs.kt
+++ b/documentify-sample/mvc-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/mvc/documentation/SnakeSampleDocs.kt
@@ -22,7 +22,7 @@ class SnakeSampleDocs : Documentify() {
fun setUp(provider: RestDocumentationContextProvider) {
standalone(provider) {
controller(api)
- objectMapper(objectMapper)
+ codec(objectMapper)
}
}
diff --git a/documentify-sample/reactive-sample/src/main/kotlin/io/github/bgmsound/documentify/sample/reactive/SampleController.kt b/documentify-sample/reactive-sample/src/main/kotlin/io/github/bgmsound/documentify/sample/reactive/SampleController.kt
index ae9f52d..16a8e85 100644
--- a/documentify-sample/reactive-sample/src/main/kotlin/io/github/bgmsound/documentify/sample/reactive/SampleController.kt
+++ b/documentify-sample/reactive-sample/src/main/kotlin/io/github/bgmsound/documentify/sample/reactive/SampleController.kt
@@ -14,6 +14,7 @@ class SampleController {
@PathVariable("integerField") integerField: Int,
@RequestParam("stringField") stringField: String
): SampleResponse {
+ "asfd"
return Mono.just(SampleResponse(integerField, stringField)).awaitFirst()
}
diff --git a/documentify-sample/reactive-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/reactive/documentation/SnakeSampleDocs.kt b/documentify-sample/reactive-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/reactive/documentation/SnakeSampleDocs.kt
index 02bdc66..54814c3 100644
--- a/documentify-sample/reactive-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/reactive/documentation/SnakeSampleDocs.kt
+++ b/documentify-sample/reactive-sample/src/test/kotlin/io/github/bgmsound/documentify/sample/reactive/documentation/SnakeSampleDocs.kt
@@ -24,7 +24,7 @@ class SnakeSampleDocs : Documentify() {
fun setUp(provider: RestDocumentationContextProvider) {
standalone(provider) {
controller(api)
- objectMapper(objectMapper)
+ codec(objectMapper)
}
}
diff --git a/gradle.properties b/gradle.properties
index f23c2a9..669118d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
project.name=documentify
project.group=io.github.bgmsound
-project.version.id=1.2.5
+project.version.id=1.3.5
project.artifact=documentify
project.description=Documentify is a tool to generate API documentation from source code.
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 0079e46..9f75a59 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -13,7 +13,7 @@ plugins {
include("documentify-project")
include("documentify-project:documentify-core")
-include("documentify-project:documentify-plugin")
+include("documentify-project:documentify-gradle-plugin")
include("documentify-project:documentify-mvc")
include("documentify-project:documentify-reactive")
include("documentify-sample")