Added recursive check for empty arrays; fixes gh-727
This commit is contained in:
@@ -55,6 +55,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 String DESCENDANT_OPERATOR = ".."
|
||||
|
||||
private final ContractVerifierConfigProperties configProperties
|
||||
|
||||
@@ -87,7 +88,7 @@ class JsonToJsonPathsConverter {
|
||||
def entry = entry(context, matcher.path())
|
||||
if (entry != null) {
|
||||
context.delete(matcher.path())
|
||||
removeTrailingContainers(matcher, context)
|
||||
removeTrailingContainers(matcher.path(), context)
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -131,21 +132,26 @@ class JsonToJsonPathsConverter {
|
||||
* remove that trailing collection. All in all it's better to use the Groovy based notation for
|
||||
* defining body...
|
||||
*/
|
||||
private static void removeTrailingContainers(BodyMatcher matcher, DocumentContext context) {
|
||||
String pathWithoutAnyArray = matcher.path().contains(ANY_ARRAY_NOTATION_IN_JSONPATH) ? matcher.path().substring(0, matcher.path().lastIndexOf(ANY_ARRAY_NOTATION_IN_JSONPATH)) : matcher.path()
|
||||
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
|
||||
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
|
||||
if (isIterable(object) && containsOnlyEmptyElements(object)) {
|
||||
if (isIterable(object) && containsOnlyEmptyElements(object) && isNotRootArray(matcherPath)) {
|
||||
String pathToDelete = pathToDelete(pathWithoutAnyArray)
|
||||
context.delete(pathToDelete)
|
||||
return pathToDelete.contains(DESCENDANT_OPERATOR) ? false :
|
||||
removeTrailingContainers(pathToDelete, context)
|
||||
} else {
|
||||
String lastParent = matcher.path().substring(0, matcher.path().lastIndexOf("."))
|
||||
String lastParent = matcherPath.substring(0, matcherPath.lastIndexOf("."))
|
||||
def lastParentObject = context.read(lastParent)
|
||||
if (isIterable(lastParentObject) && containsOnlyEmptyElements(lastParentObject)) {
|
||||
if (isIterable(lastParentObject) && containsOnlyEmptyElements(lastParentObject) && isNotRoot(lastParent)) {
|
||||
context.delete(lastParent)
|
||||
return removeTrailingContainers(lastParent, context)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private static boolean isIterable(Object object) {
|
||||
@@ -157,6 +163,16 @@ class JsonToJsonPathsConverter {
|
||||
return pathWithoutAnyArray == '$' ? '$[*]' : pathWithoutAnyArray
|
||||
}
|
||||
|
||||
private static boolean isNotRoot(String path) {
|
||||
// we can't remove root
|
||||
return path != '$'
|
||||
}
|
||||
|
||||
private static boolean isNotRootArray(String path) {
|
||||
// we can't remove root
|
||||
return path != '$[*]'
|
||||
}
|
||||
|
||||
private static boolean containsOnlyEmptyElements(Object object) {
|
||||
return object.every {
|
||||
if (it instanceof Map) {
|
||||
|
||||
@@ -1219,4 +1219,47 @@ DocumentContext parsedJson = JsonPath.parse(json);
|
||||
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
|
||||
}
|
||||
|
||||
@Issue("#727")
|
||||
def "should not leave empty arrays in a simple structure [#methodBuilderName]"() {
|
||||
given:
|
||||
Contract contractDsl = Contract.make {
|
||||
request {
|
||||
method 'GET'
|
||||
url '/list'
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body(
|
||||
[
|
||||
content: [
|
||||
three: [
|
||||
six: "seven"
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
bodyMatchers {
|
||||
jsonPath('$.content.three.six', byRegex(".*seven.*"))
|
||||
jsonPath('$.content.one', byRegex(".*two.*"))
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodBodyBuilder builder = methodBuilder(contractDsl)
|
||||
BlockBuilder blockBuilder = new BlockBuilder(" ")
|
||||
when:
|
||||
builder.appendTo(blockBuilder)
|
||||
then:
|
||||
String test = blockBuilder.toString()
|
||||
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
|
||||
!test.contains('''.isEmpty()''')
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
|
||||
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
|
||||
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) }
|
||||
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user