diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy index 298cc1b2ec..3390b6456b 100755 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy @@ -2,6 +2,7 @@ package io.codearte.accurest.dsl import groovy.transform.PackageScope import groovy.transform.TypeChecked import io.codearte.accurest.dsl.internal.ClientRequest +import io.codearte.accurest.dsl.internal.Header import io.codearte.accurest.dsl.internal.MatchingStrategy import io.codearte.accurest.dsl.internal.QueryParameter import io.codearte.accurest.dsl.internal.QueryParameters @@ -95,7 +96,19 @@ class WiremockRequestStubStrategy extends BaseWiremockStubStrategy { } ))]]] } - return [bodyPatterns: [[equalTo: parseBody(body)]]] + + return [bodyPatterns: [[(getCompareType()): parseBody(body)]]] + } + + private String getCompareType() { + Header contentType = request.headers?.entries.find { it.name == "Content-Type" } + if (contentType && contentType.clientValue.toString().endsWith("json")) { + return "equalToJson" + } + if (contentType && contentType.clientValue.toString().endsWith("xml")) { + return "equalToXml" + } + return "equalTo" } protected String parseBody(Object body) { diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy index 315135d939..c68380f0f2 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy @@ -1,5 +1,6 @@ package io.codearte.accurest.dsl.internal +import groovy.json.JsonException import groovy.json.JsonSlurper import groovy.transform.EqualsAndHashCode import groovy.transform.ToString @@ -9,6 +10,8 @@ import org.codehaus.groovy.runtime.GStringImpl import java.util.regex.Matcher import java.util.regex.Pattern +import static org.apache.commons.lang3.StringEscapeUtils.escapeXml11 + @ToString(includePackage = false, includeFields = true, includeNames = true) @EqualsAndHashCode(includeFields = true) class Body extends DslProperty { @@ -55,15 +58,51 @@ class Body extends DslProperty { * @return JSON structure with replaced client / server side parts */ private static Object extractValue(GString bodyAsValue, Closure valueProvider) { - GString gString = new GStringImpl(bodyAsValue.values.clone(), bodyAsValue.strings.clone()) - Object[] values = bodyAsValue.values.collect { it instanceof DslProperty ? valueProvider(it) : it } as Object[] - Object[] valuesWithRegexpsAsTransformedStrings = values.collect { - it instanceof Pattern ? String.format(JSON_VALUE_PATTERN_FOR_REGEX, it.toString()) : it - } as Object[] - def parsedJson = new JsonSlurper().parseText(new GStringImpl(valuesWithRegexpsAsTransformedStrings, gString.strings)) + try { + return extractValueForJSON(bodyAsValue, valueProvider) + } catch(JsonException e) { + // Not a JSON format + return extractValueForXML(bodyAsValue, valueProvider) + } + return bodyAsValue + } + + private static Object extractValueForJSON(GString bodyAsValue, Closure valueProvider) { + GString transformedString = new GStringImpl( + bodyAsValue.values.collect { transformJSONStringValue(it, valueProvider) } as Object[], + bodyAsValue.strings.clone() + ) + def parsedJson = new JsonSlurper().parseText(transformedString) return convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson) } + private static GStringImpl extractValueForXML(GString bodyAsValue, Closure valueProvider) { + return new GStringImpl( + bodyAsValue.values.collect { transformXMLStringValue(it, valueProvider) } as Object[], + bodyAsValue.strings.clone() + ) + } + + private static String transformJSONStringValue(Object obj, Closure valueProvider) { + return obj.toString() + } + + private static String transformJSONStringValue(DslProperty dslProperty, Closure valueProvider) { + return transformJSONStringValue(valueProvider(dslProperty), valueProvider) + } + + private static String transformJSONStringValue(Pattern pattern, Closure valueProvider) { + return String.format(JSON_VALUE_PATTERN_FOR_REGEX, pattern.pattern()) + } + + private static String transformXMLStringValue(Object obj, Closure valueProvider) { + return escapeXml11(obj.toString()) + } + + private static String transformXMLStringValue(DslProperty dslProperty, Closure valueProvider) { + return transformXMLStringValue(valueProvider(dslProperty), valueProvider) + } + private static Object convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson) { JsonConverter.transformValues(parsedJson, { Object value -> if (value instanceof String) { diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockGroovyDslSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockGroovyDslSpec.groovy index 7d8e5f1d49..4674441a09 100755 --- a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockGroovyDslSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockGroovyDslSpec.groovy @@ -150,6 +150,96 @@ class WiremockGroovyDslSpec extends WiremockSpec { stubMappingIsValidWiremockStub(wiremockStub) } + def 'should use equalToJson when content type ends with json'() { + given: + GroovyDsl groovyDsl = GroovyDsl.make { + request { + method 'GET' + url "/users" + headers { + header "Content-Type", "customtype/json" + } + body """ + { + "name": "Jan" + } + """ + } + response { + status 200 + } + } + when: + String json = toWiremockClientJsonStub(groovyDsl) + then: + parseJson(json) == parseJson(''' + { + "request": { + "method": "GET", + "url": "/users", + "headers": { + "Content-Type": { + "equalTo": "customtype/json" + } + }, + "bodyPatterns": [ + { + "equalToJson":"{\\"name\\":\\"Jan\\"}" + } + ] + }, + "response": { + "status": 200 + } + } + ''') + and: + stubMappingIsValidWiremockStub(json) + } + + def 'should use equalToXml when content type ends with xml'() { + given: + GroovyDsl groovyDsl = GroovyDsl.make { + request { + method 'GET' + url "/users" + headers { + header "Content-Type", "customtype/xml" + } + body """${value(client('Jozo'), server('Denis'))}${value(client(""), server('1234567890'))}""" + } + response { + status 200 + } + } + when: + String json = toWiremockClientJsonStub(groovyDsl) + then: + parseJson(json) == parseJson(''' + { + "request": { + "method": "GET", + "url": "/users", + "headers": { + "Content-Type": { + "equalTo": "customtype/xml" + } + }, + "bodyPatterns": [ + { + "equalToXml":"Jozo<test>" + } + ] + }, + "response": { + "status": 200 + } + } + ''') + and: + stubMappingIsValidWiremockStub(json) + } + def 'should convert groovy dsl stub with regexp Body as String to wiremock stub for the client side'() { given: GroovyDsl groovyDsl = GroovyDsl.make {