From 89c213f593d568960eb5071b991159c22c32aa29 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Mon, 8 Jul 2019 16:34:29 +0200 Subject: [PATCH 1/2] Convert to yaml will use query params; fixes gh-1086 --- .../verifier/converter/ContractsToYaml.groovy | 21 +++++++++-- .../verifier/converter/YamlContract.groovy | 7 +++- .../DslToYamlContractConverterSpec.groovy | 18 ++++++++-- .../converter/YamlContractSpec.groovy | 36 +++++++++++++++++++ 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractSpec.groovy diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/ContractsToYaml.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/ContractsToYaml.groovy index 6871327d74..65584f06da 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/ContractsToYaml.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/ContractsToYaml.groovy @@ -16,7 +16,6 @@ package org.springframework.cloud.contract.verifier.converter - import java.util.regex.Pattern import groovy.transform.CompileStatic @@ -29,11 +28,13 @@ import org.springframework.cloud.contract.spec.internal.DslProperty import org.springframework.cloud.contract.spec.internal.ExecutionProperty import org.springframework.cloud.contract.spec.internal.FromFileProperty import org.springframework.cloud.contract.spec.internal.Headers +import org.springframework.cloud.contract.spec.internal.MatchingStrategy import org.springframework.cloud.contract.spec.internal.MatchingType import org.springframework.cloud.contract.spec.internal.Multipart import org.springframework.cloud.contract.spec.internal.NamedProperty import org.springframework.cloud.contract.spec.internal.NotToEscapePattern import org.springframework.cloud.contract.spec.internal.RegexProperty +import org.springframework.cloud.contract.spec.internal.Url import org.springframework.cloud.contract.verifier.converter.YamlContract.RegexType import org.springframework.cloud.contract.verifier.util.ContentType import org.springframework.cloud.contract.verifier.util.JsonPaths @@ -42,6 +43,7 @@ import org.springframework.cloud.contract.verifier.util.MapConverter import static org.springframework.cloud.contract.verifier.util.ContentType.XML import static org.springframework.cloud.contract.verifier.util.ContentUtils.evaluateContentType + /** * @author Marcin Grzejszczak * @author Olga Maciaszek-Sharma @@ -139,6 +141,22 @@ class ContractsToYaml { request.method = contract.request?.method?.serverValue request.url = contract.request?.url?.serverValue request.urlPath = contract.request?.urlPath?.serverValue + request.matchers = new YamlContract.StubMatchers() + Url requestUrl = contract.request.url ?: contract.request.urlPath + if (requestUrl.queryParameters != null) { + request.queryParameters = requestUrl.queryParameters + .parameters.collectEntries { + def testSide = MapConverter.getTestSideValuesForNonBody(it) + def stubSide = it.clientValue + if (stubSide instanceof RegexProperty || stubSide instanceof Pattern) { + request.matchers.queryParameters.add(new YamlContract.QueryParameterMatcher(key: it.name, type: YamlContract.MatchingType.matching, value: new RegexProperty(stubSide).pattern())) + } + else if (stubSide instanceof MatchingStrategy) { + request.matchers.queryParameters.add(new YamlContract.QueryParameterMatcher(key: it.name, type: YamlContract.MatchingType.from(stubSide.getType().name), value: MapConverter.getStubSideValuesForNonBody(stubSide))) + } + return [(it.name): testSide] + } + } request.headers = (contract.request?.headers as Headers)?.asMap { String headerName, DslProperty prop -> def testSideValue = MapConverter.getTestSideValues(prop) @@ -185,7 +203,6 @@ class ContractsToYaml { } } } - request.matchers = new YamlContract.StubMatchers() contract.request?.bodyMatchers?.matchers()?.each { BodyMatcher matcher -> request.matchers.body << new YamlContract.BodyStubMatcher( path: matcher.path(), 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 c3877673d4..edfbe2858a 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 @@ -93,7 +93,12 @@ class YamlContract { @CompileStatic enum MatchingType { equal_to, containing, matching, not_matching, equal_to_json, - equal_to_xml, absent + equal_to_xml, absent, binary_equal_to + + static MatchingType from(String string) { + return values() + .find { MatchingType type -> (type.name().replace("_", "") == string.toLowerCase().replace("_", "")) } + } } @CompileStatic diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/DslToYamlContractConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/DslToYamlContractConverterSpec.groovy index cc1f702518..5c7270388f 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/DslToYamlContractConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/DslToYamlContractConverterSpec.groovy @@ -354,7 +354,12 @@ class DslToYamlContractConverterSpec extends Specification { List contracts = [Contract.make { request { // (1) method 'PUT' // (2) - url '/fraudcheck' // (3) + urlPath('/fraudcheck') { + queryParameters { + parameter("foo", "bar") + parameter("foo2", $(c(equalToJson('''{"foo":"bar"}''')), p("foo3"))) + } + } body([ // (4) "client.id": $(regex('[0-9]{10}')), loanAmount : 99999 @@ -381,11 +386,15 @@ class DslToYamlContractConverterSpec extends Specification { yamlContracts.size() == 1 YamlContract yamlContract = yamlContracts.first() yamlContract.request.method == "PUT" - yamlContract.request.url == "/fraudcheck" + yamlContract.request.urlPath == "/fraudcheck" + yamlContract.request.queryParameters == [ + foo2: "foo3", + foo : "bar" + ] yamlContract.request.body["client.id"] =~ /[0-9]{10}/ yamlContract.request.body["loanAmount"] == 99999 yamlContract.request.headers == [ - "Content-Type": "application/json", + "Content-Type" : "application/json", "Authorization": 'Bearer SOMETOKEN' ] yamlContract.request.matchers.headers == [ @@ -398,6 +407,9 @@ class DslToYamlContractConverterSpec extends Specification { type: YamlContract.StubMatcherType.by_regex, value: "[0-9]{3}"), ] + yamlContract.request.matchers.queryParameters == [ + new YamlContract.QueryParameterMatcher(key: "foo2", type: YamlContract.MatchingType.equal_to_json, value: '''{"foo":"bar"}'''), + ] yamlContract.response.status == 200 yamlContract.response.body == [fraudCheckStatus : "FRAUD", "rejection.reason": "Amount too high"] diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractSpec.groovy new file mode 100644 index 0000000000..47c2bb92f6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractSpec.groovy @@ -0,0 +1,36 @@ +/* + * 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.verifier.converter + +import spock.lang.Specification + +class YamlContractSpec extends Specification { + + def "should convert to matching type from string"() { + when: + YamlContract.MatchingType type = YamlContract.MatchingType.from(string) + then: + type == expectedType + where: + string || expectedType + "equalTo" || YamlContract.MatchingType.equal_to + "equalToJson" || YamlContract.MatchingType.equal_to_json + "containing" || YamlContract.MatchingType.containing + "unknown" || null + } +} + From a1f308b0cf8a3d3d97b2178e17df6a93189df0a0 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Mon, 8 Jul 2019 17:06:24 +0200 Subject: [PATCH 2/2] Fixed unnecessary file renaming for scenarios when converting to yaml; fixes gh-1132 --- .../verifier/util/ContractVerifierDslConverter.groovy | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy index a82cefe54f..02b0942de6 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy @@ -34,8 +34,6 @@ import org.springframework.util.StringUtils @Commons class ContractVerifierDslConverter { - private static final String SCENARIO_MATCHER = '^[0-9].*$' - /** * @deprecated - use {@link ContractVerifierDslConverter#convertAsCollection(java.io.File, java.lang.String)} */ @@ -136,7 +134,7 @@ class ContractVerifierDslConverter { private static Collection withName(File file, Collection contracts) { int counter = 0 return contracts.collect { - if (contractNameEmpty(it) && !relatedToScenarios(file, it)) { + if (contractNameEmpty(it)) { it.name(NamesUtil.defaultContractName(file, contracts, counter)) } counter++ @@ -147,8 +145,4 @@ class ContractVerifierDslConverter { private static boolean contractNameEmpty(Contract it) { return it != null && StringUtils.isEmpty(it.name) } - - private static boolean relatedToScenarios(File file, Contract contract) { - return contract.name?.matches(SCENARIO_MATCHER) || file.name.matches(SCENARIO_MATCHER) - } }