feat: auto auth detect (#299)
This commit is contained in:
@ -49,6 +49,12 @@ dependencies {
|
||||
testFixturesApi("io.ktor:ktor-serialization-gson:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-auth:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-auth-jwt:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-client:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
|
||||
testFixturesApi("dev.forst:ktor-api-key:2.1.0")
|
||||
|
||||
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import io.bkbn.kompendium.core.metadata.PutInfo
|
||||
import io.bkbn.kompendium.core.util.Helpers.addToSpec
|
||||
import io.bkbn.kompendium.core.util.SpecConfig
|
||||
import io.bkbn.kompendium.oas.path.Path
|
||||
import io.bkbn.kompendium.oas.path.PathOperation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.ktor.server.application.ApplicationCallPipeline
|
||||
import io.ktor.server.application.Hook
|
||||
@ -44,11 +45,13 @@ object NotarizedRoute {
|
||||
createConfiguration = ::Config
|
||||
) {
|
||||
|
||||
// This is required in order to introspect the route path
|
||||
// This is required in order to introspect the route path and authentication
|
||||
on(InstallHook) {
|
||||
val route = it as? Route ?: return@on
|
||||
val spec = application.attributes[KompendiumAttributes.openApiSpec]
|
||||
val routePath = route.calculateRoutePath()
|
||||
val authMethods = route.collectAuthMethods()
|
||||
pluginConfig.path?.addDefaultAuthMethods(authMethods)
|
||||
require(spec.paths[routePath] == null) {
|
||||
"""
|
||||
The specified path ${Parameter.Location.path} has already been documented!
|
||||
@ -76,4 +79,33 @@ object NotarizedRoute {
|
||||
}
|
||||
|
||||
private fun Route.calculateRoutePath() = toString().replace(Regex("/\\(.+\\)"), "")
|
||||
private fun Route.collectAuthMethods() = toString()
|
||||
.split("/")
|
||||
.filter { it.contains(Regex("\\(authenticate .*\\)")) }
|
||||
.map { it.replace("(authenticate ", "").replace(")", "") }
|
||||
.map { it.split(", ") }
|
||||
.flatten()
|
||||
|
||||
private fun Path.addDefaultAuthMethods(methods: List<String>) {
|
||||
get?.addDefaultAuthMethods(methods)
|
||||
put?.addDefaultAuthMethods(methods)
|
||||
post?.addDefaultAuthMethods(methods)
|
||||
delete?.addDefaultAuthMethods(methods)
|
||||
options?.addDefaultAuthMethods(methods)
|
||||
head?.addDefaultAuthMethods(methods)
|
||||
patch?.addDefaultAuthMethods(methods)
|
||||
trace?.addDefaultAuthMethods(methods)
|
||||
}
|
||||
|
||||
private fun PathOperation.addDefaultAuthMethods(methods: List<String>) {
|
||||
methods.forEach { m ->
|
||||
if (security == null || security?.all { s -> !s.containsKey(m) } == true) {
|
||||
if (security == null) {
|
||||
security = mutableListOf(mapOf(m to emptyList()))
|
||||
} else {
|
||||
security?.add(mapOf(m to emptyList()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ object Helpers {
|
||||
security = config.security
|
||||
?.map { (k, v) -> k to v }
|
||||
?.map { listOf(it).toMap() }
|
||||
?.toList(),
|
||||
?.toMutableList(),
|
||||
requestBody = when (this) {
|
||||
is MethodInfoWithRequest -> Request(
|
||||
description = this.request.description,
|
||||
|
@ -1,8 +1,11 @@
|
||||
package io.bkbn.kompendium.core
|
||||
|
||||
import dev.forst.ktor.apikey.apiKey
|
||||
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
|
||||
import io.bkbn.kompendium.core.util.TestModules.complexRequest
|
||||
import io.bkbn.kompendium.core.util.TestModules.customAuthConfig
|
||||
import io.bkbn.kompendium.core.util.TestModules.dateTimeString
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultAuthConfig
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultField
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultParameter
|
||||
import io.bkbn.kompendium.core.util.TestModules.exampleParams
|
||||
@ -16,6 +19,7 @@ import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponseMultipleImpls
|
||||
import io.bkbn.kompendium.core.util.TestModules.gnarlyGenericResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.headerParameter
|
||||
import io.bkbn.kompendium.core.util.TestModules.multipleAuthStrategies
|
||||
import io.bkbn.kompendium.core.util.TestModules.multipleExceptions
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedGenericCollection
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedGenericMultipleParamsCollection
|
||||
@ -46,7 +50,22 @@ import io.bkbn.kompendium.core.util.TestModules.simpleRecursive
|
||||
import io.bkbn.kompendium.core.util.TestModules.trailingSlash
|
||||
import io.bkbn.kompendium.core.util.TestModules.withOperationId
|
||||
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||
import io.bkbn.kompendium.oas.component.Components
|
||||
import io.bkbn.kompendium.oas.security.ApiKeyAuth
|
||||
import io.bkbn.kompendium.oas.security.BasicAuth
|
||||
import io.bkbn.kompendium.oas.security.BearerAuth
|
||||
import io.bkbn.kompendium.oas.security.OAuth
|
||||
import io.kotest.core.spec.style.DescribeSpec
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.auth.Authentication
|
||||
import io.ktor.server.auth.OAuthServerSettings
|
||||
import io.ktor.server.auth.UserIdPrincipal
|
||||
import io.ktor.server.auth.basic
|
||||
import io.ktor.server.auth.jwt.jwt
|
||||
import io.ktor.server.auth.oauth
|
||||
import kotlin.reflect.typeOf
|
||||
import java.time.Instant
|
||||
|
||||
@ -190,7 +209,7 @@ class KompendiumTest : DescribeSpec({
|
||||
// TODO Assess strategies here
|
||||
}
|
||||
it("Can serialize a recursive type") {
|
||||
openApiTestAllSerializers("T0042__simple_recursive.json") { simpleRecursive() }
|
||||
openApiTestAllSerializers("T0042__simple_recursive.json") { simpleRecursive() }
|
||||
}
|
||||
it("Nullable fields do not lead to doom") {
|
||||
openApiTestAllSerializers("T0036__nullable_fields.json") { nullableNestedObject() }
|
||||
@ -219,4 +238,100 @@ class KompendiumTest : DescribeSpec({
|
||||
describe("Free Form") {
|
||||
// todo Assess strategies here
|
||||
}
|
||||
describe("Authentication") {
|
||||
it("Can add a default auth config by default") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0045__default_auth_config.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
basic("basic") {
|
||||
realm = "Ktor Server"
|
||||
validate { UserIdPrincipal("Placeholder") }
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"basic" to BasicAuth()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { defaultAuthConfig() }
|
||||
}
|
||||
it("Can provide custom auth config with proper scopes") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0046__custom_auth_config.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
oauth("auth-oauth-google") {
|
||||
urlProvider = { "http://localhost:8080/callback" }
|
||||
providerLookup = {
|
||||
OAuthServerSettings.OAuth2ServerSettings(
|
||||
name = "google",
|
||||
authorizeUrl = "https://accounts.google.com/o/oauth2/auth",
|
||||
accessTokenUrl = "https://accounts.google.com/o/oauth2/token",
|
||||
requestMethod = HttpMethod.Post,
|
||||
clientId = "DUMMY_VAL",
|
||||
clientSecret = "DUMMY_VAL",
|
||||
defaultScopes = listOf("https://www.googleapis.com/auth/userinfo.profile"),
|
||||
extraTokenParameters = listOf("access_type" to "offline")
|
||||
)
|
||||
}
|
||||
client = HttpClient(CIO)
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"auth-oauth-google" to OAuth(
|
||||
flows = OAuth.Flows(
|
||||
implicit = OAuth.Flows.Implicit(
|
||||
authorizationUrl = "https://accounts.google.com/o/oauth2/auth",
|
||||
scopes = mapOf(
|
||||
"write:pets" to "modify pets in your account",
|
||||
"read:pets" to "read your pets"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { customAuthConfig() }
|
||||
}
|
||||
it("Can provide multiple authentication strategies") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0047__multiple_auth_strategies.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
apiKey("api-key") {
|
||||
headerName = "X-API-KEY"
|
||||
validate {
|
||||
UserIdPrincipal("Placeholder")
|
||||
}
|
||||
}
|
||||
jwt("jwt") {
|
||||
realm = "Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"jwt" to BearerAuth("JWT"),
|
||||
"api-key" to ApiKeyAuth(ApiKeyAuth.ApiKeyLocation.HEADER, "X-API-KEY")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { multipleAuthStrategies() }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -35,8 +35,10 @@ import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.routing.delete
|
||||
import io.ktor.server.routing.get
|
||||
@ -604,24 +606,68 @@ object TestModules {
|
||||
|
||||
fun Routing.simpleRecursive() = basicGetGenerator<ColumnSchema>()
|
||||
|
||||
private inline fun <reified T> Routing.basicGetGenerator(
|
||||
params: List<Parameter> = emptyList(),
|
||||
operationId: String? = null
|
||||
) {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
operationId?.let { operationId(it) }
|
||||
parameters = params
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<T>()
|
||||
fun Routing.defaultAuthConfig() {
|
||||
authenticate("basic") {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.customAuthConfig() {
|
||||
authenticate("auth-oauth-google") {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
security = mapOf(
|
||||
"auth-oauth-google" to listOf("read:pets")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.multipleAuthStrategies() {
|
||||
authenticate("jwt", "api-key") {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Routing.basicGetGenerator(
|
||||
params: List<Parameter> = emptyList(),
|
||||
operationId: String? = null
|
||||
) {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<T>(params, operationId)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Route.basicGetGenerator(
|
||||
params: List<Parameter> = emptyList(),
|
||||
operationId: String? = null
|
||||
) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
operationId?.let { operationId(it) }
|
||||
parameters = params
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<T>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
82
core/src/test/resources/T0045__default_auth_config.json
Normal file
82
core/src/test/resources/T0045__default_auth_config.json
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false,
|
||||
"security": [
|
||||
{
|
||||
"basic": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"basic": {
|
||||
"type": "http",
|
||||
"scheme": "basic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
92
core/src/test/resources/T0046__custom_auth_config.json
Normal file
92
core/src/test/resources/T0046__custom_auth_config.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false,
|
||||
"security": [
|
||||
{
|
||||
"auth-oauth-google": [
|
||||
"read:pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"auth-oauth-google": {
|
||||
"flows": {
|
||||
"implicit": {
|
||||
"authorizationUrl": "https://accounts.google.com/o/oauth2/auth",
|
||||
"scopes": {
|
||||
"write:pets": "modify pets in your account",
|
||||
"read:pets": "read your pets"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "oauth2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
91
core/src/test/resources/T0047__multiple_auth_strategies.json
Normal file
91
core/src/test/resources/T0047__multiple_auth_strategies.json
Normal file
@ -0,0 +1,91 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false,
|
||||
"security": [
|
||||
{
|
||||
"jwt": []
|
||||
},
|
||||
{
|
||||
"api-key": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"jwt": {
|
||||
"bearerFormat": "JWT",
|
||||
"type": "http",
|
||||
"scheme": "bearer"
|
||||
},
|
||||
"api-key": {
|
||||
"in": "header",
|
||||
"name": "X-API-KEY",
|
||||
"type": "apiKey"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -59,17 +59,17 @@ object TestHelpers {
|
||||
* and build a test ktor server to compare the expected output with the output found in the default
|
||||
* OpenAPI json endpoint. By default, this will run the same test with Gson, Kotlinx, and Jackson serializers
|
||||
* @param snapshotName The snapshot file to retrieve from the resources folder
|
||||
* @param moduleFunction Initializer for the application to allow tests to pass the required Ktor modules
|
||||
*/
|
||||
fun openApiTestAllSerializers(
|
||||
snapshotName: String,
|
||||
customTypes: Map<KType, JsonSchema> = emptyMap(),
|
||||
applicationSetup: Application.() -> Unit = { },
|
||||
specOverrides: OpenApiSpec.() -> OpenApiSpec = { this },
|
||||
routeUnderTest: Routing.() -> Unit
|
||||
) {
|
||||
openApiTest(snapshotName, SupportedSerializer.KOTLINX, routeUnderTest, applicationSetup, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.JACKSON, routeUnderTest, applicationSetup, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.GSON, routeUnderTest, applicationSetup, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.KOTLINX, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.JACKSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.GSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
}
|
||||
|
||||
private fun openApiTest(
|
||||
@ -77,11 +77,12 @@ object TestHelpers {
|
||||
serializer: SupportedSerializer,
|
||||
routeUnderTest: Routing.() -> Unit,
|
||||
applicationSetup: Application.() -> Unit,
|
||||
specOverrides: OpenApiSpec.() -> OpenApiSpec,
|
||||
typeOverrides: Map<KType, JsonSchema> = emptyMap()
|
||||
) = testApplication {
|
||||
install(NotarizedApplication()) {
|
||||
customTypes = typeOverrides
|
||||
spec = defaultSpec()
|
||||
spec = defaultSpec().specOverrides()
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
when (serializer) {
|
||||
|
Reference in New Issue
Block a user