now detects trailing slashes, if somewhat brittle (#8)
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
## [0.0.4] - April 14th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Added fix to route selector matching that accounts for trailing slash selection
|
||||||
|
|
||||||
## [0.0.3] - April 13th, 2021
|
## [0.0.3] - April 13th, 2021
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Backbone
|
# Kompendium
|
||||||
project.version=0.0.3
|
project.version=0.0.4
|
||||||
# Kotlin
|
# Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
# Gradle
|
# Gradle
|
||||||
|
@ -13,7 +13,11 @@ object Helpers {
|
|||||||
is RootRouteSelector -> tail
|
is RootRouteSelector -> tail
|
||||||
is PathSegmentParameterRouteSelector -> parent?.calculatePath("/$selector$tail") ?: "/{$selector}$tail"
|
is PathSegmentParameterRouteSelector -> parent?.calculatePath("/$selector$tail") ?: "/{$selector}$tail"
|
||||||
is PathSegmentConstantRouteSelector -> parent?.calculatePath("/$selector$tail") ?: "/$selector$tail"
|
is PathSegmentConstantRouteSelector -> parent?.calculatePath("/$selector$tail") ?: "/$selector$tail"
|
||||||
else -> error("unknown selector type $selector")
|
else -> when (selector.javaClass.simpleName) {
|
||||||
|
// dumb ass workaround to this object being internal to ktor
|
||||||
|
"TrailingSlashRouteSelector" -> parent?.calculatePath("$tail/") ?: "$tail/"
|
||||||
|
else -> error("unknown selector type $selector")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <K, V> MutableMap<K, V>.putPairIfAbsent(pair: Pair<K, V>) = putIfAbsent(pair.first, pair.second)
|
fun <K, V> MutableMap<K, V>.putPairIfAbsent(pair: Pair<K, V>) = putIfAbsent(pair.first, pair.second)
|
||||||
|
@ -194,6 +194,70 @@ internal class KompendiumTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can notarize the root route`() {
|
||||||
|
withTestApplication({
|
||||||
|
configModule()
|
||||||
|
openApiModule()
|
||||||
|
rootModule()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = TestData.getFileSnapshot("root_route.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can call the root route`() {
|
||||||
|
withTestApplication({
|
||||||
|
configModule()
|
||||||
|
openApiModule()
|
||||||
|
rootModule()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val result = handleRequest(HttpMethod.Get, "/").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = "☎️🏠🌲"
|
||||||
|
assertEquals(expected, result, "Should be the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can notarize a trailing slash route`() {
|
||||||
|
withTestApplication({
|
||||||
|
configModule()
|
||||||
|
openApiModule()
|
||||||
|
trailingSlash()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = TestData.getFileSnapshot("trailing_slash.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can call a trailing slash route`() {
|
||||||
|
withTestApplication({
|
||||||
|
configModule()
|
||||||
|
openApiModule()
|
||||||
|
trailingSlash()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val result = handleRequest(HttpMethod.Get, "/test/").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = "🙀👾"
|
||||||
|
assertEquals(expected, result, "Should be the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val testGetInfo = MethodInfo("Another get test", "testing more")
|
val testGetInfo = MethodInfo("Another get test", "testing more")
|
||||||
val testPostInfo = MethodInfo("Test post endpoint", "Post your tests here!")
|
val testPostInfo = MethodInfo("Test post endpoint", "Post your tests here!")
|
||||||
@ -270,6 +334,28 @@ internal class KompendiumTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Application.rootModule() {
|
||||||
|
routing {
|
||||||
|
route("/") {
|
||||||
|
notarizedGet<TestParams, TestResponse>(testGetInfo) {
|
||||||
|
call.respondText { "☎️🏠🌲" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Application.trailingSlash() {
|
||||||
|
routing {
|
||||||
|
route("/test") {
|
||||||
|
route("/") {
|
||||||
|
notarizedGet<TestParams, TestResponse>(testGetInfo) {
|
||||||
|
call.respondText { "🙀👾" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Application.openApiModule() {
|
private fun Application.openApiModule() {
|
||||||
routing {
|
routing {
|
||||||
route("/openapi.json") {
|
route("/openapi.json") {
|
||||||
|
62
kompendium-core/src/test/resources/root_route.json
Normal file
62
kompendium-core/src/test/resources/root_route.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"openapi" : "3.0.3",
|
||||||
|
"info" : {
|
||||||
|
"title" : "Test API",
|
||||||
|
"version" : "1.33.7",
|
||||||
|
"description" : "An amazing, fully-ish \uD83D\uDE09 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/lg-backbone/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" : "Another get test",
|
||||||
|
"description" : "testing more",
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A Successful Endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"$ref" : "#/components/schemas/TestResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"TestResponse" : {
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"type" : "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type" : "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
62
kompendium-core/src/test/resources/trailing_slash.json
Normal file
62
kompendium-core/src/test/resources/trailing_slash.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"openapi" : "3.0.3",
|
||||||
|
"info" : {
|
||||||
|
"title" : "Test API",
|
||||||
|
"version" : "1.33.7",
|
||||||
|
"description" : "An amazing, fully-ish \uD83D\uDE09 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/lg-backbone/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" : {
|
||||||
|
"/test/" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "Another get test",
|
||||||
|
"description" : "testing more",
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A Successful Endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"$ref" : "#/components/schemas/TestResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"TestResponse" : {
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"type" : "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type" : "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
Reference in New Issue
Block a user