From 23fd3596211f28e0396eeb5cc44a752c16ee9f55 Mon Sep 17 00:00:00 2001 From: Yannick Block Date: Mon, 3 Jun 2024 15:15:52 +0200 Subject: [PATCH] Fix linting --- .../APIGatewayProxyEventExtensionsTest.kt | 38 +- .../kotlin/io/moia/router/ApiRequestTest.kt | 1 - .../router/JsonDeserializationHandlerTest.kt | 33 +- .../moia/router/JwtPermissionHandlerTest.kt | 26 +- .../kotlin/io/moia/router/MediaTypeTest.kt | 1 - .../moia/router/NoOpPermissionHandlerTest.kt | 1 - .../PlainTextDeserializationHandlerTest.kt | 17 +- .../PlainTextSerializationHandlerTest.kt | 1 - .../io/moia/router/RequestHandlerTest.kt | 953 +++++++++--------- .../io/moia/router/ResponseEntityTest.kt | 8 +- .../test/kotlin/io/moia/router/RouterTest.kt | 100 +- .../kotlin/io/moia/router/UriTemplateTest.kt | 114 ++- 12 files changed, 681 insertions(+), 612 deletions(-) diff --git a/router/src/test/kotlin/io/moia/router/APIGatewayProxyEventExtensionsTest.kt b/router/src/test/kotlin/io/moia/router/APIGatewayProxyEventExtensionsTest.kt index 669cfe3c..ea4711d3 100644 --- a/router/src/test/kotlin/io/moia/router/APIGatewayProxyEventExtensionsTest.kt +++ b/router/src/test/kotlin/io/moia/router/APIGatewayProxyEventExtensionsTest.kt @@ -22,16 +22,17 @@ import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test class APIGatewayProxyEventExtensionsTest { - @Test fun `should add location header`() { - val request = GET() - .withHeader("Host", "example.com") - .withHeader("X-Forwarded-Proto", "http") - .withHeader("X-Forwarded-Port", "8080") + val request = + GET() + .withHeader("Host", "example.com") + .withHeader("X-Forwarded-Proto", "http") + .withHeader("X-Forwarded-Port", "8080") - val response = APIGatewayProxyResponseEvent() - .withLocationHeader(request, "/some/path") + val response = + APIGatewayProxyResponseEvent() + .withLocationHeader(request, "/some/path") then(response.location()).isEqualTo("http://example.com:8080/some/path") } @@ -40,18 +41,20 @@ class APIGatewayProxyEventExtensionsTest { fun `should add location header with default host and proto and without port`() { val request = GET() - val response = APIGatewayProxyResponseEvent() - .withLocationHeader(request, "/some/path") + val response = + APIGatewayProxyResponseEvent() + .withLocationHeader(request, "/some/path") then(response.location()).isEqualTo("http://localhost/some/path") } @Test fun `should omit default https port`() { - val request = GET() - .withHeader("Host", "example.com") - .withHeader("X-Forwarded-Proto", "https") - .withHeader("X-Forwarded-Port", "443") + val request = + GET() + .withHeader("Host", "example.com") + .withHeader("X-Forwarded-Proto", "https") + .withHeader("X-Forwarded-Port", "443") val location = request.location("some/path") @@ -60,10 +63,11 @@ class APIGatewayProxyEventExtensionsTest { @Test fun `should omit default http port`() { - val request = GET() - .withHeader("Host", "example.com") - .withHeader("X-Forwarded-Proto", "http") - .withHeader("X-Forwarded-Port", "80") + val request = + GET() + .withHeader("Host", "example.com") + .withHeader("X-Forwarded-Proto", "http") + .withHeader("X-Forwarded-Port", "80") val location = request.location("/some/path") diff --git a/router/src/test/kotlin/io/moia/router/ApiRequestTest.kt b/router/src/test/kotlin/io/moia/router/ApiRequestTest.kt index c6c6d8a0..58798921 100644 --- a/router/src/test/kotlin/io/moia/router/ApiRequestTest.kt +++ b/router/src/test/kotlin/io/moia/router/ApiRequestTest.kt @@ -22,7 +22,6 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent import org.junit.jupiter.api.Test class ApiRequestTest { - @Test fun `should match header`() { val request = APIGatewayProxyRequestEvent().withHeaders(mapOf("Accept" to "application/json")) diff --git a/router/src/test/kotlin/io/moia/router/JsonDeserializationHandlerTest.kt b/router/src/test/kotlin/io/moia/router/JsonDeserializationHandlerTest.kt index 86706554..6ade7d8a 100644 --- a/router/src/test/kotlin/io/moia/router/JsonDeserializationHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/JsonDeserializationHandlerTest.kt @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class JsonDeserializationHandlerTest { - val deserializationHandler = JsonDeserializationHandler(jacksonObjectMapper()) @Test @@ -31,14 +30,14 @@ class JsonDeserializationHandlerTest { assertTrue( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/json") - ) + .withHeader("content-type", "application/json"), + ), ) assertTrue( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/vnd.moia.v1+json") - ) + .withHeader("content-type", "application/vnd.moia.v1+json"), + ), ) } @@ -47,14 +46,14 @@ class JsonDeserializationHandlerTest { assertFalse( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "image/png") - ) + .withHeader("content-type", "image/png"), + ), ) assertFalse( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "text/plain") - ) + .withHeader("content-type", "text/plain"), + ), ) } @@ -63,14 +62,14 @@ class JsonDeserializationHandlerTest { assertTrue( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/json; charset=UTF-8") - ) + .withHeader("content-type", "application/json; charset=UTF-8"), + ), ) assertTrue( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/vnd.moia.v1+json; charset=UTF-8") - ) + .withHeader("content-type", "application/vnd.moia.v1+json; charset=UTF-8"), + ), ) } @@ -79,14 +78,14 @@ class JsonDeserializationHandlerTest { assertFalse( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/json; charset=UTF-16") - ) + .withHeader("content-type", "application/json; charset=UTF-16"), + ), ) assertFalse( deserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/vnd.moia.v1+json; charset=UTF-16") - ) + .withHeader("content-type", "application/vnd.moia.v1+json; charset=UTF-16"), + ), ) } } diff --git a/router/src/test/kotlin/io/moia/router/JwtPermissionHandlerTest.kt b/router/src/test/kotlin/io/moia/router/JwtPermissionHandlerTest.kt index c0152a21..a79e6f34 100644 --- a/router/src/test/kotlin/io/moia/router/JwtPermissionHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/JwtPermissionHandlerTest.kt @@ -20,8 +20,8 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test +@Suppress("ktlint:standard:max-line-length") class JwtPermissionHandlerTest { - /* { "sub": "1234567890", @@ -29,7 +29,7 @@ class JwtPermissionHandlerTest { "iat": 1516239022, "scope": "one two" } - */ + */ val jwtWithScopeClaimSpace = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJzY29wZSI6Im9uZSB0d28ifQ.2tPrDymXDejHfVjNlVh4XUj22ZuDrKHP6dvWN7JNAWY" /* @@ -58,14 +58,16 @@ class JwtPermissionHandlerTest { @Test fun `should extract permissions from custom permissions claim`() { - val handler = JwtPermissionHandler( - accessor = JwtAccessor( - APIGatewayProxyRequestEvent() - .withHeader("Authorization", jwtWithCustomClaimAndSeparator) - ), - permissionsClaim = "userRights", - permissionSeparator = "," - ) + val handler = + JwtPermissionHandler( + accessor = + JwtAccessor( + APIGatewayProxyRequestEvent() + .withHeader("Authorization", jwtWithCustomClaimAndSeparator), + ), + permissionsClaim = "userRights", + permissionSeparator = ",", + ) thenRecognizesRequiredPermissions(handler) } @@ -103,7 +105,7 @@ class JwtPermissionHandlerTest { JwtPermissionHandler( JwtAccessor( APIGatewayProxyRequestEvent() - .withHeader("Authorization", authHeader) - ) + .withHeader("Authorization", authHeader), + ), ) } diff --git a/router/src/test/kotlin/io/moia/router/MediaTypeTest.kt b/router/src/test/kotlin/io/moia/router/MediaTypeTest.kt index 3b0d0d43..f289ba4d 100644 --- a/router/src/test/kotlin/io/moia/router/MediaTypeTest.kt +++ b/router/src/test/kotlin/io/moia/router/MediaTypeTest.kt @@ -22,7 +22,6 @@ import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test class MediaTypeTest { - @Test fun `should match`() { then(MediaType.parse("application/json").isCompatibleWith(MediaType.parse("application/json"))).isTrue() diff --git a/router/src/test/kotlin/io/moia/router/NoOpPermissionHandlerTest.kt b/router/src/test/kotlin/io/moia/router/NoOpPermissionHandlerTest.kt index bebc569f..51f7d0bf 100644 --- a/router/src/test/kotlin/io/moia/router/NoOpPermissionHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/NoOpPermissionHandlerTest.kt @@ -20,7 +20,6 @@ import org.assertj.core.api.BDDAssertions.then import org.junit.jupiter.api.Test class NoOpPermissionHandlerTest { - @Test fun `should always return true`() { val handler = NoOpPermissionHandler() diff --git a/router/src/test/kotlin/io/moia/router/PlainTextDeserializationHandlerTest.kt b/router/src/test/kotlin/io/moia/router/PlainTextDeserializationHandlerTest.kt index 6733fe0c..a9cae07d 100644 --- a/router/src/test/kotlin/io/moia/router/PlainTextDeserializationHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/PlainTextDeserializationHandlerTest.kt @@ -23,20 +23,19 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class PlainTextDeserializationHandlerTest { - @Test fun `should support text`() { assertTrue( PlainTextDeserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "text/plain") - ) + .withHeader("content-type", "text/plain"), + ), ) assertTrue( PlainTextDeserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "text/csv") - ) + .withHeader("content-type", "text/csv"), + ), ) } @@ -45,14 +44,14 @@ class PlainTextDeserializationHandlerTest { assertFalse( PlainTextDeserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "image/png") - ) + .withHeader("content-type", "image/png"), + ), ) assertFalse( PlainTextDeserializationHandler.supports( APIGatewayProxyRequestEvent() - .withHeader("content-type", "application/json") - ) + .withHeader("content-type", "application/json"), + ), ) } diff --git a/router/src/test/kotlin/io/moia/router/PlainTextSerializationHandlerTest.kt b/router/src/test/kotlin/io/moia/router/PlainTextSerializationHandlerTest.kt index 82039624..bab7ed17 100644 --- a/router/src/test/kotlin/io/moia/router/PlainTextSerializationHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/PlainTextSerializationHandlerTest.kt @@ -7,7 +7,6 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class PlainTextSerializationHandlerTest { - @Test fun `should support text`() { assertTrue(PlainTextSerializationHandler().supports(MediaType.parse("text/plain"), "some")) diff --git a/router/src/test/kotlin/io/moia/router/RequestHandlerTest.kt b/router/src/test/kotlin/io/moia/router/RequestHandlerTest.kt index 6acbc030..b51982bc 100644 --- a/router/src/test/kotlin/io/moia/router/RequestHandlerTest.kt +++ b/router/src/test/kotlin/io/moia/router/RequestHandlerTest.kt @@ -31,20 +31,21 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import java.time.LocalDate +@Suppress("ktlint:standard:max-line-length") class RequestHandlerTest { - private val testRequestHandler = TestRequestHandler() private val mapper = testRequestHandler.objectMapper @Test fun `should match request`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":"Hello"}""") @@ -52,13 +53,14 @@ class RequestHandlerTest { @Test fun `should match request with path parameter`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some/me") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some/me") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":"Hello me"}""") @@ -66,48 +68,51 @@ class RequestHandlerTest { @Test fun `should return not acceptable on unsupported accept header`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "image/jpg")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "image/jpg")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(406) } @Test fun `should return unsupported media type`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("POST") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "image/jpg" - ) - ), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("POST") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "image/jpg", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(415) } @Test fun `should handle request with body`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":"some"}""") @@ -115,17 +120,18 @@ class RequestHandlerTest { @Test fun `should handle request with body as a List`() { - val response = testRequestHandler.handleRequest( - POST("/somes") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/somes") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""[{ "greeting": "some" },{ "greeting": "some1" }]""".trimMargin()), - mockk() - ) + .withBody("""[{ "greeting": "some" },{ "greeting": "some1" }]""".trimMargin()), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""[{"greeting":"some"},{"greeting":"some1"}]""") @@ -133,31 +139,33 @@ class RequestHandlerTest { @Test fun `should return method not allowed`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("PUT") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "image/jpg" - ) - ), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("PUT") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "image/jpg", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(405) } @Test fun `should return not found`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some-other") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some-other") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(404) } @@ -165,13 +173,14 @@ class RequestHandlerTest { @Test fun `should invoke filter chain`() { val handler = TestRequestHandlerWithFilter() - val response = handler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + handler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(handler.filterInvocations).isEqualTo(2) @@ -180,13 +189,14 @@ class RequestHandlerTest { @Test fun `should invoke filter chain also for non successful requests`() { val handler = TestRequestHandlerWithFilter() - val response = handler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some-internal-server-error") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + handler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some-internal-server-error") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(500) assertThat(response.headers["header"]).isEqualTo("value") @@ -196,51 +206,54 @@ class RequestHandlerTest { @Test fun `should ignore content-type header when handler expects none`() { val handler = TestRequestHandlerWithFilter() - val response = handler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("GET") - .withHeaders( - mapOf( - "Accept" to "application/json", - "content-type" to "application/json" - ) - ), - mockk() - ) + val response = + handler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("GET") + .withHeaders( + mapOf( + "Accept" to "application/json", + "content-type" to "application/json", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) } @Test fun `should handle deserialization error`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("{}"), - mockk() - ) + .withBody("{}"), + mockk(), + ) assertThat(response.statusCode).isEqualTo(422) } @Test fun `should handle deserialization error, when field has invalid format`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{"greeting": "hello","age": "a"}"""), - mockk() - ) + .withBody("""{"greeting": "hello","age": "a"}"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(422) val body = mapper.readValue>(response.body) assertThat(body.size).isEqualTo(1) @@ -254,17 +267,18 @@ class RequestHandlerTest { @Test fun `should handle deserialization error, when field can not be parsed to class`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{"greeting": "hello","age": 1, "bday": "2000-01-AA"}"""), - mockk() - ) + .withBody("""{"greeting": "hello","age": 1, "bday": "2000-01-AA"}"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(422) val body = mapper.readValue>(response.body) assertThat(body.size).isEqualTo(1) @@ -278,17 +292,18 @@ class RequestHandlerTest { @Test fun `should handle deserialization error, when json can not be parsed`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{"greeting": "hello", bday: "2000-01-01"}"""), - mockk() - ) + .withBody("""{"greeting": "hello", bday: "2000-01-01"}"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(422) val body = mapper.readValue>(response.body) assertThat(body.size).isEqualTo(1) @@ -302,77 +317,82 @@ class RequestHandlerTest { @Test fun `should return 400 on missing body when content type stated`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody(null), - mockk() - ) + .withBody(null), + mockk(), + ) assertThat(response.statusCode).isEqualTo(400) assertThat(mapper.readValue(response.body).code).isEqualTo("REQUEST_BODY_MISSING") } @Test fun `should handle null body when content type is stated and request handler body type is nullable`() { - val response = testRequestHandler.handleRequest( - POST("/some-nullable") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some-nullable") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Content-Type" to "application/json", + ), ) - ) - .withBody(null), - mockk() - ) + .withBody(null), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":""}""") } @Test fun `should handle api exception`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some-api-exception") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some-api-exception") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(400) } @Test fun `should handle internal server error`() { - val response = testRequestHandler.handleRequest( - APIGatewayProxyRequestEvent() - .withPath("/some-internal-server-error") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")), - mockk() - ) + val response = + testRequestHandler.handleRequest( + APIGatewayProxyRequestEvent() + .withPath("/some-internal-server-error") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")), + mockk(), + ) assertThat(response.statusCode).isEqualTo(500) } @Test fun `should handle request with a media type range in accept header`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/xhtml+xml, application/json, application/xml;q=0.9, image/webp, */*;q=0.8", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/xhtml+xml, application/json, application/xml;q=0.9, image/webp, */*;q=0.8", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.getHeaderCaseInsensitive("content-type")).isEqualTo("application/json") @@ -382,17 +402,18 @@ class RequestHandlerTest { @Test fun `should handle request with accept all header`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "*/*", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "*/*", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.getHeaderCaseInsensitive("content-type")).isEqualTo("application/vnd.moia.v2+json") @@ -402,17 +423,18 @@ class RequestHandlerTest { @Test fun `should handle subtype structured suffix wildcard`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/vnd.moia.v1+json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/vnd.moia.v1+json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":"some"}""") @@ -420,17 +442,18 @@ class RequestHandlerTest { @Test fun `should match version`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "application/vnd.moia.v2+json", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "application/vnd.moia.v2+json", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "v2" }"""), - mockk() - ) + .withBody("""{ "greeting": "v2" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) assertThat(response.body).isEqualTo("""{"greeting":"v2"}""") @@ -439,122 +462,131 @@ class RequestHandlerTest { @Test fun `should fail with 406 Not Acceptable on an unparsable media type`() { - val response = testRequestHandler.handleRequest( - POST("/some") - .withHeaders( - mapOf( - "Accept" to "*", - "Content-Type" to "application/json" + val response = + testRequestHandler.handleRequest( + POST("/some") + .withHeaders( + mapOf( + "Accept" to "*", + "Content-Type" to "application/json", + ), ) - ) - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(406) } @Test fun `should match request requiring permission`() { - val response = TestRequestHandlerAuthorization().handleRequest( - GET("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Authorization" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24xIn0.E3PxWx68uP2s9yyAV7UVs8egyrGTIuWXjtkcqAA840I" - ) - ), - mockk() - ) + val response = + TestRequestHandlerAuthorization().handleRequest( + GET("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Authorization" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24xIn0.E3PxWx68uP2s9yyAV7UVs8egyrGTIuWXjtkcqAA840I", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) } @Test fun `should match request requiring permission from custom header`() { - val response = TestRequestHandlerCustomAuthorizationHeader().handleRequest( - GET("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Custom-Auth" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24xIn0.E3PxWx68uP2s9yyAV7UVs8egyrGTIuWXjtkcqAA840I" - ) - ), - mockk() - ) + val response = + TestRequestHandlerCustomAuthorizationHeader().handleRequest( + GET("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Custom-Auth" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24xIn0.E3PxWx68uP2s9yyAV7UVs8egyrGTIuWXjtkcqAA840I", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(200) } @Test fun `should fail on missing permission`() { - val response = TestRequestHandlerAuthorization().handleRequest( - GET("/some") - .withHeaders( - mapOf( - "Accept" to "application/json", - "Authorization" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24yIn0.RA8ERppuFmastqFN-6C98WqMEE7L6h88WylMeq6jh1w" - ) - ), - mockk() - ) + val response = + TestRequestHandlerAuthorization().handleRequest( + GET("/some") + .withHeaders( + mapOf( + "Accept" to "application/json", + "Authorization" to "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJwZXJtaXNzaW9ucyI6InBlcm1pc3Npb24yIn0.RA8ERppuFmastqFN-6C98WqMEE7L6h88WylMeq6jh1w", + ), + ), + mockk(), + ) assertThat(response.statusCode).isEqualTo(403) } @Test fun `Request without headers should return status code 406`() { - val response = testRequestHandler.handleRequest( - GET("/some"), - mockk() - ) + val response = + testRequestHandler.handleRequest( + GET("/some"), + mockk(), + ) assertThat(response.statusCode).isEqualTo(406) } @Test fun `Request without request path should return status code 404`() { - val response = testRequestHandler.handleRequest( - GET(), - mockk() - ) + val response = + testRequestHandler.handleRequest( + GET(), + mockk(), + ) assertThat(response.statusCode).isEqualTo(404) } @Test fun `Successful POST request should return status code 204`() { - val response = testRequestHandler.handleRequest( - POST("/no-content") - .withHeader("Accept", "application/json") - .withHeader("Content-Type", "application/json") - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + val response = + testRequestHandler.handleRequest( + POST("/no-content") + .withHeader("Accept", "application/json") + .withHeader("Content-Type", "application/json") + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(204) assertThat(response.body).isNullOrEmpty() } @Test fun `Create should not return a location header`() { - val response = testRequestHandler.handleRequest( - POST("/create-without-location") - .withHeader("Accept", "application/json") - .withHeader("Content-Type", "application/json") - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + val response = + testRequestHandler.handleRequest( + POST("/create-without-location") + .withHeader("Accept", "application/json") + .withHeader("Content-Type", "application/json") + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(201) assertThat(response.headers.containsKey("location")).isFalse() } @Test fun `Create should return a location header`() { - val response = testRequestHandler.handleRequest( - POST("/create-with-location") - .withHeader("Accept", "application/json") - .withHeader("Content-Type", "application/json") - .withBody("""{ "greeting": "some" }"""), - mockk() - ) + val response = + testRequestHandler.handleRequest( + POST("/create-with-location") + .withHeader("Accept", "application/json") + .withHeader("Content-Type", "application/json") + .withBody("""{ "greeting": "some" }"""), + mockk(), + ) assertThat(response.statusCode).isEqualTo(201) assertThat(response.headers.containsKey("location")).isTrue() assertThat(response.headers["location"]).isEqualTo("http://localhost/test") @@ -562,13 +594,14 @@ class RequestHandlerTest { @Test fun `Deletion should ignore the body and content-type`() { - val response = testRequestHandler.handleRequest( - DELETE("/delete-me") - .withHeader("Accept", "application/json") - .withHeader("Content-Type", "text/csv") - .withBody("this may be faulty"), - mockk() - ) + val response = + testRequestHandler.handleRequest( + DELETE("/delete-me") + .withHeader("Accept", "application/json") + .withHeader("Content-Type", "text/csv") + .withBody("this may be faulty"), + mockk(), + ) assertThat(response.statusCode).isEqualTo(204) } @@ -578,48 +611,54 @@ class RequestHandlerTest { GET("/search") .withQueryStringParameters( mapOf( - "testQueryParam" to "foo" - ) + "testQueryParam" to "foo", + ), ) .withMultiValueQueryStringParameters( mapOf( - "testMultiValueQueryStringParam" to listOf("foo", "bar") - ) + "testMultiValueQueryStringParam" to listOf("foo", "bar"), + ), ), - mockk() + mockk(), ) TestQueryParamParsingHandler().handleRequest( GET("/search?testQueryParam=foo&testMultiValueQueryStringParam=foo&testMultiValueQueryStringParam=bar"), - mockk() + mockk(), ) } @Test fun `Not existing path parameter should throw an error`() { - val response = testRequestHandler.handleRequest( - GET("/non-existing-path-parameter") - .withHeader("accept", "application/json"), - mockk() - ) + val response = + testRequestHandler.handleRequest( + GET("/non-existing-path-parameter") + .withHeader("accept", "application/json"), + mockk(), + ) assertEquals(500, response.statusCode) - assertEquals("{\"message\":\"Could not find path parameter 'foo\",\"code\":\"INTERNAL_SERVER_ERROR\",\"details\":{}}", response.body) + assertEquals( + "{\"message\":\"Could not find path parameter 'foo\",\"code\":\"INTERNAL_SERVER_ERROR\",\"details\":{}}", + response.body, + ) } @Test fun `should return the content type that is accepted`() { - val jsonResponse = AcceptTypeDependingHandler().handleRequest( - GET("/all-objects") - .withHeader("accept", "application/json"), - mockk() - ) + val jsonResponse = + AcceptTypeDependingHandler().handleRequest( + GET("/all-objects") + .withHeader("accept", "application/json"), + mockk(), + ) assertEquals(200, jsonResponse.statusCode) assertEquals("application/json", jsonResponse.getHeaderCaseInsensitive("content-type")) assertEquals("[{\"text\":\"foo\",\"number\":1},{\"text\":\"bar\",\"number\":2}]", jsonResponse.body) - val plainTextResponse = AcceptTypeDependingHandler().handleRequest( - GET("/all-objects") - .withHeader("accept", "text/plain"), - mockk() - ) + val plainTextResponse = + AcceptTypeDependingHandler().handleRequest( + GET("/all-objects") + .withHeader("accept", "text/plain"), + mockk(), + ) assertEquals(200, plainTextResponse.statusCode) assertEquals("text/plain", plainTextResponse.getHeaderCaseInsensitive("content-type")) assertEquals("[CustomObject(text=foo, number=1), CustomObject(text=bar, number=2)]", plainTextResponse.body) @@ -627,21 +666,22 @@ class RequestHandlerTest { @Test fun `headers should be case insensitive`() { - val request = APIGatewayProxyRequestEvent() - .withPath("/some") - .withHttpMethod("GET") - .withHeaders( - mapOf( - "Accept" to "Application/Json", - "User-Agent" to "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0" + val request = + APIGatewayProxyRequestEvent() + .withPath("/some") + .withHttpMethod("GET") + .withHeaders( + mapOf( + "Accept" to "Application/Json", + "User-Agent" to "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0", + ), ) - ) val response = testRequestHandler.handleRequest(request, mockk()) assertThat(request.headers["accept"].toString()).isEqualTo("Application/Json") assertThat(request.headers["user-agent"].toString()) .isEqualTo( - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0" + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0", ) assertThat(response.statusCode).isEqualTo(200) } @@ -649,16 +689,18 @@ class RequestHandlerTest { @Test fun `should deserialize plain text`() { class SampleRouter : RequestHandler() { - override val router = router { - POST("/some", { r: Request -> ResponseEntity.ok(r.body) }) - .producing("text/plain") - .consuming("text/plain") - } + override val router = + router { + POST("/some", { r: Request -> ResponseEntity.ok(r.body) }) + .producing("text/plain") + .consuming("text/plain") + } } - val request = POST("/some") - .withAcceptHeader("text/plain") - .withContentTypeHeader("text/plain") - .withBody("just text") + val request = + POST("/some") + .withAcceptHeader("text/plain") + .withContentTypeHeader("text/plain") + .withBody("just text") val response = SampleRouter().handleRequest(request, mockk()) @@ -670,14 +712,18 @@ class RequestHandlerTest { @Test fun `should fail for function references when using Kotlin 1_6_10`() { class DummyHandler : RequestHandler() { - val dummy = object { - @Suppress("UNUSED_PARAMETER") - fun handler(r: Request) = ResponseEntity.ok(Unit) - } + val dummy = + object { + @Suppress("UNUSED_PARAMETER") + fun handler(r: Request) = ResponseEntity.ok(Unit) + } + override fun exceptionToResponseEntity(ex: Exception) = throw ex - override val router = router { - GET("/some", dummy::handler).producing("application/json") - } + + override val router = + router { + GET("/some", dummy::handler).producing("application/json") + } } assertThrows { DummyHandler().handleRequest( @@ -685,175 +731,180 @@ class RequestHandlerTest { .withHttpMethod("GET") .withPath("/some") .withAcceptHeader("application/json"), - mockk() + mockk(), ) } } class TestRequestHandlerAuthorization : RequestHandler() { - override val router = router { - GET("/some") { _: Request -> - ResponseEntity.ok("hello") - }.requiringPermissions("permission1") - } + override val router = + router { + GET("/some") { _: Request -> + ResponseEntity.ok("hello") + }.requiringPermissions("permission1") + } override fun permissionHandlerSupplier(): (r: APIGatewayProxyRequestEvent) -> PermissionHandler = { JwtPermissionHandler( request = it, permissionsClaim = "permissions", - permissionSeparator = "," + permissionSeparator = ",", ) } } class TestRequestHandlerCustomAuthorizationHeader : RequestHandler() { - override val router = router { - GET("/some") { _: Request -> - ResponseEntity.ok("hello") - }.requiringPermissions("permission1") - } + override val router = + router { + GET("/some") { _: Request -> + ResponseEntity.ok("hello") + }.requiringPermissions("permission1") + } override fun permissionHandlerSupplier(): (r: APIGatewayProxyRequestEvent) -> PermissionHandler = { JwtPermissionHandler( - accessor = JwtAccessor( - request = it, - authorizationHeaderName = "custom-auth" - ), + accessor = + JwtAccessor( + request = it, + authorizationHeaderName = "custom-auth", + ), permissionsClaim = "permissions", - permissionSeparator = "," + permissionSeparator = ",", ) } } class TestRequestHandlerWithFilter : RequestHandler() { - var filterInvocations = 0 - private val incrementingFilter = Filter { next -> - { request -> - filterInvocations += 1 - next(request).apply { withHeader("header", "value") } + private val incrementingFilter = + Filter { next -> + { request -> + filterInvocations += 1 + next(request).apply { withHeader("header", "value") } + } } - } - override val router = router { - filter = incrementingFilter.then(incrementingFilter) - - GET("/some") { _: Request -> - ResponseEntity.ok("hello") + override val router = + router { + filter = incrementingFilter.then(incrementingFilter) + + GET("/some") { _: Request -> + ResponseEntity.ok("hello") + } + GET("/some-internal-server-error") { + throw IllegalArgumentException("boom") + } } - GET("/some-internal-server-error") { - throw IllegalArgumentException("boom") - } - } } class TestRequestHandler : RequestHandler() { - data class TestResponse(val greeting: String) + data class TestRequest(val greeting: String, val age: Int = 0, val bday: LocalDate = LocalDate.now()) - override val router = router { - GET("/some") { _: Request -> - ResponseEntity.ok( - TestResponse( - "Hello" - ) - ) - } - GET("/some-api-exception") { - throw ApiException("boom", "BOOM", 400, mapOf("more" to "info")) - } - GET("/some-internal-server-error") { - throw IllegalArgumentException("boom") - } - GET("/some/{id}") { r: Request -> - assertThat(r.pathParameters.containsKey("id")).isTrue() - ResponseEntity.ok( - TestResponse( - "Hello ${r.getPathParameter("id")}" + override val router = + router { + GET("/some") { _: Request -> + ResponseEntity.ok( + TestResponse( + "Hello", + ), ) - ) - } - - POST("/some") { _: Request -> - ResponseEntity.ok( - TestResponse( - "v2" + } + GET("/some-api-exception") { + throw ApiException("boom", "BOOM", 400, mapOf("more" to "info")) + } + GET("/some-internal-server-error") { + throw IllegalArgumentException("boom") + } + GET("/some/{id}") { r: Request -> + assertThat(r.pathParameters.containsKey("id")).isTrue() + ResponseEntity.ok( + TestResponse( + "Hello ${r.getPathParameter("id")}", + ), ) - ) - }.producing("application/vnd.moia.v2+json") + } - POST("/some") { r: Request -> - ResponseEntity.ok( - TestResponse( - r.body.greeting + POST("/some") { _: Request -> + ResponseEntity.ok( + TestResponse( + "v2", + ), ) - ) - }.producing("application/json", "application/*+json") + }.producing("application/vnd.moia.v2+json") - POST("/some-nullable") { r: Request -> - ResponseEntity.ok( - TestResponse( - r.body?.greeting.orEmpty() + POST("/some") { r: Request -> + ResponseEntity.ok( + TestResponse( + r.body.greeting, + ), ) - ) - }.producing("application/json") + }.producing("application/json", "application/*+json") - POST("/somes") { r: Request> -> - ResponseEntity.ok( - r.body.map { + POST("/some-nullable") { r: Request -> + ResponseEntity.ok( TestResponse( - it.greeting - ) - }.toList() - ) - } - POST("/no-content") { _: Request -> - ResponseEntity.noContent() - } - POST("/create-without-location") { _: Request -> - ResponseEntity.created(null, null, emptyMap()) - } - POST("/create-with-location") { r: Request -> - ResponseEntity.created(null, r.apiRequest.location("test"), emptyMap()) - } - DELETE("/delete-me") { _: Request -> - ResponseEntity.noContent() - } - GET("/non-existing-path-parameter") { request: Request -> - request.getPathParameter("foo") - ResponseEntity.ok(null) + r.body?.greeting.orEmpty(), + ), + ) + }.producing("application/json") + + POST("/somes") { r: Request> -> + ResponseEntity.ok( + r.body.map { + TestResponse( + it.greeting, + ) + }.toList(), + ) + } + POST("/no-content") { _: Request -> + ResponseEntity.noContent() + } + POST("/create-without-location") { _: Request -> + ResponseEntity.created(null, null, emptyMap()) + } + POST("/create-with-location") { r: Request -> + ResponseEntity.created(null, r.apiRequest.location("test"), emptyMap()) + } + DELETE("/delete-me") { _: Request -> + ResponseEntity.noContent() + } + GET("/non-existing-path-parameter") { request: Request -> + request.getPathParameter("foo") + ResponseEntity.ok(null) + } } - } } class TestQueryParamParsingHandler : RequestHandler() { - - override val router = router { - GET("/search") { r: Request -> - assertThat(r.getQueryParameter("testQueryParam")).isNotNull() - assertThat(r.getQueryParameter("testQueryParam")).isEqualTo("foo") - assertThat(r.queryParameters!!["testQueryParam"]).isNotNull() - assertThat(r.getMultiValueQueryStringParameter("testMultiValueQueryStringParam")).isNotNull() - assertThat(r.getMultiValueQueryStringParameter("testMultiValueQueryStringParam")).isEqualTo(listOf("foo", "bar")) - assertThat(r.multiValueQueryStringParameters!!["testMultiValueQueryStringParam"]).isNotNull() - ResponseEntity.ok(null) + override val router = + router { + GET("/search") { r: Request -> + assertThat(r.getQueryParameter("testQueryParam")).isNotNull() + assertThat(r.getQueryParameter("testQueryParam")).isEqualTo("foo") + assertThat(r.queryParameters!!["testQueryParam"]).isNotNull() + assertThat(r.getMultiValueQueryStringParameter("testMultiValueQueryStringParam")).isNotNull() + assertThat(r.getMultiValueQueryStringParameter("testMultiValueQueryStringParam")).isEqualTo(listOf("foo", "bar")) + assertThat(r.multiValueQueryStringParameters!!["testMultiValueQueryStringParam"]).isNotNull() + ResponseEntity.ok(null) + } } - } } class AcceptTypeDependingHandler : RequestHandler() { - data class CustomObject(val text: String, val number: Int) - override val router = router { - defaultConsuming = setOf("application/json", "text/plain") - defaultProducing = setOf("application/json", "text/plain") - GET("/all-objects") { _: Request -> - ResponseEntity.ok(body = listOf(CustomObject("foo", 1), CustomObject("bar", 2))) + override val router = + router { + defaultConsuming = setOf("application/json", "text/plain") + defaultProducing = setOf("application/json", "text/plain") + GET("/all-objects") { _: Request -> + ResponseEntity.ok(body = listOf(CustomObject("foo", 1), CustomObject("bar", 2))) + } } - } } } diff --git a/router/src/test/kotlin/io/moia/router/ResponseEntityTest.kt b/router/src/test/kotlin/io/moia/router/ResponseEntityTest.kt index 7afc6ee3..47d844e6 100644 --- a/router/src/test/kotlin/io/moia/router/ResponseEntityTest.kt +++ b/router/src/test/kotlin/io/moia/router/ResponseEntityTest.kt @@ -24,11 +24,11 @@ import assertk.assertions.isNull import org.junit.jupiter.api.Test class ResponseEntityTest { - private val body = "body" - private val headers = mapOf( - "content-type" to "text/plain" - ) + private val headers = + mapOf( + "content-type" to "text/plain", + ) @Test fun `should process ok response`() { diff --git a/router/src/test/kotlin/io/moia/router/RouterTest.kt b/router/src/test/kotlin/io/moia/router/RouterTest.kt index 46278829..e75b218c 100644 --- a/router/src/test/kotlin/io/moia/router/RouterTest.kt +++ b/router/src/test/kotlin/io/moia/router/RouterTest.kt @@ -27,14 +27,14 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class RouterTest { - @Test fun `should register get route with default accept header`() { - val router = router { - GET("/some") { r: Request -> - ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + val router = + router { + GET("/some") { r: Request -> + ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + } } - } assertThat(router.routes).hasSize(1) with(router.routes.first().requestPredicate) { @@ -47,25 +47,27 @@ class RouterTest { @Test fun `should register routes`() { - val router = router { - PUT("/some") { _: Request -> ResponseEntity.ok("") } - PATCH("/some") { _: Request -> ResponseEntity.ok("") } - DELETE("/some") { _: Request -> ResponseEntity.ok("") } - POST("/some") { _: Request -> ResponseEntity.ok("") } - } + val router = + router { + PUT("/some") { _: Request -> ResponseEntity.ok("") } + PATCH("/some") { _: Request -> ResponseEntity.ok("") } + DELETE("/some") { _: Request -> ResponseEntity.ok("") } + POST("/some") { _: Request -> ResponseEntity.ok("") } + } then(router.routes.map { it.requestPredicate.method }).containsOnly("PUT", "PATCH", "DELETE", "POST") } @Test fun `should register post route with specific content types`() { - val router = router { - POST("/some") { r: Request -> - ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + val router = + router { + POST("/some") { r: Request -> + ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + } + .producing("text/plain") + .consuming("text/plain") } - .producing("text/plain") - .consuming("text/plain") - } assertThat(router.routes).hasSize(1) with(router.routes.first().requestPredicate) { @@ -78,14 +80,15 @@ class RouterTest { @Test fun `should register get route with custom default content types`() { - val router = router { - defaultConsuming = setOf("text/plain") - defaultProducing = setOf("text/plain") - - POST("/some") { r: Request -> - ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + val router = + router { + defaultConsuming = setOf("text/plain") + defaultProducing = setOf("text/plain") + + POST("/some") { r: Request -> + ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + } } - } assertThat(router.routes).hasSize(1) with(router.routes.first().requestPredicate) { @@ -98,11 +101,12 @@ class RouterTest { @Test fun `should handle greedy path variables successfully`() { - val router = router { - POST("/some/{proxy+}") { r: Request -> - ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + val router = + router { + POST("/some/{proxy+}") { r: Request -> + ResponseEntity.ok("""{"hello": "world", "request":"${r.body}"}""") + } } - } assertThat(router.routes).hasSize(1) with(router.routes.first().requestPredicate) { assertTrue(UriTemplate.from(pathPattern).matches("/some/sub/sub/sub/path")) @@ -111,11 +115,12 @@ class RouterTest { @Test fun `should not consume for a deletion route`() { - val router = router { - DELETE("/delete-me") { _: Request -> - ResponseEntity.ok(null) + val router = + router { + DELETE("/delete-me") { _: Request -> + ResponseEntity.ok(null) + } } - } with(router.routes.first().requestPredicate) { assertThat(consumes).isEqualTo(setOf()) } @@ -123,21 +128,24 @@ class RouterTest { @Test fun `request should contain ProxyRequestContext`() { - val claims = mapOf( - "foobar" to "foo" - ) - val context = APIGatewayProxyRequestEvent.ProxyRequestContext().apply { - authorizer = mapOf("claims" to claims) - } + val claims = + mapOf( + "foobar" to "foo", + ) + val context = + APIGatewayProxyRequestEvent.ProxyRequestContext().apply { + authorizer = mapOf("claims" to claims) + } - val request = Request( - APIGatewayProxyRequestEvent() - .withPath("/some-other") - .withHttpMethod("GET") - .withHeaders(mapOf("Accept" to "application/json")) - .withRequestContext(context), - Unit - ) + val request = + Request( + APIGatewayProxyRequestEvent() + .withPath("/some-other") + .withHttpMethod("GET") + .withHeaders(mapOf("Accept" to "application/json")) + .withRequestContext(context), + Unit, + ) assertThat(request.requestContext.authorizer!!["claims"]).isEqualTo(claims) } } diff --git a/router/src/test/kotlin/io/moia/router/UriTemplateTest.kt b/router/src/test/kotlin/io/moia/router/UriTemplateTest.kt index 742c24d5..7aafce45 100644 --- a/router/src/test/kotlin/io/moia/router/UriTemplateTest.kt +++ b/router/src/test/kotlin/io/moia/router/UriTemplateTest.kt @@ -24,16 +24,23 @@ import org.junit.jupiter.params.provider.MethodSource import java.util.UUID class UriTemplateTest { - @ParameterizedTest @MethodSource("matchTestParams") - fun `match template`(uriTemplate: String, matchTemplate: String, expectedResult: Boolean) { + fun `match template`( + uriTemplate: String, + matchTemplate: String, + expectedResult: Boolean, + ) { then(UriTemplate.from(uriTemplate).matches(matchTemplate)).isEqualTo(expectedResult) } @ParameterizedTest @MethodSource("extractTestParams") - fun `extract template`(uriTemplate: String, extractTemplate: String, expectedResult: Map) { + fun `extract template`( + uriTemplate: String, + extractTemplate: String, + expectedResult: Map, + ) { then(UriTemplate.from(uriTemplate).extract(extractTemplate)).isEqualTo(expectedResult) } @@ -48,62 +55,65 @@ class UriTemplateTest { companion object { @JvmStatic @Suppress("unused") - fun matchTestParams() = listOf( - Arguments.of("/some", "/some", true, "should match without parameter"), - Arguments.of("/some", "/some-other", false, "should not match simple"), - Arguments.of("/some/{id}", "/some/${UUID.randomUUID()}", true, "should match with parameter-1"), - Arguments.of("/some/{id}/other", "/some/${UUID.randomUUID()}/other", true, "should match with parameter-2"), - Arguments.of("/some/{id}", "/some-other/${UUID.randomUUID()}", false, "should not match with parameter-1"), - Arguments.of( - "/some/{id}/other", - "/some/${UUID.randomUUID()}/other-test", - false, - "should not match with parameter-2" - ), - Arguments.of("/some?a=1", "/some", true, "should match with query parameter 1"), - Arguments.of("/some?a=1&b=2", "/some", true, "should match with query parameter 2"), - Arguments.of( - "/some/{id}?a=1", - "/some/${UUID.randomUUID()}", - true, - "should match with path parameter and query parameter 1" - ), - Arguments.of( - "/some/{id}/other?a=1&b=2", - "/some/${UUID.randomUUID()}/other", - true, - "should match with path parameter and query parameter 2" - ), - Arguments.of( - "/some/{proxy+}", - "/some/sub/sub/sub/path", - true, - "should handle greedy path variables successfully" + fun matchTestParams() = + listOf( + Arguments.of("/some", "/some", true, "should match without parameter"), + Arguments.of("/some", "/some-other", false, "should not match simple"), + Arguments.of("/some/{id}", "/some/${UUID.randomUUID()}", true, "should match with parameter-1"), + Arguments.of("/some/{id}/other", "/some/${UUID.randomUUID()}/other", true, "should match with parameter-2"), + Arguments.of("/some/{id}", "/some-other/${UUID.randomUUID()}", false, "should not match with parameter-1"), + Arguments.of( + "/some/{id}/other", + "/some/${UUID.randomUUID()}/other-test", + false, + "should not match with parameter-2", + ), + Arguments.of("/some?a=1", "/some", true, "should match with query parameter 1"), + Arguments.of("/some?a=1&b=2", "/some", true, "should match with query parameter 2"), + Arguments.of( + "/some/{id}?a=1", + "/some/${UUID.randomUUID()}", + true, + "should match with path parameter and query parameter 1", + ), + Arguments.of( + "/some/{id}/other?a=1&b=2", + "/some/${UUID.randomUUID()}/other", + true, + "should match with path parameter and query parameter 2", + ), + Arguments.of( + "/some/{proxy+}", + "/some/sub/sub/sub/path", + true, + "should handle greedy path variables successfully", + ), ) - ) @JvmStatic @Suppress("unused") - fun extractTestParams() = listOf( - Arguments.of("/some", "/some", emptyMap(), "should extract parameters-1"), - Arguments.of( - "/some/{first}/other/{second}", - "/some/first-value/other/second-value", - mapOf("first" to "first-value", "second" to "second-value"), - "should extract parameters 2" + fun extractTestParams() = + listOf( + Arguments.of("/some", "/some", emptyMap(), "should extract parameters-1"), + Arguments.of( + "/some/{first}/other/{second}", + "/some/first-value/other/second-value", + mapOf("first" to "first-value", "second" to "second-value"), + "should extract parameters 2", + ), ) - ) @JvmStatic @Suppress("unused") - fun notAllowedGreedyPathTemplates() = listOf( - "/some/{proxy+}/and/{variable}/error", - "/{proxy+}/some/and/{variable}/error", - "/here/some/and/{proxy+}/{variable}", - "/here/some/and/{proxy+}/error", // FIXME: it should throw exception - "/here/some/and//good/good/{proxy+}/bad/bad/bad", // FIXME: it should throw exception - "/{proxy+}/{id}", - "/{proxy+}/whatever" - ) + fun notAllowedGreedyPathTemplates() = + listOf( + "/some/{proxy+}/and/{variable}/error", + "/{proxy+}/some/and/{variable}/error", + "/here/some/and/{proxy+}/{variable}", + "/here/some/and/{proxy+}/error", // FIXME: it should throw exception + "/here/some/and//good/good/{proxy+}/bad/bad/bad", // FIXME: it should throw exception + "/{proxy+}/{id}", + "/{proxy+}/whatever", + ) } }