@@ -21,8 +21,9 @@ import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Headers
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters
|
||||
import org.springframework.cloud.contract.verifier.util.JsonPaths
|
||||
import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* Converter of JSON PACT file
|
||||
*
|
||||
@@ -36,6 +37,7 @@ class PactContractConverter implements ContractConverter<Pact> {
|
||||
private static final String REGEX_KEY = "regex"
|
||||
private static final String MAX_KEY = "max"
|
||||
private static final String MIN_KEY = "min"
|
||||
private static final String FULL_BODY = '$.body'
|
||||
|
||||
@Override
|
||||
boolean isAccepted(File file) {
|
||||
@@ -90,7 +92,8 @@ class PactContractConverter implements ContractConverter<Pact> {
|
||||
}
|
||||
if (requestResponseInteraction.request?.matchingRules) {
|
||||
stubMatchers {
|
||||
requestResponseInteraction.request.matchingRules.each { String key, Map<String, Object> value ->
|
||||
Map<String, Map<String, Object>> rules = requestResponseInteraction.request.matchingRules
|
||||
rules.each { String key, Map<String, Object> value ->
|
||||
String keyFromBody = toKeyStartingFromBody(key)
|
||||
if (value.containsKey(MATCH_KEY)) {
|
||||
MatchingType matchingType = MatchingType.valueOf((value.get(MATCH_KEY) as String).toUpperCase())
|
||||
@@ -132,8 +135,19 @@ class PactContractConverter implements ContractConverter<Pact> {
|
||||
}
|
||||
if (requestResponseInteraction.response?.matchingRules) {
|
||||
testMatchers {
|
||||
requestResponseInteraction.response.matchingRules.each { String key, Map<String, Object> value ->
|
||||
Map<String, Map<String, Object>> rules = requestResponseInteraction.response.matchingRules
|
||||
Map<String, Object> fullBodyCheck = rules.get(FULL_BODY)
|
||||
if (fullBodyCheck != null) {
|
||||
JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(requestResponseInteraction.request?.body?.value)
|
||||
jsonPaths.each {
|
||||
jsonPath(it.keyBeforeChecking(), byType())
|
||||
}
|
||||
}
|
||||
rules.each { String key, Map<String, Object> value ->
|
||||
String keyFromBody = toKeyStartingFromBody(key)
|
||||
if (!keyFromBody) {
|
||||
return
|
||||
}
|
||||
if (value.containsKey(MATCH_KEY)) {
|
||||
MatchingType matchingType = MatchingType.valueOf((value.get(MATCH_KEY) as String).toUpperCase())
|
||||
switch (matchingType) {
|
||||
@@ -185,7 +199,10 @@ class PactContractConverter implements ContractConverter<Pact> {
|
||||
}
|
||||
|
||||
protected String toKeyStartingFromBody(String key) {
|
||||
return key.replace('$.body', '$')
|
||||
if (key == FULL_BODY) {
|
||||
return ""
|
||||
}
|
||||
return key.replace(FULL_BODY, '$')
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
|
||||
import org.springframework.core.io.Resource
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
|
||||
import spock.lang.Issue
|
||||
import spock.lang.Specification
|
||||
import spock.lang.Subject
|
||||
/**
|
||||
@@ -16,6 +17,7 @@ import spock.lang.Subject
|
||||
class PactContractConverterSpec extends Specification {
|
||||
|
||||
File pactJson = new File(PactContractConverterSpec.getResource("/pact/pact.json").toURI())
|
||||
File pact509Json = new File(PactContractConverterSpec.getResource("/pact/pact_509.json").toURI())
|
||||
@Subject PactContractConverter converter = new PactContractConverter()
|
||||
|
||||
def "should accept json files that are pact files"() {
|
||||
@@ -76,6 +78,37 @@ class PactContractConverterSpec extends Specification {
|
||||
contracts == [expectedContract]
|
||||
}
|
||||
|
||||
@Issue("#509")
|
||||
def "should convert from pact with matching rules to whole body to contract"() {
|
||||
given:
|
||||
Contract expectedContract = Contract.make {
|
||||
description("a request to POST a person provider accepts a new person")
|
||||
request {
|
||||
method(POST())
|
||||
url("/user-service/users")
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
body(firstName: "Arthur", lastName: "Dent")
|
||||
}
|
||||
response {
|
||||
status(201)
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
body(id: 42)
|
||||
testMatchers {
|
||||
jsonPath('''$.['lastName']''', byType())
|
||||
jsonPath('''$.['firstName']''', byType())
|
||||
}
|
||||
}
|
||||
}
|
||||
when:
|
||||
Collection<Contract> contracts = converter.convertFrom(pact509Json)
|
||||
then:
|
||||
contracts == [expectedContract]
|
||||
}
|
||||
|
||||
def "should convert from contract to pact"() {
|
||||
given:
|
||||
Collection<Contract> inputContracts = [
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"consumer": {
|
||||
"name": "ui"
|
||||
},
|
||||
"provider": {
|
||||
"name": "userservice"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request to POST a person",
|
||||
"providerState": "provider accepts a new person",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"path": "/user-service/users",
|
||||
"headers": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"body": {
|
||||
"firstName": "Arthur",
|
||||
"lastName": "Dent"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 201,
|
||||
"headers": {
|
||||
"Content-Type": "application/json;charset=UTF-8"
|
||||
},
|
||||
"body": {
|
||||
"id": 42
|
||||
},
|
||||
"matchingRules": {
|
||||
"$.body": {
|
||||
"match": "type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable contains(Object value) {
|
||||
DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.contains(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.contains(value), this.methodsBuffer);
|
||||
verifiable.appendMethodWithQuotedValue("contains", value);
|
||||
if (isAssertingAValueInArray()) {
|
||||
verifiable.methodsBuffer.offer(".value()");
|
||||
@@ -145,7 +146,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(String value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
if (this.delegate.isAssertingAValueInArray() && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) {
|
||||
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
@@ -167,7 +169,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(Number value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.jsonPath(),
|
||||
this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
// related to #271 - the problem is with asserting arrays of maps vs arrays of primitives
|
||||
String last = readyToCheck.methodsBuffer.peekLast();
|
||||
boolean containsAMatcher = containsAnyMatcher(last);
|
||||
@@ -185,20 +188,23 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isNull() {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isNull(), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isNull(), this.methodsBuffer);
|
||||
readyToCheck.methodsBuffer.offer(".isNull()");
|
||||
return readyToCheck;
|
||||
}
|
||||
|
||||
@Override public MethodBufferingJsonVerifiable isEmpty() {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEmpty(), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEmpty(), this.methodsBuffer);
|
||||
readyToCheck.methodsBuffer.offer(".isEmpty()");
|
||||
return readyToCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable matches(String value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.matches(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.matches(value), this.methodsBuffer);
|
||||
if (this.delegate.isAssertingAValueInArray()) {
|
||||
readyToCheck.appendMethodWithQuotedValue("matches", escapedHackedJavaText(value));
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
@@ -221,7 +227,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable isEqualTo(Boolean value) {
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.isEqualTo(value), this.methodsBuffer);
|
||||
if (this.delegate.isAssertingAValueInArray()) {
|
||||
readyToCheck.methodsBuffer.offer(".value()");
|
||||
} else {
|
||||
@@ -235,6 +242,10 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
return new FinishedDelegatingJsonVerifiable(this.delegate, this.methodsBuffer);
|
||||
}
|
||||
|
||||
@Override public String keyBeforeChecking() {
|
||||
return this.delegate.jsonPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertsSize() {
|
||||
for (String s : this.methodsBuffer) {
|
||||
@@ -272,7 +283,8 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
@Override
|
||||
public JsonVerifiable hasSize(int size) {
|
||||
FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.hasSize(size), this.methodsBuffer);
|
||||
FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(
|
||||
this.delegate.jsonPath(), this.delegate.hasSize(size), this.methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".hasSize(" + size + ")");
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,21 @@ import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
*/
|
||||
class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
|
||||
|
||||
final String keyBeforeChecking;
|
||||
|
||||
FinishedDelegatingJsonVerifiable(String keyBeforeChecking, JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer) {
|
||||
super(delegate, methodsBuffer);
|
||||
this.keyBeforeChecking = keyBeforeChecking;
|
||||
}
|
||||
|
||||
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer) {
|
||||
super(delegate, methodsBuffer);
|
||||
this.keyBeforeChecking = delegate.jsonPath();
|
||||
}
|
||||
|
||||
@Override public String keyBeforeChecking() {
|
||||
return this.keyBeforeChecking;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ public interface MethodBufferingJsonVerifiable
|
||||
@Override
|
||||
MethodBufferingJsonVerifiable value();
|
||||
|
||||
String keyBeforeChecking();
|
||||
|
||||
boolean assertsSize();
|
||||
|
||||
boolean assertsConcreteValue();
|
||||
|
||||
Reference in New Issue
Block a user