From 232634090bd9ebf278e3cf86d44b59803ba49745 Mon Sep 17 00:00:00 2001 From: Tim Ysewyn Date: Fri, 9 Aug 2019 23:42:58 +0200 Subject: [PATCH] Reworked DSL for cookies --- .../fraudname/shouldReturnACookie.kts | 10 ++- .../cloud/contract/spec/internal/CookieDsl.kt | 29 ++++++ .../contract/spec/internal/CookiesDsl.kt | 48 ++++++++++ .../contract/spec/internal/RequestDsl.kt | 22 ++++- .../contract/spec/internal/ResponseDsl.kt | 24 ++++- .../cloud/contract/spec/ContractTests.kt | 89 +++++++++++++++++++ 6 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt create mode 100644 specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt diff --git a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts index 308bd83607..4ba135dc42 100644 --- a/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts +++ b/samples/standalone/kotlin/http-server/src/test/resources/contracts/fraudname/shouldReturnACookie.kts @@ -24,8 +24,14 @@ contract { method = GET url = url("/frauds/name") cookies { - cookie("name", "foo") - cookie(mapOf("name2" to "bar")) + cookie { + name = "name" + value = "foo" + } + cookie{ + name = "name2" + value = "bar" + } } } response { diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt new file mode 100644 index 0000000000..da71232d76 --- /dev/null +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookieDsl.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.spec.internal + +import kotlin.properties.Delegates + +/** + * @author Tim Ysewyn + */ +class CookieDsl { + + var name: String by Delegates.notNull() + + var value: Any by Delegates.notNull() +} diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt new file mode 100644 index 0000000000..de6f34cd98 --- /dev/null +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/CookiesDsl.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.spec.internal + +/** + * @author Tim Ysewyn + */ +open class CookiesDsl : CommonDsl() { + + private val cookies = LinkedHashMap() + + open fun matching(value: Any?): Any? = value + + /** + * Adds and configures a cookie. + * + * @param configurer The lambda to configure the cookie. + */ + fun cookie(configurer: CookieDsl.() -> Unit) { + try { + val cookie = CookieDsl().apply(configurer) + this.cookies[cookie.name] = cookie.value + } catch (ex: IllegalStateException) { + throw IllegalStateException("Cookie is missing its name or value") + } + } + + internal fun get(): Cookies { + val cookies = Cookies() + this.cookies.forEach { (name, value) -> cookies.cookie(name, value) } + return cookies + } + +} diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt index 959ab88333..d0a843a354 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/RequestDsl.kt @@ -54,8 +54,8 @@ open class RequestDsl : CommonDsl(), RegexCreatingProperty { this.headers = RequestHeadersDsl().apply(headers).get() } - fun cookies(cookies: Cookies.() -> Unit) { - this.cookies = Request.RequestCookies().apply(cookies) + fun cookies(cookies: CookiesDsl.() -> Unit) { + this.cookies = RequestCookiesDsl().apply(cookies).get() } fun body(body: Map) = Body(body.toDslProperties()) @@ -266,4 +266,22 @@ open class RequestDsl : CommonDsl(), RegexCreatingProperty { } } + + private class RequestCookiesDsl: CookiesDsl() { + + private val common = Common() + + override fun matching(value: Any?): Any? { + return value?.also { + return when(value) { + is String -> this.common.value( + c(regex(RegexpUtils.escapeSpecialRegexWithSingleEscape(value) + ".*")), + p(value) + ) + else -> value + } + } + } + + } } \ No newline at end of file diff --git a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt index 92e1af647c..50727468f0 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/main/kotlin/org/springframework/cloud/contract/spec/internal/ResponseDsl.kt @@ -45,9 +45,9 @@ class ResponseDsl : CommonDsl(), RegexCreatingProperty { this.headers = ResponseHeadersDsl().apply(headers).get() } - fun cookies(cookies: Cookies.() -> Unit) { - this.cookies = Response.ResponseCookies().apply(cookies) - } + fun cookies(cookies: CookiesDsl.() -> Unit) { + this.cookies = ResponseCookiesDsl().apply(cookies).get() + } fun body(body: Map) = Body(body.toDslProperties()) @@ -305,4 +305,22 @@ class ResponseDsl : CommonDsl(), RegexCreatingProperty { } } + + private class ResponseCookiesDsl: CookiesDsl() { + + private val common = Common() + + override fun matching(value: Any?): Any? { + return value?.also { + return when(value) { + is String -> return this.common.value( + c(value), + p(regex(RegexpUtils.escapeSpecialRegexWithSingleEscape(value) + ".*")) + ) + else -> value + } + } + } + + } } diff --git a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt index 30c27dde5b..ae957edcc8 100644 --- a/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt +++ b/specs/spring-cloud-contract-spec-kotlin/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt @@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract +import org.springframework.cloud.contract.spec.internal.Cookie import org.springframework.cloud.contract.spec.internal.RegexProperty /** @@ -701,4 +702,92 @@ then: } } + @Test + fun `should work with cookies`() { + val contract = contract { + request { + method = GET + url = url("/cookie") + cookies { + cookie { + name = "name" + value = "foo" + } + cookie { + name = "name2" + value = "bar" + } + } + } + response { + status = OK + cookies { + cookie { + name = "name" + value = "foo" + } + cookie { + name = "name2" + value = "bar" + } + } + } + } + + assertDoesNotThrow { + Contract.assertContract(contract) + }.also { + val request = contract.request + val cookies = request.cookies.entries + assertThat(cookies).hasSize(2) + assertThat(cookies).containsExactlyInAnyOrder(Cookie.build("name", "foo"), Cookie.build("name2", "bar")) + }.also { + val response = contract.response + val cookies = response.cookies.entries + assertThat(cookies).hasSize(2) + assertThat(cookies).containsExactlyInAnyOrder(Cookie.build("name", "foo"), Cookie.build("name2", "bar")) + } + } + + @Test + fun `should throw error when cookie is not configured correctly`() { + assertThrows { + contract { + request { + method = GET + url = url("/cookie") + cookies { + cookie { + value = "bar" + } + } + } + response { + status = OK + } + } + }.also { + assertThat(it.message).contains("Cookie is missing its name or value") + } + + assertThrows { + contract { + request { + method = GET + url = url("/cookie") + cookies { + cookie { + name = "foo" + } + } + } + response { + status = OK + } + } + }.also { + assertThat(it.message).contains("Cookie is missing its name or value") + } + } + } \ No newline at end of file