Merge branch '2.0.x'

This commit is contained in:
Marcin Grzejszczak
2018-10-24 22:31:35 +02:00
4 changed files with 123 additions and 11 deletions

View File

@@ -1,20 +1,20 @@
package org.springframework.cloud.contract.verifier.converter
import java.nio.file.Files
import java.util.regex.Pattern
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper
import groovy.transform.CompileStatic
import groovy.transform.PackageScope
import org.yaml.snakeyaml.Yaml
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.internal.DslProperty
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
import org.springframework.cloud.contract.spec.internal.MatchingTypeValue
import org.springframework.cloud.contract.spec.internal.NamedProperty
import org.springframework.cloud.contract.spec.internal.RegexPatterns
import org.springframework.cloud.contract.spec.internal.Request
import org.yaml.snakeyaml.Yaml
import java.nio.file.Files
import java.util.regex.Pattern
/**
* @author Marcin Grzejszczak
@@ -86,10 +86,10 @@ class YamlToContracts {
yamlContract.request.queryParameters.each { String key, Object value ->
if (value instanceof List) {
((List) value).each {
parameter(key, it)
parameter(key, queryParamValue(yamlContract, key, it))
}
} else {
parameter(key, value)
parameter(key, queryParamValue(yamlContract, key, value))
}
}
}
@@ -202,8 +202,15 @@ class YamlToContracts {
case YamlContract.StubMatcherType.by_equality:
value = byEquality()
break
case YamlContract.StubMatcherType.by_null:
// do nothing
break
default:
throw new UnsupportedOperationException("The type [" + matcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
}
if (value) {
jsonPath(matcher.path, value)
}
jsonPath(matcher.path, value)
}
}
}
@@ -282,6 +289,8 @@ class YamlToContracts {
case YamlContract.TestMatcherType.by_null:
value = byNull()
break
default:
throw new UnsupportedOperationException("The type [" + testMatcher.type + "] is unsupported. Hint: If you're using <predefined> remember to pass <type: by_regex>")
}
if (testMatcher.path) {
jsonPath(testMatcher.path, value)
@@ -451,6 +460,33 @@ class YamlToContracts {
return clientValue
}
protected Object queryParamValue(YamlContract yamlContract, String key, Object value) {
Request request = new Request()
YamlContract.QueryParameterMatcher matcher = yamlContract.request.
matchers.queryParameters.find { it.key == key}
if (!matcher) {
return value
}
switch (matcher.type) {
case YamlContract.MatchingType.equal_to:
return new DslProperty(request.equalTo(matcher.value), value)
case YamlContract.MatchingType.containing:
return new DslProperty(request.containing(matcher.value), value)
case YamlContract.MatchingType.matching:
return new DslProperty(request.matching(matcher.value), value)
case YamlContract.MatchingType.not_matching:
return new DslProperty(request.notMatching(matcher.value), value)
case YamlContract.MatchingType.equal_to_json:
return new DslProperty(request.equalToJson(matcher.value), value)
case YamlContract.MatchingType.equal_to_xml:
return new DslProperty(request.equalToXml(matcher.value), value)
case YamlContract.MatchingType.absent:
return new DslProperty(request.absent(), null)
default:
throw new UnsupportedOperationException("The provided matching type [" + matcher + "] is unsupported. Use on of " + YamlContract.MatchingType.values())
}
}
protected Object serverValue(Object value, YamlContract.KeyValueMatcher matcher) {
Object serverValue = value
if (matcher?.command) {
@@ -499,6 +535,8 @@ class YamlToContracts {
return patterns.nonEmpty()
case YamlContract.PredefinedRegex.non_blank:
return patterns.nonBlank()
default:
throw new UnsupportedOperationException("The predefined regex [" + predefinedRegex + "] is unsupported. Use on of " + YamlContract.PredefinedRegex.values())
}
}

View File

@@ -16,6 +16,8 @@
package org.springframework.cloud.contract.verifier.converter
import org.springframework.cloud.contract.spec.internal.MatchingStrategy
import org.springframework.cloud.contract.spec.internal.QueryParameters
import spock.lang.Issue
import java.util.regex.Pattern
@@ -187,6 +189,22 @@ class YamlContractConverterSpec extends Specification {
RegexPatterns patterns = new RegexPatterns()
contract.request.headers.entries.find { it.name == "Content-Type" &&
((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json" }
contract.request.urlPath.queryParameters.parameters.size() == 8
QueryParameters queryParameters = contract.request.urlPath.queryParameters
assertQueryParam(queryParameters, "limit", 10,
MatchingStrategy.Type.EQUAL_TO, 20)
assertQueryParam(queryParameters, "offset", 20,
MatchingStrategy.Type.CONTAINS, 20)
assertQueryParam(queryParameters, "sort", "name",
MatchingStrategy.Type.EQUAL_TO, "name")
assertQueryParam(queryParameters, "search", 55,
MatchingStrategy.Type.NOT_MATCHING, (~/^[0-9]{2}$/).pattern())
assertQueryParam(queryParameters, "age", 99,
MatchingStrategy.Type.NOT_MATCHING, "^\\\\w*\$")
assertQueryParam(queryParameters, "name", "John.Doe",
MatchingStrategy.Type.MATCHING, "John.*")
assertQueryParam(queryParameters, "hello", true,
MatchingStrategy.Type.ABSENT, null)
contract.request.bodyMatchers.jsonPathRegexMatchers[0].path() == '$.duck'
contract.request.bodyMatchers.jsonPathRegexMatchers[0].matchingType() == MatchingType.REGEX
contract.request.bodyMatchers.jsonPathRegexMatchers[0].value() == '[0-9]{3}'
@@ -264,6 +282,17 @@ class YamlContractConverterSpec extends Specification {
contract.response.bodyMatchers.jsonPathRegexMatchers[15].value() == new ExecutionProperty('assertThatValueIsANumber($it)')
}
protected Object assertQueryParam(QueryParameters queryParameters, String queryParamName, Object serverValue,
MatchingStrategy.Type clientType, Object clientValue) {
if (clientType == MatchingStrategy.Type.ABSENT) {
return ! queryParameters.parameters.find { it.name == queryParamName}
}
return queryParameters.parameters.find { it.name == queryParamName &&
it.serverValue == serverValue &&
((MatchingStrategy) it.clientValue).type == clientType &&
((MatchingStrategy) it.clientValue).clientValue == clientValue }
}
@Issue("#604")
def "should convert YAML with Message matchers to DSL"() {
given:

View File

@@ -209,5 +209,10 @@ class WireMockResponseStubStrategySpec extends Specification {
subject.buildClientRequestContent()
then:
noExceptionThrown()
when:
def response = new WireMockResponseStubStrategy(contract)
response.buildClientResponseContent()
then:
noExceptionThrown()
}
}

View File

@@ -1,6 +1,19 @@
request:
method: GET
urlPath: /get
urlPath: /get/1
headers:
Content-Type: application/json
cookies:
foo: 2
queryParameters:
limit: 10
offset: 20
filter: 'email'
sort: name
search: 55
age: 99
name: John.Doe
email: 'bob@email.com'
body:
duck: 123
alpha: "abc"
@@ -15,6 +28,35 @@ request:
"complex.key": 'foo'
nullValue: null
matchers:
url:
regex: /get/[0-9]
# predefined:
# execute a method
# command:
queryParameters:
- key: limit
type: equal_to
value: 20
- key: offset
type: containing
value: 20
- key: sort
type: equal_to
value: name
- key: search
type: not_matching
value: '^[0-9]{2}$'
- key: age
type: not_matching
value: '^\\w*$'
- key: name
type: matching
value: 'John.*'
- key: hello
type: absent
cookies:
- key: foo
regex: '[0-9]'
headers:
- key: Content-Type
regex: "application/json.*"
@@ -45,8 +87,6 @@ request:
type: by_equality
- path: $.nullvalue
type: by_null
headers:
Content-Type: application/json
response:
status: 200
body: