diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c9c24555..f19f977a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 ### Added diff --git a/gradle.properties b/gradle.properties index b5cf24255..44cc995dc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -# Backbone -project.version=0.0.3 +# Kompendium +project.version=0.0.4 # Kotlin kotlin.code.style=official # Gradle diff --git a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt index c0c1f722d..53e5c6a98 100644 --- a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt +++ b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt @@ -13,7 +13,11 @@ object Helpers { is RootRouteSelector -> tail is PathSegmentParameterRouteSelector -> 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 MutableMap.putPairIfAbsent(pair: Pair) = putIfAbsent(pair.first, pair.second) diff --git a/kompendium-core/src/test/kotlin/org/leafygreens/kompendium/KompendiumTest.kt b/kompendium-core/src/test/kotlin/org/leafygreens/kompendium/KompendiumTest.kt index 6ed614098..d3740e9a7 100644 --- a/kompendium-core/src/test/kotlin/org/leafygreens/kompendium/KompendiumTest.kt +++ b/kompendium-core/src/test/kotlin/org/leafygreens/kompendium/KompendiumTest.kt @@ -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 { val testGetInfo = MethodInfo("Another get test", "testing more") val testPostInfo = MethodInfo("Test post endpoint", "Post your tests here!") @@ -270,6 +334,28 @@ internal class KompendiumTest { } } + private fun Application.rootModule() { + routing { + route("/") { + notarizedGet(testGetInfo) { + call.respondText { "☎️🏠🌲" } + } + } + } + } + + private fun Application.trailingSlash() { + routing { + route("/test") { + route("/") { + notarizedGet(testGetInfo) { + call.respondText { "🙀👾" } + } + } + } + } + } + private fun Application.openApiModule() { routing { route("/openapi.json") { diff --git a/kompendium-core/src/test/resources/root_route.json b/kompendium-core/src/test/resources/root_route.json new file mode 100644 index 000000000..1bdae1ff3 --- /dev/null +++ b/kompendium-core/src/test/resources/root_route.json @@ -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" : [ ] +} diff --git a/kompendium-core/src/test/resources/trailing_slash.json b/kompendium-core/src/test/resources/trailing_slash.json new file mode 100644 index 000000000..7ad806e6c --- /dev/null +++ b/kompendium-core/src/test/resources/trailing_slash.json @@ -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" : [ ] +}