diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy index df528651fe..468923744c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy @@ -43,6 +43,7 @@ class YamlContract { public String urlPath public Map queryParameters = [:] public Map headers = [:] + public Map cookies = [:] public Object body public String bodyFromFile public StubMatchers matchers = new StubMatchers() @@ -66,6 +67,7 @@ class YamlContract { static class StubMatchers { public List body = [] public List headers = [] + public List cookies = [] public MultipartStubMatcher multipart } @@ -121,6 +123,14 @@ class YamlContract { public PredefinedRegex predefined } + @CompileStatic + static class TestCookieMatcher { + public String key + public String regex + public String command + public PredefinedRegex predefined + } + @CompileStatic static enum PredefinedRegex { only_alpha_unicode, number, any_boolean, ip_address, hostname, @@ -142,6 +152,7 @@ class YamlContract { static class Response { public int status public Map headers = [:] + public Map cookies = [:] public Object body public String bodyFromFile public TestMatchers matchers = new TestMatchers() @@ -152,6 +163,7 @@ class YamlContract { static class TestMatchers { public List body = [] public List headers = [] + public List cookies = [] } @CompileStatic diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy index 9f9b759d17..11a18e8e32 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy @@ -45,6 +45,7 @@ import org.springframework.cloud.contract.verifier.converter.YamlContract.KeyVal import org.springframework.cloud.contract.verifier.converter.YamlContract.StubMatcherType import org.springframework.cloud.contract.verifier.converter.YamlContract.StubMatchers import org.springframework.cloud.contract.verifier.converter.YamlContract.TestHeaderMatcher +import org.springframework.cloud.contract.verifier.converter.YamlContract.TestCookieMatcher import org.springframework.cloud.contract.verifier.converter.YamlContract.TestMatcherType import org.springframework.cloud.contract.verifier.util.MapConverter @@ -132,6 +133,16 @@ class YamlContractConverter implements ContractConverter> { } } } + if (yamlContract.request?.cookies) { + cookies { + yamlContract.request?.cookies?.each { String key, Object value -> + KeyValueMatcher matcher = yamlContract.request.matchers.cookies.find { it.key == key } + Object clientValue = clientValue(value, matcher, key) + + cookie(key, new DslProperty(clientValue, value)) + } + } + } if (yamlContract.request.body) body(yamlContract.request.body) if (yamlContract.request.bodyFromFile) body(file(yamlContract.request.bodyFromFile)) if (yamlContract.request.multipart) { @@ -211,6 +222,16 @@ class YamlContractConverter implements ContractConverter> { } } } + if (yamlContract.response?.cookies) { + cookies { + yamlContract.response?.cookies?.each { String key, Object value -> + TestCookieMatcher matcher = yamlContract.response.matchers.cookies.find { it.key == key } + Object serverValue = serverCookieValue(value, matcher, key) + + cookie(key, new DslProperty(value, serverValue)) + } + } + } if (yamlContract.response.body) body(yamlContract.response.body) if (yamlContract.response.bodyFromFile) body(file(yamlContract.response.bodyFromFile)) if (yamlContract.response.async) async() @@ -381,6 +402,20 @@ class YamlContractConverter implements ContractConverter> { return serverValue } + protected Object serverCookieValue(Object value, TestCookieMatcher matcher, String key) { + Object serverValue = value + if (matcher?.regex) { + serverValue = Pattern.compile(matcher.regex) + Pattern pattern = (Pattern) serverValue + assertPatternMatched(pattern, value, key) + } else if (matcher?.predefined) { + Pattern pattern = predefinedToPattern(matcher.predefined) + serverValue = pattern + assertPatternMatched(pattern, value, key) + } + return serverValue + } + protected Object clientValue(Object value, KeyValueMatcher matcher, String key) { Object clientValue = value if (matcher?.regex) { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy index 02d67a9506..0d6bd5d4b3 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy @@ -58,8 +58,34 @@ class YamlContractConverterSpec extends Specification { File ymlMultiple = new File(ymlMultipleFile.toURI()) URL ymlMessagingMatchersFile = YamlContractConverterSpec.getResource("/yml/contract_message_matchers.yml") File ymlMessagingMatchers = new File(ymlMessagingMatchersFile.toURI()) + URL ymlCookiesUrl = YamlContractConverterSpec.getResource("/yml/contract_cookies.yml") + File ymlCookies = new File(ymlCookiesUrl.toURI()) YamlContractConverter converter = new YamlContractConverter() + def "should convert YAML with Cookies to DSL"() { + given: + assert converter.isAccepted(ymlCookies) + when: + Collection contracts = converter.convertFrom(ymlCookies) + then: + contracts.size() == 1 + Contract contract = contracts.first() + contract.description == "Contract with cookies" + contract.name == "cookies-contract" + contract.priority == 1 + contract.ignored == true + contract.request.method.clientValue == "PUT" + contract.request.url.clientValue == "/foo" + contract.request.cookies.entries.find { it.key == "foo" && it.serverValue == "bar" } + contract.request.cookies.entries.find { it.key == "fooRegex" && ((Pattern) it.clientValue).pattern == "reg" && it.serverValue == "reg" } + and: + contract.response.status.clientValue == 200 + contract.response.cookies.entries.find { it.key == "foo" && it.clientValue == "baz" } + contract.response.cookies.entries.find { it.key == "fooRegex" && ((Pattern) it.serverValue).pattern == "[0-9]+" && it.clientValue == 123 } + contract.response.cookies.entries.find { it.key == "source" && ((Pattern) it.serverValue).pattern == "ip_address" && it.clientValue == "ip_address" } + contract.response.body.clientValue == ["status": "OK"] + } + def "should convert YAML with REST to DSL for [#yamlFile]"() { given: assert converter.isAccepted(yamlFile) diff --git a/spring-cloud-contract-verifier/src/test/resources/yml/contract_cookies.yml b/spring-cloud-contract-verifier/src/test/resources/yml/contract_cookies.yml new file mode 100644 index 0000000000..24c68802d0 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/yml/contract_cookies.yml @@ -0,0 +1,28 @@ +description: Contract with cookies +name: cookies-contract +priority: 1 +ignored: true +request: + method: PUT + url: /foo + cookies: + foo: bar + fooRegex: reg + matchers: + cookies: + - key: fooRegex + regex: reg +response: + status: 200 + cookies: + foo: baz + fooRegex: 123 + source: ip_address + body: + status: OK + matchers: + cookies: + - key: fooRegex + regex: "[0-9]+" + - key: source + regex: ip_address