Test openapi schema requestBody

This commit is contained in:
2021-03-15 02:01:39 +01:00
parent 9c88adbabd
commit 97b07fb424
12 changed files with 155 additions and 87 deletions

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.TextNode
import fr.dcproject.common.utils.getResource
import io.ktor.http.ContentType
import io.ktor.http.Url
import io.ktor.request.contentType
import io.ktor.request.httpMethod
@@ -11,14 +12,27 @@ import io.ktor.request.uri
import io.ktor.server.testing.TestApplicationResponse
import org.openapi4j.core.model.v3.OAI3
import org.openapi4j.parser.OpenApi3Parser
import org.openapi4j.parser.model.v3.OpenApi3
import org.openapi4j.parser.model.v3.Operation
import org.openapi4j.parser.model.v3.Schema
import org.openapi4j.schema.validator.ValidationContext
import org.openapi4j.schema.validator.ValidationData
import org.openapi4j.schema.validator.v3.SchemaValidator
import java.io.File
import kotlin.test.assertTrue
fun TestApplicationResponse.`And schema must be valid`(route: String? = null) {
OpenApi3Parser().parse(File("/openapi2.yaml".getResource().toURI()), true).let { api ->
fun Schema.validate(api: OpenApi3, toValidate: JsonNode) {
val validationContext: ValidationContext<OAI3> = ValidationContext(api.context)
val schemaValidator = SchemaValidator(validationContext, "", this.toNode())
val results = ValidationData<Unit>()
schemaValidator.validate(toValidate, results)
assertTrue(results.isValid, results.results().toString())
}
fun TestApplicationResponse.operation(route: String? = null, callback: Operation.(OpenApi3, String) -> Unit): Operation {
return OpenApi3Parser().parse(File("/openapi2.yaml".getResource().toURI()), true).let { api: OpenApi3 ->
val operation = call.request.httpMethod
val uri = route ?: "/" + Url(call.request.uri).encodedPath
val path = api.paths
@@ -28,38 +42,43 @@ fun TestApplicationResponse.`And schema must be valid`(route: String? = null) {
api.getPath(path)
?.getOperation(operation.value.toLowerCase())
?.apply {
val mediaType = call.request.contentType()
val status = call.response.status()
getResponse(status?.value?.toString() ?: error("HttpStatus not found"))
?.getContentMediaType(mediaType.toString())
?.schema?.let { schema ->
val validationContext: ValidationContext<OAI3> = ValidationContext(api.context)
val jsonNode: JsonNode = schema.toNode()
val schemaValidator = SchemaValidator(validationContext, "", jsonNode)
val results = ValidationData<Unit>()
val mapper = ObjectMapper()
schemaValidator.validate(mapper.readTree(content), results)
assertTrue(results.isValid, results.results().toString())
}
?: error("""No path found for "$operation $uri" for status ${status.value} with media type "$mediaType".""")
}
?.apply {
Url(call.request.uri).parameters.forEach { parameter: String, values: List<String> ->
getParametersIn(api.context, "query")
?.firstOrNull { it.name == parameter }?.schema?.let { schema ->
val validationContext: ValidationContext<OAI3> = ValidationContext(api.context)
val jsonNode: JsonNode = schema.toNode()
val schemaValidator = SchemaValidator(validationContext, "", jsonNode)
val params = ValidationData<Unit>()
schemaValidator.validate(TextNode(values.first()), params)
assertTrue(params.isValid, params.results().toString())
}
?: error("""No path found for "$operation $uri" for status "$parameter".""")
}
this.callback(api, uri)
}
?: error("""No path found for "$operation $uri".""")
}
}
fun TestApplicationResponse.`And the schema must be valid`(route: String? = null, contentType: ContentType? = ContentType.Application.Json) {
operation(route) { api, uri ->
/* Validate Response */
this.apply {
val status = call.response.status()
getResponse(status?.value?.toString() ?: error("HttpStatus not found"))
?.getContentMediaType(contentType.toString())
?.schema
?.validate(api, ObjectMapper().readTree(content))
?: error("""No path found for "$this $uri" for status ${status.value} with media type "$contentType".""")
}
/* Validate Request URL */
this.apply {
Url(call.request.uri).parameters.forEach { parameter: String, values: List<String> ->
getParametersIn(api.context, "query")
?.firstOrNull { it.name == parameter }?.schema
?.validate(api, TextNode(values.first()))
?: error("""No path found for "$this $uri" for status "$parameter".""")
}
}
}
}
/**
* Validate request body
*/
fun TestApplicationResponse.`And the schema request body must be valid`(body: String) {
operation { api, uri ->
requestBody
.getContentMediaType(call.request.contentType().toString())
.schema
.validate(api, ObjectMapper().readTree(body))
}
}