From f31d7c0c2eb631866377f9d84018af99a43b091e Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Thu, 27 Mar 2025 22:39:50 +0900 Subject: [PATCH 01/12] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a54a73f..436684d 100644 --- a/README.md +++ b/README.md @@ -112,3 +112,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). From 5a9aed5a6fbebdad0305b1329dd622c3a067a40e Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Thu, 27 Mar 2025 22:42:49 +0900 Subject: [PATCH 02/12] Rename documentify plugin and update package structure --- build.gradle.kts | 4 ++-- .../build.gradle.kts | 2 +- .../bgmsound/documentify/gradle}/plugin/DocumentifyPlugin.kt | 2 +- .../gradle/plugin/extensions/DocumentifyExtension.kt | 4 ++++ .../documentify/plugin/extensions/DocumentifyExtension.kt | 4 ---- settings.gradle.kts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) rename documentify-project/{documentify-plugin => documentify-gradle-plugin}/build.gradle.kts (93%) rename documentify-project/{documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify => documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle}/plugin/DocumentifyPlugin.kt (85%) create mode 100644 documentify-project/documentify-gradle-plugin/src/main/kotlin/io/github/bgmsound/documentify/gradle/plugin/extensions/DocumentifyExtension.kt delete mode 100644 documentify-project/documentify-plugin/src/main/kotlin/io/github/bgmsound/documentify/plugin/extensions/DocumentifyExtension.kt 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-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-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/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") From 8501625c5b06683039b6ffdaff44fdd92f1cb382 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Sat, 29 Mar 2025 22:02:54 +0900 Subject: [PATCH 03/12] Update README.md --- README.md | 4 ++-- documentify-sample/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 436684d..02316ed 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,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) @@ -81,7 +81,7 @@ fun documentationGetApi() { 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}" 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 { From 2f064dd4e71ee4e0bae83d52d884f5cb1afe0d0e Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Wed, 2 Apr 2025 15:36:29 +0900 Subject: [PATCH 04/12] Update README.md --- README.md | 1 + gradle.properties | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 02316ed..2e5906a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # 📝 Documentify ![Latest Release](https://img.shields.io/github/v/release/BGMSound/documentify) [![Apache 2.0 license](https://img.shields.io/badge/License-APACHE%202.0-green.svg?logo=APACHE&style=flat)](https://opensource.org/licenses/Apache-2.0) +[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
Documentify allows easy and convenient creation of OpenAPI specification documents through Kotlin DSL, making users from the complexity of traditional RestDocs. It combines the advantages of both Swagger and RestDocs for efficient and intuitive document management. diff --git a/gradle.properties b/gradle.properties index f23c2a9..8d4c854 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.2.6 project.artifact=documentify project.description=Documentify is a tool to generate API documentation from source code. From a1c0115243d0a874800dcc98339db4fb5aa72b87 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Mon, 7 Apr 2025 13:44:05 +0900 Subject: [PATCH 05/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e5906a..d98d130 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # 📝 Documentify +[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org) ![Latest Release](https://img.shields.io/github/v/release/BGMSound/documentify) [![Apache 2.0 license](https://img.shields.io/badge/License-APACHE%202.0-green.svg?logo=APACHE&style=flat)](https://opensource.org/licenses/Apache-2.0) -[![Kotlin](https://img.shields.io/badge/kotlin-2.0.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
Documentify allows easy and convenient creation of OpenAPI specification documents through Kotlin DSL, making users from the complexity of traditional RestDocs. It combines the advantages of both Swagger and RestDocs for efficient and intuitive document management. From 5491cc96fbc8f79af83b1537bbc713cd0a65e4a0 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Mon, 7 Apr 2025 13:44:29 +0900 Subject: [PATCH 06/12] Rename objectMapper to codec in context environment classes --- .../environment/AbstractStandaloneContextEnvironment.kt | 6 +++--- .../core/environment/StandaloneContextEnvironment.kt | 2 +- .../mvc/environment/StandaloneMvcContextEnvironment.kt | 4 ++-- .../environment/StandaloneReactiveContextEnvironment.kt | 6 +++--- .../documentify/sample/mvc/documentation/SnakeSampleDocs.kt | 2 +- .../documentify/sample/reactive/SampleController.kt | 1 + .../sample/reactive/documentation/SnakeSampleDocs.kt | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) 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-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-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/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) } } From 2040bc9b3426b7cfb51fad0ecf8aa599907b7437 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Wed, 9 Apr 2025 15:08:09 +0900 Subject: [PATCH 07/12] Refactor alternative response document controller to simplify response handling --- ...lternativeMvcResponseDocumentController.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) 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..2f9e04c 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,36 @@ 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 = if (response is ResponseEntity<*>) { + response + } else 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 { From 2633b2f7df519f4a4ced1ec303daa6b0fdcf87c0 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Fri, 11 Apr 2025 15:08:29 +0900 Subject: [PATCH 08/12] Add example case for documentation API in README.md --- .github/workflows/deploy-to-mavencentral.yaml | 2 +- README.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) 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 d98d130..8161b23 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,24 @@ 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. From cf75e24fe7caa2d19443f7c580d86c6ef1bf81d5 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Mon, 5 May 2025 18:10:07 +0900 Subject: [PATCH 09/12] Refactor emitters to use DocumentSpecSampleAggregator --- .../core/emitter/AbstractDocumentEmitter.kt | 3 +- .../DefaultDocumentSpecSampleAggregator.kt | 52 +++++++++++++++++++ .../emitter/DocumentSpecSampleAggregator.kt | 9 ++++ .../bgmsound/documentify/mvc/Documentify.kt | 10 ++-- ...lternativeMvcResponseDocumentController.kt | 4 +- .../documentify/mvc/emitter/EmitterFactory.kt | 2 +- .../emitter/RestAssuredMvcDocumentEmitter.kt | 20 ++++--- .../documentify/reactive/Documentify.kt | 10 ++-- .../reactive/emitter/EmitterFactory.kt | 2 +- .../WebTestClientReactiveDocumentEmitter.kt | 18 ++++--- gradle.properties | 2 +- 11 files changed, 102 insertions(+), 30 deletions(-) create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentSpecSampleAggregator.kt 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..440d806 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,7 +10,8 @@ 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 ) { protected fun ResponseSpec.buildResource(index: Int): Snippet { val resourceBuilder = ResourceSnippetParameters.builder() diff --git a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt new file mode 100644 index 0000000..3a7e7c7 --- /dev/null +++ b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DefaultDocumentSpecSampleAggregator.kt @@ -0,0 +1,52 @@ +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 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.aggregateSample() + } + } + + private fun Field.aggregateSample(): Pair { + if (isIgnored()) { + throw IllegalStateException("can't associate ignored field $key") + } + if (!hasSample() && !canHaveChild()) { + throw IllegalStateException("Field $key must have sample or child fields") + } + return key to if (hasSample()) { + sample + } else { + if (childFields().isEmpty()) { + throw IllegalStateException("Field $key must have child fields") + } + val sample = childFields().associate { it.aggregateSample() } + if (isArray()) { + listOf(sample) + } else { + 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/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-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..6141899 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 @@ -15,14 +15,14 @@ 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 fun documentation( name: String, specCustomizer: DocumentSpec.() -> Unit ): ValidatableMockResponse { val documentSpec = DocumentSpec(name).also { specCustomizer(it) } - val emitter = EmitterFactory.createMvcEmitter(provider, documentSpec, documentContextEnvironment) + val emitter = EmitterFactory.of(provider, documentSpec, environment) return emitter.emit() } @@ -32,7 +32,7 @@ abstract class Documentify { mockMvc: MockMvc ) { this.provider = provider - documentContextEnvironment = mockMvcEnvironment(mockMvc) + environment = mockMvcEnvironment(mockMvc) } fun standalone( @@ -40,7 +40,7 @@ abstract class Documentify { standaloneContext: StandaloneMvcContextEnvironment ) { this.provider = provider - documentContextEnvironment = standaloneContext + environment = standaloneContext } fun standalone( @@ -71,7 +71,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/emitter/AlternativeMvcResponseDocumentController.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/AlternativeMvcResponseDocumentController.kt index 2f9e04c..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 @@ -9,9 +9,7 @@ class AlternativeMvcResponseDocumentController private constructor( status: Int, response: Any ) { - private val response = if (response is ResponseEntity<*>) { - response - } else ResponseEntity.status(status).body(response) + private val response = response as? ResponseEntity<*> ?: ResponseEntity.status(status).body(response) @GetMapping fun get(): Any { 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/RestAssuredMvcDocumentEmitter.kt b/documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt index fc0ba85..233f2cd 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 @@ -31,6 +31,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 +45,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() @@ -58,18 +63,19 @@ class RestAssuredMvcDocumentEmitter( 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() 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..ab55313 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 @@ -16,14 +16,14 @@ 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 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 = EmitterFactory.of(provider, documentSpec, environment) return emitter.emit() } @@ -33,7 +33,7 @@ abstract class Documentify { webTestClient: WebTestClient ) { this.provider = provider - documentContextEnvironment = webTestClientEnvironment(provider, webTestClient) + environment = webTestClientEnvironment(provider, webTestClient) } fun standalone( @@ -41,7 +41,7 @@ abstract class Documentify { standaloneContext: StandaloneReactiveContextEnvironment ) { this.provider = provider - documentContextEnvironment = standaloneContext + environment = standaloneContext } fun standalone( @@ -70,6 +70,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/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/WebTestClientReactiveDocumentEmitter.kt b/documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/WebTestClientReactiveDocumentEmitter.kt index 36df2ac..3e4e7ec 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 @@ -30,13 +30,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(uri(), 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) @@ -57,19 +61,21 @@ class WebTestClientReactiveDocumentEmitter( 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(uri(), samplePathVariables) .exchange() .expectStatus() .isEqualTo(response.statusCode) diff --git a/gradle.properties b/gradle.properties index 8d4c854..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.6 +project.version.id=1.3.5 project.artifact=documentify project.description=Documentify is a tool to generate API documentation from source code. From dbd5cbf88429bb2dfd8f7a995fe2fd77b24b72a6 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Tue, 6 May 2025 00:42:21 +0900 Subject: [PATCH 10/12] Refactor response validate logic and support custom document emitter --- .../core/emitter/AbstractDocumentEmitter.kt | 2 +- .../core/emitter/AbstractDocumentResult.kt | 48 +++++++++++++++++++ .../core/emitter/DocumentEmitter.kt | 3 ++ .../core/emitter/DocumentResult.kt | 9 ++++ .../core/emitter/JsonResultMatcher.kt | 10 ++++ .../emitter/SpecElementSampleAssociater.kt | 42 ---------------- .../bgmsound/documentify/mvc/Documentify.kt | 10 +++- .../mvc/ValidatableMockMvcResponseAdapter.kt | 6 +-- .../mvc/ValidatableMockResponse.kt | 8 ++++ .../mvc/emitter/AbstractMvcDocumentEmitter.kt | 6 ++- .../mvc/emitter/MvcDocumentResult.kt | 34 +++++++++++++ .../emitter/RestAssuredMvcDocumentEmitter.kt | 20 -------- .../documentify/reactive/Documentify.kt | 10 +++- .../AbstractReactiveDocumentEmitter.kt | 2 + .../emitter/ReactiveDocumentResult.kt | 33 +++++++++++++ .../WebTestClientReactiveDocumentEmitter.kt | 48 ++++++------------- 16 files changed, 187 insertions(+), 104 deletions(-) create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/AbstractDocumentResult.kt create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentEmitter.kt create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/DocumentResult.kt create mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/JsonResultMatcher.kt delete mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt create mode 100644 documentify-project/documentify-mvc/src/main/kotlin/io/github/bgmsound/documentify/mvc/emitter/MvcDocumentResult.kt create mode 100644 documentify-project/documentify-reactive/src/main/kotlin/io/github/bgmsound/documentify/reactive/emitter/ReactiveDocumentResult.kt 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 440d806..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 @@ -12,7 +12,7 @@ abstract class AbstractDocumentEmitter( protected val provider: RestDocumentationContextProvider, 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/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/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/emitter/SpecElementSampleAssociater.kt b/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt deleted file mode 100644 index 92a0244..0000000 --- a/documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/SpecElementSampleAssociater.kt +++ /dev/null @@ -1,42 +0,0 @@ -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 { - it.hasSample() || it.canHaveChild() || !it.isIgnored() - }.associate { - it.associatedSample() - } - } - - fun Field.associatedSample(): Pair { - if (isIgnored()) { - throw IllegalStateException("can't associate ignored field $key") - } - if (!hasSample() && !canHaveChild()) { - throw IllegalStateException("Field $key must have sample or child fields") - } - return key to if (hasSample()) { - sample - } else { - if (childFields().isEmpty()) { - throw IllegalStateException("Field $key must have child fields") - } - val sample = childFields().associate { it.associatedSample() } - if (isArray()) { - listOf(sample) - } else { - sample - } - } - } - - fun List.associatedSample(): Map { - return associate { - it.key to it.sample - } - } -} \ 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 6141899..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 @@ -16,17 +17,24 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver abstract class Documentify { private lateinit var provider: RestDocumentationContextProvider 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.of(provider, documentSpec, environment) + val emitter = customEmitter ?: EmitterFactory.of(provider, documentSpec, environment) return emitter.emit() } + fun emitter( + customEmitter: MvcDocumentEmitter + ) { + this.customEmitter = customEmitter + } + fun mockMvc( provider: RestDocumentationContextProvider, mockMvc: MockMvc 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/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 233f2cd..a291a61 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 @@ -2,8 +2,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 @@ -58,7 +56,6 @@ class RestAssuredMvcDocumentEmitter( .assertThat() .apply(documentResultHandler) .statusCode(documentSpec.response.statusCode) - .validateExpectPayload() } override fun emitAlternativeResponseDocument() { @@ -109,21 +106,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-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 ab55313..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 @@ -17,17 +18,24 @@ import org.springframework.web.reactive.result.method.HandlerMethodArgumentResol abstract class Documentify { private lateinit var provider: RestDocumentationContextProvider 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.of(provider, documentSpec, environment) + val emitter = customEmitter ?: EmitterFactory.of(provider, documentSpec, environment) return emitter.emit() } + fun emitter( + customEmitter: ReactiveDocumentEmitter + ) { + this.customEmitter = customEmitter + } + fun webTestClient( provider: RestDocumentationContextProvider, webTestClient: WebTestClient 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/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 3e4e7ec..1c6905a 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 @@ -2,8 +2,6 @@ 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 @@ -36,7 +34,7 @@ class WebTestClientReactiveDocumentEmitter( return webTestClient .method(method()) - .uri(uri(), samplePathVariables) + .uri(requestUri, samplePathVariables) .headers { headers -> headers.addAll(sampleHeaders.toMultiValueMap()) } @@ -56,7 +54,6 @@ class WebTestClientReactiveDocumentEmitter( *snippets.toTypedArray() ) ) - .validateExpectPayload() } override suspend fun emitAlternativeResponseDocument() { @@ -75,7 +72,7 @@ class WebTestClientReactiveDocumentEmitter( val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables) webTestClient .method(method()) - .uri(uri(), samplePathVariables) + .uri(requestUri, samplePathVariables) .exchange() .expectStatus() .isEqualTo(response.statusCode) @@ -92,6 +89,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()) { @@ -117,33 +126,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 - } } From 1833937539f3d31140a606f6698ea18421ea7eaf Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Tue, 6 May 2025 00:45:09 +0900 Subject: [PATCH 11/12] Optimize Imports --- .../documentify/mvc/emitter/RestAssuredMvcDocumentEmitter.kt | 3 --- .../reactive/emitter/WebTestClientReactiveDocumentEmitter.kt | 2 -- 2 files changed, 5 deletions(-) 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 a291a61..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,7 +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.specification.schema.Method import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec import io.github.bgmsound.documentify.mvc.MvcDocumentContextEnvironment @@ -10,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 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 1c6905a..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,11 +1,9 @@ package io.github.bgmsound.documentify.reactive.emitter -import io.github.bgmsound.documentify.core.emitter.FieldJsonMatcherAssociater.associatedMatchers 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.* From f46f6954ff05f5a50c61e876c376cf95ee623ae7 Mon Sep 17 00:00:00 2001 From: Gyumin Bae Date: Tue, 6 May 2025 00:45:52 +0900 Subject: [PATCH 12/12] Remove useless component --- .../emitter/FieldJsonMatcherAssociater.kt | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 documentify-project/documentify-core/src/main/kotlin/io/github/bgmsound/documentify/core/emitter/FieldJsonMatcherAssociater.kt 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