Merge branch '2.1.x'
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.util
|
||||
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import com.jayway.jsonpath.DocumentContext
|
||||
@@ -42,6 +43,7 @@ import org.springframework.util.SerializationUtils
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Tim Ysewyn
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Commons
|
||||
class JsonToJsonPathsConverter {
|
||||
@@ -54,7 +56,7 @@ class JsonToJsonPathsConverter {
|
||||
|
||||
private static final Boolean SERVER_SIDE = false
|
||||
private static final Boolean CLIENT_SIDE = true
|
||||
private static final String ANY_ARRAY_NOTATION_IN_JSONPATH = "[*]"
|
||||
private static final Pattern ANY_ARRAY_NOTATION_IN_JSONPATH = ~/\[(.*?)\]/
|
||||
private static final String DESCENDANT_OPERATOR = ".."
|
||||
|
||||
private final boolean assertJsonSize
|
||||
@@ -132,7 +134,7 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Related to #391. The converted body looks different when done via the String notation than
|
||||
* Related to #391 and #1091. The converted body looks different when done via the String notation than
|
||||
* it does when done via a map notation. When working with String body and when matchers
|
||||
* are provided, even when all entries of a map / list got removed, the map / list itself
|
||||
* remains. That leads to unnecessary creation of checks for empty collection. With this method
|
||||
@@ -141,9 +143,10 @@ class JsonToJsonPathsConverter {
|
||||
* defining body...
|
||||
*/
|
||||
private static boolean removeTrailingContainers(String matcherPath, DocumentContext context) {
|
||||
boolean containsArray = matcherPath.contains(ANY_ARRAY_NOTATION_IN_JSONPATH)
|
||||
String pathWithoutAnyArray = containsArray ? matcherPath.substring(0, matcherPath.
|
||||
lastIndexOf(ANY_ARRAY_NOTATION_IN_JSONPATH)) : matcherPath
|
||||
Matcher matcher = ANY_ARRAY_NOTATION_IN_JSONPATH.matcher(matcherPath)
|
||||
boolean containsArray = matcher.find()
|
||||
String pathWithoutAnyArray = containsArray ? matcherPath.
|
||||
substring(0, matcherPath.lastIndexOf(lastMatch(matcher))) : matcherPath
|
||||
def object = entry(context, pathWithoutAnyArray)
|
||||
// object got removed and it was the only element
|
||||
// let's get its parent and see if it contains an empty element
|
||||
@@ -170,6 +173,15 @@ class JsonToJsonPathsConverter {
|
||||
return false
|
||||
}
|
||||
|
||||
private static String lastMatch(Matcher matcher) {
|
||||
List<String> matches = []
|
||||
while ({
|
||||
matches << matcher.group()
|
||||
matcher.find()
|
||||
}()) continue
|
||||
return matches[matches.size() - 1]
|
||||
}
|
||||
|
||||
private static boolean isIterable(Object object) {
|
||||
return object instanceof Iterable || object instanceof Map
|
||||
}
|
||||
|
||||
@@ -623,4 +623,118 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
|
||||
}
|
||||
}
|
||||
|
||||
@Issue('#1091')
|
||||
def 'should work for map with array value where matchers cover all array fields for [#methodBuilderName]'() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
name "ISSUE 1091"
|
||||
method 'GET'
|
||||
url '/test'
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
body('''
|
||||
{
|
||||
"prices": [
|
||||
{
|
||||
"country" : "ES",
|
||||
"originalPrice": "1500"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
'''
|
||||
)
|
||||
bodyMatchers {
|
||||
jsonPath('$.prices[0].country', byRegex(nonBlank()))
|
||||
jsonPath('$.prices[0].originalPrice', byRegex(number()))
|
||||
}
|
||||
headers {
|
||||
contentType(applicationJsonUtf8())
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodBodyBuilder builder = methodBuilder(contractDsl)
|
||||
BlockBuilder blockBuilder = new BlockBuilder(" ")
|
||||
and:
|
||||
builder.appendTo(blockBuilder)
|
||||
String test = blockBuilder.toString()
|
||||
when:
|
||||
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
|
||||
then:
|
||||
!test.contains('isEmpty()')
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
}
|
||||
|
||||
@Issue('#1091')
|
||||
def 'should work for array containing map with array value where matchers cover all array fields for [#methodBuilderName]'() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
name "ISSUE 1091"
|
||||
method 'GET'
|
||||
url '/test'
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
body('''
|
||||
{
|
||||
"test": [
|
||||
{
|
||||
"prices": [
|
||||
{
|
||||
"country" : "ES",
|
||||
"originalPrice": 1500
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
'''
|
||||
)
|
||||
bodyMatchers {
|
||||
jsonPath('$.test[0].barcode', byRegex(nonBlank()))
|
||||
jsonPath('$.test[0].id', byRegex(nonBlank()))
|
||||
jsonPath('$.test[0].prices[0].country', byRegex(nonBlank()))
|
||||
jsonPath('$.test[0].prices[0].originalPrice', byRegex(nonBlank()))
|
||||
jsonPath('$.test[0].prices[?(@.originalPrice==1500)].originalPrice',
|
||||
byRegex(nonBlank()))
|
||||
}
|
||||
headers {
|
||||
contentType(applicationJsonUtf8())
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodBodyBuilder builder = methodBuilder(contractDsl)
|
||||
BlockBuilder blockBuilder = new BlockBuilder(" ")
|
||||
and:
|
||||
builder.appendTo(blockBuilder)
|
||||
String test = blockBuilder.toString()
|
||||
when:
|
||||
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
|
||||
then:
|
||||
!test.contains('isEmpty()')
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user