From 40bce485df1e9608fc6d98343cf222e101ab3b85 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 12 May 2015 11:15:06 +0200 Subject: [PATCH 1/3] [#49] Fixed two more issues with the conversion --- .../wiremock/WiremockToDslConverter.groovy | 39 +- .../WiremockToDslConverterSpec.groovy | 376 ++++++++++++------ build.gradle | 1 + 3 files changed, 279 insertions(+), 137 deletions(-) diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy index beb15bfd2b..76570ee2b2 100644 --- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy +++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy @@ -18,12 +18,12 @@ class WiremockToDslConverter { def response = wiremockStub.response def bodyPatterns = request.bodyPatterns return """\ - request { - ${request.method ? "method \"\"\"$request.method\"\"\"" : ""} - ${request.url ? "url \"\"\"$request.url\"\"\"" : ""} - ${request.urlPattern ? "url \$(client(regex('${escapeJava(request.urlPattern)}')), server(''))" : ""} - ${request.urlPath ? "url \"\"\"$request.urlPath\"\"\"" : ""} - ${ + request { + ${request.method ? "method \"\"\"$request.method\"\"\"" : ""} + ${request.url ? "url \"\"\"$request.url\"\"\"" : ""} + ${request.urlPattern ? "url \$(client(regex('${escapeJava(request.urlPattern)}')), server(''))" : ""} + ${request.urlPath ? "url \"\"\"$request.urlPath\"\"\"" : ""} + ${ request.headers ? """headers { ${ request.headers.collect { @@ -36,20 +36,21 @@ class WiremockToDslConverter { } """ : "" } - ${bodyPatterns?.equalTo ? "body('''${bodyPatterns.equalTo}''')" : '' } - ${bodyPatterns?.matches ? "body \$(client(regex('${escapeJava(bodyPatterns.matches)}')), server(''))" : ""} - } - response { - ${response.status ? "status $response.status" : ""} - ${response.body ? "body( ${buildBody(response.body)})" : ""} - ${ + ${bodyPatterns?.equalTo?.every { it } ? "body('''${bodyPatterns.equalTo[0]}''')" : ''} + ${bodyPatterns?.equalToJson?.every { it } ? "body('''${bodyPatterns.equalToJson[0]}''')" : ''} + ${bodyPatterns?.matches?.every { it } ? "body \$(client(regex('${escapeJava(bodyPatterns.matches[0])}')), server(''))" : ""} + } + response { + ${response.status ? "status $response.status" : ""} + ${response.body ? "body( ${buildBody(response.body)})" : ""} + ${ response.headers ? """headers { - ${response.headers.collect { "header('$it.key': '${it.value}')\n" }.join('')} - } - """ : "" + ${response.headers.collect { "header('$it.key': '${it.value}')\n" }.join('')} + } + """ : "" } - } - """ + } + """ } private String buildHeader(String method, Object value) { @@ -158,7 +159,7 @@ class WiremockToDslConverter { static String wrapWithFactoryMethod(String dslFromWiremockStub) { return """\ ${GroovyDsl.name}.make { - $dslFromWiremockStub + $dslFromWiremockStub } """ } diff --git a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy index a88c05681e..98d74e6ca2 100755 --- a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy +++ b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy @@ -1,5 +1,6 @@ package io.codearte.accurest.wiremock +import com.github.tomakehurst.wiremock.stubbing.StubMapping import io.codearte.accurest.dsl.GroovyDsl import spock.lang.Specification @@ -9,27 +10,29 @@ class WiremockToDslConverterSpec extends Specification { given: String wiremockStub = '''\ { - "request": { - "method": "GET", - "url": "/path", - "headers" : { - "Accept": { - "matches": "text/.*" - }, - "X-Custom-Header": { - "contains": "2134" - } - } - }, - "response": { - "status": 200, - "body": "{ \\"id\\": { \\"value\\": \\"132\\" }, \\"surname\\": \\"Kowalsky\\", \\"name\\": \\"Jan\\", \\"created\\": \\"2014-02-02 12:23:43\\" }", - "headers": { - "Content-Type": "text/plain", - } - } + "request": { + "method": "GET", + "url": "/path", + "headers" : { + "Accept": { + "matches": "text/.*" + }, + "X-Custom-Header": { + "contains": "2134" + } + } + }, + "response": { + "status": 200, + "body": "{ \\"id\\": { \\"value\\": \\"132\\" }, \\"surname\\": \\"Kowalsky\\", \\"name\\": \\"Jan\\", \\"created\\": \\"2014-02-02 12:23:43\\" }", + "headers": { + "Content-Type": "text/plain" + } + } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -66,8 +69,8 @@ class WiremockToDslConverterSpec extends Specification { then: new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") == expectedGroovyDsl + $groovyDsl + }""") == expectedGroovyDsl } @@ -75,24 +78,26 @@ class WiremockToDslConverterSpec extends Specification { given: String wiremockStub = '''\ { - "request": { - "method": "DELETE", - "urlPattern": "/credit-card-verification-data/[0-9]+", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.mymoid-adapter.v2+json; charset=UTF-8" - } - } - }, - "response": { - "status": 200, - "body": "{\\"status\\": \\"OK\\"}", - "headers": { - "Content-Type": "application/json" - } - } + "request": { + "method": "DELETE", + "urlPattern": "/credit-card-verification-data/[0-9]+", + "headers": { + "Content-Type": { + "equalTo": "application/vnd.mymoid-adapter.v2+json; charset=UTF-8" + } + } + }, + "response": { + "status": 200, + "body": "{\\"status\\": \\"OK\\"}", + "headers": { + "Content-Type": "application/json" + } + } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -105,7 +110,7 @@ class WiremockToDslConverterSpec extends Specification { response { status 200 body("""{ - "status": "OK" + "status": "OK" }""") headers { header 'Content-Type': 'application/json' @@ -118,8 +123,8 @@ class WiremockToDslConverterSpec extends Specification { then: new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") == expectedGroovyDsl + $groovyDsl + }""") == expectedGroovyDsl } def 'should convert Wiremock stub with response body containing integer'() { @@ -127,23 +132,25 @@ class WiremockToDslConverterSpec extends Specification { String wiremockStub = '''\ { "request": { - "method": "POST", - "url": "/charge/count", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.creditcard-reporter.v1+json" - } - } + "method": "POST", + "url": "/charge/count", + "headers": { + "Content-Type": { + "equalTo": "application/vnd.creditcard-reporter.v1+json" + } + } }, "response": { - "status": 200, - "body": 200, - "headers": { - "Content-Type": "application/json" - } + "status": 200, + "body": 200, + "headers": { + "Content-Type": "application/json" + } } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -167,8 +174,8 @@ class WiremockToDslConverterSpec extends Specification { then: new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") == expectedGroovyDsl + $groovyDsl + }""") == expectedGroovyDsl } def 'should convert Wiremock stub with response body as a list'() { @@ -176,23 +183,25 @@ class WiremockToDslConverterSpec extends Specification { String wiremockStub = '''\ { "request": { - "method": "POST", - "url": "/charge/count", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.creditcard-reporter.v1+json" - } - } + "method": "POST", + "url": "/charge/count", + "headers": { + "Content-Type": { + "equalTo": "application/vnd.creditcard-reporter.v1+json" + } + } }, "response": { - "status": 200, - "body": "[ {\\"a\\":1, \\"c\\":\\"3\\"}, \\"b\\", \\"a\\" ]", - "headers": { - "Content-Type": "application/json" - } + "status": 200, + "body": "[ {\\"a\\":1, \\"c\\":\\"3\\"}, \\"b\\", \\"a\\" ]", + "headers": { + "Content-Type": "application/json" + } } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -219,8 +228,8 @@ class WiremockToDslConverterSpec extends Specification { then: new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") == expectedGroovyDsl + $groovyDsl + }""") == expectedGroovyDsl } @@ -229,20 +238,22 @@ class WiremockToDslConverterSpec extends Specification { String wiremockStub = '''\ { "request": { - "method": "POST", - "url": "/charge/search?pageNumber=0&size=2147483647", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.creditcard-reporter.v1+json" - } - } + "method": "POST", + "url": "/charge/search?pageNumber=0&size=2147483647", + "headers": { + "Content-Type": { + "equalTo": "application/vnd.creditcard-reporter.v1+json" + } + } }, "response": { - "status": 200, - "body":"[{\\"amount\\":1.01,\\"name\\":\\"Name\\",\\"info\\":{\\"title\\":\\"title1\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null},{\\"amount\\":2.01,\\"name\\":\\"Name2\\",\\"info\\":{\\"title\\":\\"title2\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null}]" - } + "status": 200, + "body":"[{\\"amount\\":1.01,\\"name\\":\\"Name\\",\\"info\\":{\\"title\\":\\"title1\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null},{\\"amount\\":2.01,\\"name\\":\\"Name2\\",\\"info\\":{\\"title\\":\\"title2\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null}]" + } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -255,26 +266,26 @@ class WiremockToDslConverterSpec extends Specification { response { status 200 body("""[ - { - "amount": 1.01, - "name": "Name", - "info": { - "title": "title1", - "payload": null - }, - "booleanvalue": true, - "user": null - }, - { - "amount": 2.01, - "name": "Name2", - "info": { - "title": "title2", - "payload": null - }, - "booleanvalue": true, - "user": null - } + { + "amount": 1.01, + "name": "Name", + "info": { + "title": "title1", + "payload": null + }, + "booleanvalue": true, + "user": null + }, + { + "amount": 2.01, + "name": "Name2", + "info": { + "title": "title2", + "payload": null + }, + "booleanvalue": true, + "user": null + } ]""") } } @@ -283,8 +294,8 @@ class WiremockToDslConverterSpec extends Specification { then: new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") == expectedGroovyDsl + $groovyDsl + }""") == expectedGroovyDsl } def 'should convert Wiremock stub with request body checking equality to Json'() { @@ -292,17 +303,19 @@ class WiremockToDslConverterSpec extends Specification { String wiremockStub = '''\ { "request": { - "method": "POST", - "url": "/test", - "bodyPatterns": { - "equalTo": "{\\"property1\\":\\"abc\\",\\"property2\\":\\"2017-01\\",\\"property3\\":\\"666\\",\\"property4\\":1428566412}" - } + "method": "POST", + "url": "/test", + "bodyPatterns": [{ + "equalTo": "{\\"property1\\":\\"abc\\",\\"property2\\":\\"2017-01\\",\\"property3\\":\\"666\\",\\"property4\\":1428566412}" + }] }, "response": { - "status": 200 - } + "status": 200 + } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -319,8 +332,8 @@ class WiremockToDslConverterSpec extends Specification { then: GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") + $groovyDsl + }""") and: evaluatedGroovyDsl == expectedGroovyDsl } @@ -330,17 +343,19 @@ class WiremockToDslConverterSpec extends Specification { String wiremockStub = '''\ { "request": { - "method": "POST", - "url": "/test", - "bodyPatterns": { - "matches": "[0-9]{5}" - } + "method": "POST", + "url": "/test", + "bodyPatterns": [{ + "matches": "[0-9]{5}" + }] }, "response": { - "status": 200 - } + "status": 200 + } } ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) and: GroovyDsl expectedGroovyDsl = GroovyDsl.make { request { @@ -357,10 +372,135 @@ class WiremockToDslConverterSpec extends Specification { then: GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate( """ io.codearte.accurest.dsl.GroovyDsl.make { - $groovyDsl - }""") + $groovyDsl + }""") and: evaluatedGroovyDsl == expectedGroovyDsl } + def 'should convert Wiremock stub with request body with equalToJson'() { + given: + String wiremockStub = '''\ +{ + "request" : { + "url" : "/test", + "method" : "POST", + "bodyPatterns" : [ { + "equalToJson" : "{\\"pan\\":\\"4855141150107894\\",\\"expirationDate\\":\\"2017-01\\",\\"dcvx\\":\\"178\\"}", + "jsonCompareMode" : "LENIENT" + } ] + }, + "response" : { + "status" : 200 + } +} +''' + and: + stubMappingIsValidWiremockStub(wiremockStub) + and: + GroovyDsl expectedGroovyDsl = GroovyDsl.make { + request { + method 'POST' + url '/test' + body '''{"pan":"4855141150107894","expirationDate":"2017-01","dcvx":"178"}''' + } + response { + status 200 + } + } + when: + String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub) + then: + GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate( + """ io.codearte.accurest.dsl.GroovyDsl.make { + $groovyDsl + }""") + and: + evaluatedGroovyDsl == expectedGroovyDsl + } + + def 'should convert Wiremock stub with request body with equalTo'() { + given: + String wiremockStub = '''\ + { + "request" : { + "url" : "/test", + "method" : "POST", + "bodyPatterns" : [ { + "equalTo" : "{\\"pan\\":\\"4855141150107894\\",\\"expirationDate\\":\\"2017-01\\",\\"dcvx\\":\\"178\\"}" + } ] + }, + "response" : { + "status" : 200 + } + } + ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) + and: + GroovyDsl expectedGroovyDsl = GroovyDsl.make { + request { + method 'POST' + url '/test' + body '''{"pan":"4855141150107894","expirationDate":"2017-01","dcvx":"178"}''' + } + response { + status 200 + } + } + when: + String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub) + then: + GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate( + """ io.codearte.accurest.dsl.GroovyDsl.make { + $groovyDsl + }""") + and: + evaluatedGroovyDsl == expectedGroovyDsl + } + + def 'should convert Wiremock stub with request body with matches'() { + given: + String wiremockStub = '''\ + { + "request" : { + "url" : "/test", + "method" : "POST", + "bodyPatterns" : [ { + "matches" : "[0-9]{2}" + } ] + }, + "response" : { + "status" : 200 + } + } + ''' + and: + stubMappingIsValidWiremockStub(wiremockStub) + and: + GroovyDsl expectedGroovyDsl = GroovyDsl.make { + request { + method 'POST' + url '/test' + body $(client(~/[0-9]{2}/), server('')) + } + response { + status 200 + } + } + when: + String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub) + then: + GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate( + """ io.codearte.accurest.dsl.GroovyDsl.make { + $groovyDsl + }""") + and: + evaluatedGroovyDsl == expectedGroovyDsl + } + + void stubMappingIsValidWiremockStub(String mappingDefinition) { + StubMapping.buildFrom(mappingDefinition) + } + } diff --git a/build.gradle b/build.gradle index c2d42cfdf1..28d6b6d0a2 100644 --- a/build.gradle +++ b/build.gradle @@ -98,6 +98,7 @@ project(':accurest-converters') { compile project(':accurest-core') compile 'org.apache.commons:commons-lang3:3.3.2' compile 'commons-io:commons-io:[2.4,)' + testCompile 'com.github.tomakehurst:wiremock:1.53' } } From 7e7e3ff003c3da920ca24765f8d653cdbc0e91b7 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 12 May 2015 16:14:46 +0200 Subject: [PATCH 2/3] [#49] Fixed missing conversion of request body --- .../dsl/WiremockRequestStubStrategy.groovy | 8 ++- .../dsl/WiremockResponseStubStrategy.groovy | 12 ++-- .../accurest/dsl/internal/Body.groovy | 34 +++++++++-- .../accurest/util/JsonConverter.groovy | 38 ++++++++++++ .../accurest/util/StubMappingConverter.groovy | 53 ----------------- .../builder/SpockMethodBuilderSpec.groovy | 59 +++++++++++++++++++ 6 files changed, 139 insertions(+), 65 deletions(-) create mode 100644 accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy delete mode 100644 accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy 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 36f7ec1ab5..97a7e942ba 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 @@ -3,6 +3,7 @@ import groovy.transform.PackageScope import groovy.transform.TypeChecked import io.codearte.accurest.dsl.internal.ClientRequest import io.codearte.accurest.dsl.internal.Request +import io.codearte.accurest.util.JsonConverter import java.util.regex.Pattern @@ -38,9 +39,8 @@ class WiremockRequestStubStrategy extends BaseWiremockStubStrategy { return [:] } if (containsRegex(body)) { - return [bodyPatterns: [[matches: parseBody(body)]]] + return [bodyPatterns: [[matches: parseBody(JsonConverter.transformValues(body, { it.toString() }))]]] } - return [bodyPatterns: [[equalTo: parseBody(body)]]] } @@ -49,4 +49,8 @@ class WiremockRequestStubStrategy extends BaseWiremockStubStrategy { return (bodyString =~ /\^.*\$/).find() } + boolean containsRegex(Map map) { + return map.values().any { it instanceof Pattern } + } + } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockResponseStubStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockResponseStubStrategy.groovy index e0b7556547..b517150236 100755 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockResponseStubStrategy.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockResponseStubStrategy.groovy @@ -21,12 +21,12 @@ class WiremockResponseStubStrategy extends BaseWiremockStubStrategy { private Map buildResponseContent(ClientResponse response) { return ([status : response?.status?.clientValue, - headers: buildClientResponseHeadersSection(response.headers) - ] << appendBody(response)).findAll { it.value } + headers: buildClientResponseHeadersSection(response.headers) + ] << appendBody(response)).findAll { it.value } } - private Map appendBody(ClientResponse response) { - Object body = response?.body?.clientValue - return body != null ? [body: parseBody(body)] : [:] - } + private Map appendBody(ClientResponse response) { + Object body = response?.body?.clientValue + return body != null ? [body: parseBody(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 5e8d46ed98..da602b5ebc 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 @@ -3,12 +3,19 @@ package io.codearte.accurest.dsl.internal import groovy.json.JsonSlurper import groovy.transform.EqualsAndHashCode import groovy.transform.ToString +import io.codearte.accurest.util.JsonConverter import org.codehaus.groovy.runtime.GStringImpl +import java.util.regex.Matcher +import java.util.regex.Pattern + @ToString(includePackage = false, includeFields = true, includeNames = true) @EqualsAndHashCode(includeFields = true) class Body extends DslProperty { + private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile('REGEXP>>(.*)<<') + private static final String JSON_VALUE_PATTERN_FOR_REGEX = 'REGEXP>>%s<<' + Body(Map body) { super(extractValue(body, {it.clientValue}), extractValue(body, {it.serverValue})) } @@ -36,9 +43,28 @@ class Body extends DslProperty { } private static Object extractValue(GString bodyAsValue, Closure valueProvider) { - GString clientGString = new GStringImpl(bodyAsValue.values.clone(), bodyAsValue.strings.clone()) - Object[] clientValues = bodyAsValue.values.collect { it instanceof DslProperty ? valueProvider(it) : it } as Object[] - return new JsonSlurper().parseText(new GStringImpl(clientValues, clientGString.strings).toString()) + 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)) + return convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson) } - + + private static Object convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson) { + JsonConverter.transformValues(parsedJson, { Object value -> + if (value instanceof String) { + String string = (String) value + Matcher matcher = TEMPORARY_PATTERN_HOLDER.matcher(string) + if (matcher.matches()) { + String pattern = matcher[0][1] + return Pattern.compile(pattern) + } + return value + } + return value + }) + } + } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy new file mode 100644 index 0000000000..208a3aefa3 --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy @@ -0,0 +1,38 @@ +package io.codearte.accurest.util + +import groovy.json.JsonSlurper +/** + * @author Marcin Grzejszczak + */ +class JsonConverter { + + private static Map convert(Map map, Closure closure) { + return map.collectEntries { + key, value -> + [key, transformValues(value, closure)] + } + } + + static def transformValues(def value, Closure closure) { + if (value instanceof String && value) { + try { + def json = new JsonSlurper().parseText(value) + if (json instanceof Map) { + return convert(json, closure) + } + } catch (Exception ignore) { + return closure(value) + } + } else if (value instanceof Map) { + return convert(value as Map, closure) + } else if (value instanceof List) { + return value.collect({ transformValues(it, closure) }) + } + try { + return closure(value) + } catch (Exception ignore) { + return value + } + } + +} diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy deleted file mode 100644 index f1ce59959f..0000000000 --- a/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package io.codearte.accurest.util - -import groovy.json.JsonException -import groovy.json.JsonSlurper - -import java.util.regex.Pattern - -/** - * @author Marcin Grzejszczak - */ -class StubMappingConverter { - - private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile(/^\$\{(.*):(.*)\}$/) - public static final int SERVER_SIDE_GROUP = 2 - - static Map toStubMappingOnServerSide(File stubMapping) { - def json = new JsonSlurper().parse(stubMapping) - return convertPlaceholders(json as Map, { String value -> - getGroupFromMatchingPattern(value) - }) - } - - private static Map convertPlaceholders(Map map, Closure closure) { - return map.collectEntries { - key, value -> - [key, transformValue(value, closure)] - } - } - - static def transformValue(def value, Closure closure) { - if (value instanceof String && value) { - try { - def json = new JsonSlurper().parseText(value) - if (json instanceof Map) { - return convertPlaceholders(json, closure) - } - } catch (JsonException ignore) { - return closure(value) - } - } else if (value instanceof Map) { - return convertPlaceholders(value as Map, closure) - } else if (value instanceof List) { - return value.collect({ transformValue(it, closure) }) - } - - return value - } - - private static Object getGroupFromMatchingPattern(String value) { - return value.matches(PLACEHOLDER_PATTERN) ? PLACEHOLDER_PATTERN.matcher(value)[0][SERVER_SIDE_GROUP] : value - } - -} diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy index c68a96a1e6..39f2b4762f 100644 --- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy @@ -110,4 +110,63 @@ class SpockMethodBuilderSpec extends Specification { blockBuilder.toString().contains("responseBody.property1 == \"a\"") blockBuilder.toString().contains("responseBody.property2.property3 == \"b\"") } + + def "should generate regex assertions for map objects in response body"() { + given: + GroovyDsl contractDsl = GroovyDsl.make { + request { + method "GET" + url "test" + } + response { + status 200 + body( + property1: "a", + property2: value( + client(''), + server(regex('\\\\d{3}')) + ) + ) + headers { + header('Content-Type': 'application/json') + + } + + } + } + SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + then: + blockBuilder.toString().contains("responseBody.property1 == \"a\"") + blockBuilder.toString().contains("responseBody.property2 ==~ java.util.regex.Pattern.compile('\\\\d{3}')") + } + + def "should generate regex assertions for string objects in response body"() { + given: + GroovyDsl contractDsl = GroovyDsl.make { + request { + method "GET" + url "test" + } + response { + status 200 + body( """{"property1":"a","property2":"${value(client('123'), server(regex('[0-9]{3}')))}"}""") + headers { + header('Content-Type': 'application/json') + + } + + } + } + SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + then: + blockBuilder.toString().contains("responseBody.property1 == \"a\"") + blockBuilder.toString().contains("responseBody.property2 ==~ java.util.regex.Pattern.compile('[0-9]{3}')") + } + } From f84f11611b88c23f087b8fce1e7ad18adca0cae9 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 12 May 2015 16:20:42 +0200 Subject: [PATCH 3/3] [#49] Surrounded with different quotes --- .../accurest/wiremock/WiremockToDslConverter.groovy | 4 ++-- .../io/codearte/accurest/dsl/internal/Body.groovy | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy index 76570ee2b2..00d4d3786e 100644 --- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy +++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy @@ -36,8 +36,8 @@ class WiremockToDslConverter { } """ : "" } - ${bodyPatterns?.equalTo?.every { it } ? "body('''${bodyPatterns.equalTo[0]}''')" : ''} - ${bodyPatterns?.equalToJson?.every { it } ? "body('''${bodyPatterns.equalToJson[0]}''')" : ''} + ${bodyPatterns?.equalTo?.every { it } ? "body(\"\"\"${bodyPatterns.equalTo[0]}\"\"\")" : ''} + ${bodyPatterns?.equalToJson?.every { it } ? "body(\"\"\"${bodyPatterns.equalToJson[0]}\"\"\")" : ''} ${bodyPatterns?.matches?.every { it } ? "body \$(client(regex('${escapeJava(bodyPatterns.matches[0])}')), server(''))" : ""} } response { 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 da602b5ebc..315135d939 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 @@ -42,6 +42,18 @@ class Body extends DslProperty { super(bodyAsValue.clientValue, bodyAsValue.serverValue) } + /** + * Due to the fact that we allow users to have a body with GString and different values inside + * we need to be prepared that they pass regexps around both on client and server side. + * + * In order to preserve the original JSON structure we need to convert the passed Regex patterns + * to a temporary string, then convert all to a legitimate JSON structure and then finally + * convert it back from string to a pattern. + * + * @param bodyAsValue - GString with passed values + * @param valueProvider - provider of values either for server or client side + * @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[]