@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user