Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy-to-mavencentral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ jobs:
steps:
- name: GitHub 리포지토리 체크아웃
uses: actions/checkout@v6
- name: JDK 17 설치
- name: JDK 21 설치
uses: actions/setup-java@v5
with:
distribution: 'adopt'
java-version: '17'
java-version: '21'
- name: Gradle 애드온 준비하기
uses: gradle/gradle-build-action@v3
- name: 프로젝트 빌드
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pull-request-coverage-report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ jobs:
steps:
- name: GitHub 리포지토리 체크아웃
uses: actions/checkout@v6
- name: JDK 17 설치
- name: JDK 21 설치
uses: actions/setup-java@v5
with:
distribution: 'adopt'
java-version: '17'
java-version: '21'
- name: Gradle 애드온 준비하기
uses: gradle/gradle-build-action@v3
- name: 커버리지 측정 및 리포트 생성
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ It combines the advantages of both Swagger and RestDocs for efficient and intuit

## Installation and Getting Started
### Installation

This library requires `spring-restdocs-webtestclient` to be declared explicitly
in your project, as it is no longer transitively provided.

```kotlin
dependencies {
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
}
Comment thread
BGMSound marked this conversation as resolved.
Comment thread
BGMSound marked this conversation as resolved.
```

Add the following dependency to your `build.gradle.kts` file:
<br><br>
`MVC`
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ subprojects {
}
tasks {
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
withType<KotlinCompile> {
compilerOptions {
freeCompilerArgs.add("-Xjsr305=strict")
jvmTarget.set(JvmTarget.JVM_17)
jvmTarget.set(JvmTarget.JVM_21)
}
}
test {
Expand Down
5 changes: 2 additions & 3 deletions documentify-project/documentify-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
dependencies {
implementation(libs.spring.boot.starter.test)
implementation(libs.restdocs.api.spec)
implementation(libs.jackson.databind)
implementation(libs.jackson.datatype.jsr310)
compileOnly(libs.spring.restdocs.mockmvc)
compileOnly(libs.spring.boot.starter.test)
compileOnly(libs.spring.restdocs.webtestclient)
compileOnly(libs.spring.boot.starter.web)
compileOnly(libs.spring.boot.starter.webflux)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.github.bgmsound.documentify.core

import io.github.bgmsound.documentify.core.emitter.DocumentEmitter
import io.github.bgmsound.documentify.core.emitter.EmitterFactory
import io.github.bgmsound.documentify.core.environment.ApplicationContextEnvironment.Companion.applicationContextEnvironment
import io.github.bgmsound.documentify.core.environment.DocumentContextEnvironment
import io.github.bgmsound.documentify.core.environment.WebTestClientContextEnvironment.Companion.webTestClientEnvironment
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import org.springframework.context.ApplicationContext
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.context.WebApplicationContext

abstract class AbstractDocumentify {
protected lateinit var provider: RestDocumentationContextProvider
protected lateinit var environment: DocumentContextEnvironment
protected var customEmitter: DocumentEmitter? = null

fun documentation(
name: String,
specCustomizer: DocumentSpec.() -> Unit
): WebTestClient.BodyContentSpec {
val documentSpec = DocumentSpec(name).also { specCustomizer(it) }
val emitter = customEmitter ?: EmitterFactory.of(provider, documentSpec, environment)

return emitter.emit()
}

fun emitter(
customEmitter: DocumentEmitter
) {
this.customEmitter = customEmitter
}

fun webTestClient(
provider: RestDocumentationContextProvider,
webTestClient: WebTestClient
) {
this.provider = provider
environment = webTestClientEnvironment(provider, webTestClient)
}

fun applicationContext(
provider: RestDocumentationContextProvider,
applicationContext: ApplicationContext
) {
this.provider = provider
environment = applicationContextEnvironment(provider, applicationContext)
}

fun webApplicationContext(
provider: RestDocumentationContextProvider,
context: WebApplicationContext
) {
environment = applicationContextEnvironment(provider, context)
this.provider = provider
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package io.github.bgmsound.documentify.core.emitter
import com.epages.restdocs.apispec.ResourceDocumentation
import com.epages.restdocs.apispec.ResourceSnippetParameters
import com.epages.restdocs.apispec.Schema
import io.github.bgmsound.documentify.core.emitter.WebTestClientDocumentResult.Companion.validateWith
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.snippet.Snippet
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec

abstract class AbstractDocumentEmitter(
protected val provider: RestDocumentationContextProvider,
Expand All @@ -27,4 +29,16 @@ abstract class AbstractDocumentEmitter(
}
return ResourceDocumentation.resource(resourceBuilder.build())
}

override fun emit(): BodyContentSpec {
val validatableDocumentResponse = emitDocument()
emitAlternativeResponseDocument()
validatableDocumentResponse.validateWith(documentSpec.response)

return validatableDocumentResponse
}

abstract fun emitDocument(): BodyContentSpec

abstract fun emitAlternativeResponseDocument()
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package io.github.bgmsound.documentify.mvc.emitter
package io.github.bgmsound.documentify.core.emitter

import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/**")
class AlternativeMvcResponseDocumentController private constructor(
class AlternativeResponseDocumentController private constructor(
status: Int,
response: Any
) {
Expand Down Expand Up @@ -40,8 +46,8 @@ class AlternativeMvcResponseDocumentController private constructor(
fun new(
status: Int,
response: Any
): AlternativeMvcResponseDocumentController {
return AlternativeMvcResponseDocumentController(status, response)
): AlternativeResponseDocumentController {
return AlternativeResponseDocumentController(status, response)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
package io.github.bgmsound.documentify.core.emitter

interface DocumentEmitter
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec

interface DocumentEmitter {

fun emit(): BodyContentSpec

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.github.bgmsound.documentify.reactive.emitter
package io.github.bgmsound.documentify.core.emitter

import io.github.bgmsound.documentify.core.environment.DocumentContextEnvironment
import io.github.bgmsound.documentify.core.specification.schema.document.DocumentSpec
import io.github.bgmsound.documentify.reactive.ReactiveDocumentContextEnvironment
import org.springframework.restdocs.RestDocumentationContextProvider

object EmitterFactory {
fun of(
provider: RestDocumentationContextProvider,
documentSpec: DocumentSpec,
environment: ReactiveDocumentContextEnvironment
): ReactiveDocumentEmitter {
return WebTestClientReactiveDocumentEmitter(provider, documentSpec, environment)
environment: DocumentContextEnvironment
): DocumentEmitter {
return WebTestClientDocumentEmitter(provider, documentSpec, environment)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.github.bgmsound.documentify.reactive.emitter
package io.github.bgmsound.documentify.core.emitter


import io.github.bgmsound.documentify.core.environment.DocumentContextEnvironment
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.springframework.http.HttpMethod
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.operation.preprocess.Preprocessors.*
Expand All @@ -15,16 +15,16 @@ import org.springframework.test.web.reactive.server.WebTestClient.RequestBodySpe
import org.springframework.util.LinkedMultiValueMap
import org.springframework.util.MultiValueMap

class WebTestClientReactiveDocumentEmitter(
class WebTestClientDocumentEmitter(
provider: RestDocumentationContextProvider,
documentSpec: DocumentSpec,
environment: ReactiveDocumentContextEnvironment
) : AbstractReactiveDocumentEmitter(provider, documentSpec) {
private val webTestClient: WebTestClient = environment.buildWebTestClient()
environment: DocumentContextEnvironment
) : AbstractDocumentEmitter(provider, documentSpec) {
private val webTestClient: WebTestClient = environment.buildTestClient()
private val requestPreprocessors = environment.requestPreprocessors().toTypedArray()
private val responsePreprocessors = environment.responsePreprocessors().toTypedArray()

override suspend fun emitDocument(): BodyContentSpec {
override fun emitDocument(): BodyContentSpec {
val snippets = documentSpec.build()
val samplePathVariables = sampleAggregator.aggregate(documentSpec.request.pathVariables)
val sampleHeaders = sampleAggregator.aggregate(documentSpec.request.headers)
Expand Down Expand Up @@ -54,10 +54,10 @@ class WebTestClientReactiveDocumentEmitter(
)
}

override suspend fun emitAlternativeResponseDocument() {
override fun emitAlternativeResponseDocument() {
documentSpec.otherResponses.forEachIndexed { index, response ->
val sampleResponseFields = sampleAggregator.aggregate(response.fields)
val api = AlternativeReactiveResponseDocumentController.new(
val api = AlternativeResponseDocumentController.new(
response.statusCode,
sampleResponseFields
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package io.github.bgmsound.documentify.reactive.emitter
package io.github.bgmsound.documentify.core.emitter

import io.github.bgmsound.documentify.core.emitter.AbstractDocumentResult
import io.github.bgmsound.documentify.core.specification.schema.response.ResponseSpec
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.springframework.test.web.reactive.server.WebTestClient

class ReactiveDocumentResult(
class WebTestClientDocumentResult(
private val actualResponse: WebTestClient.BodyContentSpec
) : AbstractDocumentResult() {
override fun expect(jsonPath: String, matcher: Matcher<*>) {
Expand All @@ -19,7 +18,7 @@ class ReactiveDocumentResult(

companion object {
fun WebTestClient.BodyContentSpec.validateWith(responseSpec: ResponseSpec) {
ReactiveDocumentResult(this).validateWith(responseSpec)
WebTestClientDocumentResult(this).validateWith(responseSpec)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.bgmsound.documentify.reactive.environment
package io.github.bgmsound.documentify.core.environment

import io.github.bgmsound.documentify.reactive.AbstractReactiveDocumentContextEnvironment
import org.springframework.context.ApplicationContext
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
Expand All @@ -9,8 +8,8 @@ import org.springframework.test.web.reactive.server.WebTestClient
class ApplicationContextEnvironment private constructor(
private val provider: RestDocumentationContextProvider,
private val applicationContext: ApplicationContext
) : AbstractReactiveDocumentContextEnvironment() {
override fun buildWebTestClient(): WebTestClient {
) : AbstractDocumentContextEnvironment() {
override fun buildTestClient(): WebTestClient {
return WebTestClient
.bindToApplicationContext(applicationContext)
.configureClient()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.bgmsound.documentify.core.environment

import org.springframework.restdocs.operation.preprocess.OperationPreprocessor
import org.springframework.test.web.reactive.server.WebTestClient

interface DocumentContextEnvironment {

Expand All @@ -20,4 +21,6 @@ interface DocumentContextEnvironment {

fun responsePreprocessors(): List<OperationPreprocessor>

Comment thread
BGMSound marked this conversation as resolved.
fun buildTestClient(): WebTestClient

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package io.github.bgmsound.documentify.reactive.environment
package io.github.bgmsound.documentify.core.environment

import io.github.bgmsound.documentify.reactive.AbstractReactiveDocumentContextEnvironment
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
import org.springframework.test.web.reactive.server.WebTestClient

class WebTestClientContextEnvironment private constructor(
private val provider: RestDocumentationContextProvider,
private val webTestClient: WebTestClient
) : AbstractReactiveDocumentContextEnvironment() {
override fun buildWebTestClient(): WebTestClient {
) : AbstractDocumentContextEnvironment() {
override fun buildTestClient(): WebTestClient {
return webTestClient
.mutate()
.filter(WebTestClientRestDocumentation.documentationConfiguration(provider))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class ResourceSpec(
}

private fun randomSuffix(): String {
return (1..7).map {
return (1..5).map {
val char = ('0'..'9').random()
val number = ('a'..'z').random()
(0..1).random().let { if (it == 0) char else number }
Expand Down
6 changes: 1 addition & 5 deletions documentify-project/documentify-mvc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
dependencies {
compileOnly(libs.spring.boot.starter.web)
implementation(libs.spring.restdocs.mockmvc)
implementation(libs.spring.restdocs.restassured)
implementation(libs.restassured.mockmvc)
implementation(libs.spring.restdocs.webtestclient)
implementation(libs.restdocs.api.spec)
implementation(libs.restdocs.api.spec.mockmvc)
implementation(libs.restdocs.api.spec.restassured)
}

This file was deleted.

Loading
Loading