Issues wrong arrayfield (#272)

* Bumped up jsonassert to 0.4.3
* Added a fix (?) for arrays of primitives - the tests pass ;)

fixes #271
This commit is contained in:
Marcin Grzejszczak
2016-05-11 12:16:29 +02:00
parent 38cc614fc7
commit a409a94005
8 changed files with 142 additions and 90 deletions

View File

@@ -117,48 +117,40 @@ class DslToWireMockClientConverterSpec extends Specification {
{
"request" : {
"url" : "/api/12",
"method" : "PUT",
"bodyPatterns" : [ {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.country == 'United States')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.name == 'Washington')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box[?(@.type == 'Polygon')]"
}, {
"matchesJsonPath" : "$[*][?(@.id_str == '492967299297845248')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.country_code == 'US')]"
}, {
"matchesJsonPath" : "$[*][?(@.id == 492967299297845248)]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.id == '01fbe706f872cb32')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.url == 'http://api.twitter.com/1/geo/id/01fbe706f872cb32.json')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]"
}, {
"matchesJsonPath" : "$[*][?(@.text == 'Gonna see you at Warsaw')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.place_type == 'city')]"
}, {
"matchesJsonPath" : "$[*][?(@.created_at == 'Sat Jul 26 09:38:57 +0000 2014')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.full_name == 'Washington, DC')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]"
} ],
"method" : "PUT",
"bodyPatterns" : [ {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]"
}, {
"matchesJsonPath" : "$[*][?(@.text == 'Gonna see you at Warsaw')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.place_type == 'city')]"
}, {
"matchesJsonPath" : "$[*][?(@.id == 492967299297845248)]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.country == 'United States')]"
}, {
"matchesJsonPath" : "$[*][?(@.id_str == '492967299297845248')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.name == 'Washington')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box[?(@.type == 'Polygon')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.url == 'http://api.twitter.com/1/geo/id/01fbe706f872cb32.json')]"
}, {
"matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]"
}, {
"matchesJsonPath" : "$[*].place[?(@.country_code == 'US')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.full_name == 'Washington, DC')]"
}, {
"matchesJsonPath" : "$[*][?(@.created_at == 'Sat Jul 26 09:38:57 +0000 2014')]"
}, {
"matchesJsonPath" : "$[*].place[?(@.id == '01fbe706f872cb32')]"
} ],
"headers" : {
"Content-Type" : {
"equalTo" : "application/vnd.com.ofg.twitter-places-analyzer.v1+json"
@@ -207,7 +199,7 @@ class DslToWireMockClientConverterSpec extends Specification {
{"request":{"urlPath":"/foos","method":"GET"},"response":{"body":"[{\\"id\\":\\"123\\"},{\\"id\\":\\"567\\"}]"}}
''', json, false)
}
def 'should convert dsl to wiremock to show it in the docs'() {
given:
def converter = new DslToWireMockClientConverter()
@@ -272,5 +264,5 @@ class DslToWireMockClientConverterSpec extends Specification {
// end::wiremock[]
, json, false)
}
}

View File

@@ -2,6 +2,8 @@ package io.codearte.accurest.util;
import com.toomuchcoding.jsonassert.JsonVerifiable;
import java.util.LinkedList;
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
/**
@@ -10,17 +12,17 @@ import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
private final JsonVerifiable delegate;
private final StringBuffer methodsBuffer;
private final LinkedList<String> methodsBuffer;
DelegatingJsonVerifiable(JsonVerifiable delegate,
StringBuffer methodsBuffer) {
LinkedList<String> methodsBuffer) {
this.delegate = delegate;
this.methodsBuffer = new StringBuffer(methodsBuffer.toString());
this.methodsBuffer = new LinkedList<String>(methodsBuffer);
}
DelegatingJsonVerifiable(JsonVerifiable delegate) {
this.delegate = delegate;
this.methodsBuffer = new StringBuffer();
this.methodsBuffer = new LinkedList<String>();
}
private static String stringWithEscapedQuotes(Object object) {
@@ -35,8 +37,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
}
private void appendMethodWithValue(String methodName, Object value) {
methodsBuffer.append(".").append(methodName).append("(").append(value)
.append(")");
methodsBuffer.offer("." + methodName + "(" + value + ")");
}
private void appendMethodWithQuotedValue(String methodName, Object value) {
@@ -48,7 +49,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(delegate.contains(value), methodsBuffer);
verifiable.appendMethodWithQuotedValue("contains", value);
if (isAssertingAValueInArray()) {
verifiable.methodsBuffer.append(".value()");
verifiable.methodsBuffer.offer(".value()");
}
return verifiable;
}
@@ -91,14 +92,14 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
@Override
public MethodBufferingJsonVerifiable arrayField() {
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.arrayField(), methodsBuffer);
verifiable.methodsBuffer.append(".arrayField()");
verifiable.methodsBuffer.offer(".arrayField()");
return verifiable;
}
@Override
public MethodBufferingJsonVerifiable array() {
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.array(), methodsBuffer);
verifiable.methodsBuffer.append(".array()");
verifiable.methodsBuffer.offer(".array()");
return verifiable;
}
@@ -110,8 +111,11 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
@Override
public MethodBufferingJsonVerifiable isEqualTo(String value) {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer);
if (delegate.isAssertingAValueInArray()) {
readyToCheck.methodsBuffer.append(".value()");
if (delegate.isAssertingAValueInArray() && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) {
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
readyToCheck.methodsBuffer.offer(".value()");
} else if (delegate.isAssertingAValueInArray() && !readyToCheck.methodsBuffer.peekLast().contains("array")) {
readyToCheck.methodsBuffer.offer(".value()");
} else {
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
}
@@ -129,18 +133,25 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
@Override
public MethodBufferingJsonVerifiable isEqualTo(Number value) {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer);
if (delegate.isAssertingAValueInArray()) {
readyToCheck.methodsBuffer.append(".value()");
// related to #271 - the problem is with asserting arrays of maps vs arrays of primitives
String last = readyToCheck.methodsBuffer.peekLast();
boolean containsAMatcher = containsAnyMatcher(last);
if (delegate.isAssertingAValueInArray() && containsAMatcher) {
readyToCheck.methodsBuffer.offer(".value()");
} else {
readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value));
}
return readyToCheck;
}
private boolean containsAnyMatcher(String string) {
return string.contains("isEqualTo") || string.contains("matches") || string.contains("isNull");
}
@Override
public MethodBufferingJsonVerifiable isNull() {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isNull(), methodsBuffer);
readyToCheck.methodsBuffer.append(".isNull()");
readyToCheck.methodsBuffer.offer(".isNull()");
return readyToCheck;
}
@@ -149,7 +160,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.matches(value), methodsBuffer);
if (delegate.isAssertingAValueInArray()) {
readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value));
readyToCheck.methodsBuffer.append(".value()");
readyToCheck.methodsBuffer.offer(".value()");
} else {
readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value));
}
@@ -160,7 +171,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
public MethodBufferingJsonVerifiable isEqualTo(Boolean value) {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(delegate.isEqualTo(value), methodsBuffer);
if (delegate.isAssertingAValueInArray()) {
readyToCheck.methodsBuffer.append(".value()");
readyToCheck.methodsBuffer.offer(".value()");
} else {
readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value));
}
@@ -204,7 +215,16 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
@Override
public String method() {
return methodsBuffer.toString();
return createMethodString();
}
private String createMethodString() {
LinkedList<String> queue = new LinkedList<String>(methodsBuffer);
StringBuilder stringBuffer = new StringBuilder();
while (!queue.isEmpty()) {
stringBuffer.append(queue.remove());
}
return stringBuffer.toString();
}
@Override

View File

@@ -2,18 +2,20 @@ package io.codearte.accurest.util;
import com.toomuchcoding.jsonassert.JsonVerifiable;
import java.util.LinkedList;
/**
* @author Marcin Grzejszczak
*/
class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate,
StringBuffer methodsBuffer) {
LinkedList<String> methodsBuffer) {
super(delegate, methodsBuffer);
}
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate) {
super(delegate, new StringBuffer());
super(delegate, new LinkedList<String>());
}
}

View File

@@ -62,17 +62,25 @@ class JsonToJsonPathsConverter {
// JSON with a list of primitives ["a", "b", "c"] in root issue #266
} else if (key.isIteratingOverNamelessArray() && value instanceof List && listContainsOnlyPrimitives(value)) {
value.each {
traverseRecursively(Object, key.arrayField().contains(it), it, closure)
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(it)),
ContentUtils.returnParsedObject(it), closure)
}
// JSON containing list of primitives { "partners":[ { "role":"AGENT", "payment_methods":[ "BANK", "CASH" ] } ]
} else if (value instanceof List && listContainsOnlyPrimitives(value)) {
value.each {
traverseRecursively(Object, valueToAsserter(key.arrayField(), ContentUtils.returnParsedObject(it)),
ContentUtils.returnParsedObject(it), closure)
}
} else if (value instanceof List) {
MethodBufferingJsonVerifiable jsonPathVerifiable = createAsserterFromList(key, value)
value.each { def element ->
traverseRecursively(List, createAsserterFromListElement(jsonPathVerifiable, element),
element, closure)
traverseRecursively(List, createAsserterFromListElement(jsonPathVerifiable, ContentUtils.returnParsedObject(element)),
ContentUtils.returnParsedObject(element), closure)
}
return value
} else if (key.isIteratingOverArray()) {
traverseRecursively(Object, key.arrayField().contains(value), value, closure)
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(value)),
ContentUtils.returnParsedObject(value), closure)
}
try {
return runClosure(closure, key, value)
@@ -108,7 +116,7 @@ class JsonToJsonPathsConverter {
}
private static def runClosure(Closure closure, MethodBufferingJsonVerifiable key, def value) {
if (key.isAssertingAValueInArray()) {
if (key.isAssertingAValueInArray() && !(value instanceof List || value instanceof Map)) {
return closure(valueToAsserter(key, value), value)
}
return closure(key, value)
@@ -172,19 +180,20 @@ class JsonToJsonPathsConverter {
}
protected static MethodBufferingJsonVerifiable valueToAsserter(MethodBufferingJsonVerifiable key, Object value) {
def convertedValue = ContentUtils.returnParsedObject(value)
if (key instanceof FinishedDelegatingJsonVerifiable) {
return key
}
if (value instanceof Pattern) {
return key.matches((value as Pattern).pattern())
} else if (value instanceof OptionalProperty) {
return key.matches((value as OptionalProperty).optionalPattern())
} else if (value instanceof GString) {
return key.matches(RegexpBuilders.buildGStringRegexpForTestSide(value))
} else if (ContentUtils.returnParsedObject(value) instanceof ExecutionProperty) {
if (convertedValue instanceof Pattern) {
return key.matches((convertedValue as Pattern).pattern())
} else if (convertedValue instanceof OptionalProperty) {
return key.matches((convertedValue as OptionalProperty).optionalPattern())
} else if (convertedValue instanceof GString) {
return key.matches(RegexpBuilders.buildGStringRegexpForTestSide(convertedValue))
} else if (convertedValue instanceof ExecutionProperty) {
return key
}
return key.isEqualTo(value)
return key.isEqualTo(convertedValue)
}
}

View File

@@ -1131,7 +1131,7 @@ World.'''"""
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
test.contains('''assertThatJson(parsedJson).array("authorities").matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''')
test.contains('''assertThatJson(parsedJson).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
@@ -1232,6 +1232,39 @@ World.'''"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
def "should generate proper test code with array of primitives using #methodBuilderName"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'GET'
urlPath '/api/tags'
}
response {
status 200
body('''{
"partners":[
{
"payment_methods":[ "BANK", "CASH" ]
}
]
}
''')
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.then(blockBuilder)
def test = blockBuilder.toString()
then:
test.contains('assertThatJson(parsedJson).array("partners").array("payment_methods").arrayField().isEqualTo("BANK").value()')
test.contains('assertThatJson(parsedJson).array("partners").array("payment_methods").arrayField().isEqualTo("CASH").value()')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
GroovyDsl dslForDocs =
// tag::dsl_example[]
@@ -1278,4 +1311,4 @@ World.'''"""
}
}
// end::dsl_example[]
}
}

View File

@@ -1015,19 +1015,15 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie
"matchesJsonPath" : "$.errors[*][?(@.propertyName =~ /[0-9]{2}/)]"
}, {
"matchesJsonPath" : "$.errors[*][?(@.providerValue == 'Test')]"
}, {
"matchesJsonPath" : "$.errors[*][?(@.providerValue == 'Test')]"
}, {
"matchesJsonPath" : "$[?(@.lastName =~ /.*/)]"
}, {
"matchesJsonPath" : "$.errors[*][?(@.propertyName =~ /[0-9]{2}/)]"
"matchesJsonPath" : "$[?(@.firstName =~ /.*/)]"
}, {
"matchesJsonPath" : "$[?(@.birthDate =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/)]"
}, {
"matchesJsonPath" : "$[?(@.personalId =~ /[0-9]{11}/)]"
}, {
"matchesJsonPath" : "$[?(@.firstName =~ /.*/)]"
} ]
}]
},
"response" : {
"status" : 200,

View File

@@ -142,7 +142,7 @@ class JsonToJsonPathsConverterSpec extends Specification {
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method() == """.array("items").contains("HOP").value()""" &&
it.method() == """.array("items").arrayField().isEqualTo("HOP").value()""" &&
it.jsonPath() == '''$.items[?(@ == 'HOP')]'''
}
and:
@@ -534,19 +534,19 @@ class JsonToJsonPathsConverterSpec extends Specification {
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues.find {
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(38.995548).value()""" &&
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.995548)""" &&
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]"""
}
pathAndValues.find {
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(-77.119759).value()""" &&
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-77.119759)""" &&
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]"""
}
pathAndValues.find {
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(-76.909393).value()""" &&
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-76.909393)""" &&
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]"""
}
pathAndValues.find {
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(38.791645).value()""" &&
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.791645)""" &&
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]"""
}
and:

View File

@@ -2,7 +2,7 @@ nexusUsername =
nexusPassword =
wiremockVersion = 2.0.10-beta
jsonassertVersion = 0.4.2
jsonassertVersion = 0.4.3
BOM_VERSION=Brixton-1.0.0.RC1
springBootVersion=1.3.3.RELEASE