diff --git a/.travis.yml b/.travis.yml index 7a0dff7140..074a9aabda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,15 @@ language: java +sudo: false jdk: - oraclejdk7 - openjdk7 - oraclejdk8 +cache: + directories: + - $HOME/.gradle + - $HOME/.m2 + install: ./gradlew assemble script: ./gradlew check --stacktrace --info --continue \ No newline at end of file diff --git a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverterSpec.groovy b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverterSpec.groovy index 0831dde57b..22fc850efe 100755 --- a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverterSpec.groovy +++ b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverterSpec.groovy @@ -1,6 +1,6 @@ package io.codearte.accurest.wiremock -import groovy.json.JsonSlurper +import org.skyscreamer.jsonassert.JSONAssert import spock.lang.Specification class DslToWireMockClientConverterSpec extends Specification { @@ -23,8 +23,9 @@ class DslToWireMockClientConverterSpec extends Specification { when: String json = converter.convertContent(dslBody) then: - new JsonSlurper().parseText(json) == new JsonSlurper().parseText(""" -{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}}""") + JSONAssert.assertEquals(''' +{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}} +''', json, false) } @@ -80,22 +81,62 @@ class DslToWireMockClientConverterSpec extends Specification { when: String json = converter.convertContent(dslBody) then: - new JsonSlurper().parseText(json) == new JsonSlurper().parseText("""{ - "request":{ - "method":"PUT", - "url":"/api/12", - "bodyPatterns": [ - { "equalToJson": "[{\\"created_at\\":\\"Sat Jul 26 09:38:57 +0000 2014\\",\\"id\\":492967299297845248,\\"id_str\\":\\"492967299297845248\\",\\"place\\":{\\"attributes\\":{},\\"bounding_box\\":{\\"coordinates\\":[[[-77.119759,38.791645],[-76.909393,38.791645],[-76.909393,38.995548],[-77.119759,38.995548]]],\\"type\\":\\"Polygon\\"},\\"country\\":\\"United States\\",\\"country_code\\":\\"US\\",\\"full_name\\":\\"Washington, DC\\",\\"id\\":\\"01fbe706f872cb32\\",\\"name\\":\\"Washington\\",\\"place_type\\":\\"city\\",\\"url\\":\\"http://api.twitter.com/1/geo/id/01fbe706f872cb32.json\\"},\\"text\\":\\"Gonna see you at Warsaw\\"}]" } - ], - "headers": { - "Content-Type": { - "equalTo": "application/vnd.com.ofg.twitter-places-analyzer.v1+json" - } - } - }, - "response":{ - "status":200} - } -""") + JSONAssert.assertEquals(''' +{ + "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)]" + } ], + "headers" : { + "Content-Type" : { + "equalTo" : "application/vnd.com.ofg.twitter-places-analyzer.v1+json" + } + } + }, + "response" : { + "status" : 200 + } +} +''', json, false) } } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy index 2765d7114b..fb2d135419 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy @@ -50,14 +50,23 @@ class SingleTestGenerator { } if (configProperties.ruleClassForTests) { + clazz.addImport('org.junit.Rule') - .addRule(configProperties.ruleClassForTests) + .addRule(configProperties.ruleClassForTests) } + addJsonPathRelatedImports(clazz) + listOfFiles.each { clazz.addMethod(createTestMethod(it, configProperties)) } return clazz.build() } + private ClassBuilder addJsonPathRelatedImports(ClassBuilder clazz) { + clazz.addImport(['com.jayway.jsonpath.DocumentContext', + 'com.jayway.jsonpath.JsonPath', + 'net.minidev.json.JSONArray']) + } + } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/ClassBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/ClassBuilder.groovy index 29f4fc2c14..3e3a8ce1c0 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/builder/ClassBuilder.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/ClassBuilder.groovy @@ -43,6 +43,11 @@ class ClassBuilder { return this } + ClassBuilder addImport(List importsToAdd) { + imports.addAll(importsToAdd) + return this + } + ClassBuilder addStaticImport(String importToAdd) { staticImports << importToAdd return this diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy index af8993e140..49df619015 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy @@ -3,21 +3,13 @@ import groovy.json.JsonOutput import groovy.transform.PackageScope import groovy.transform.TypeChecked import io.codearte.accurest.dsl.GroovyDsl -import io.codearte.accurest.dsl.internal.DslProperty -import io.codearte.accurest.dsl.internal.ExecutionProperty -import io.codearte.accurest.dsl.internal.MatchingStrategy -import io.codearte.accurest.dsl.internal.QueryParameter -import io.codearte.accurest.dsl.internal.Request -import io.codearte.accurest.dsl.internal.Response +import io.codearte.accurest.dsl.internal.* import io.codearte.accurest.util.ContentType -import io.codearte.accurest.util.JsonConverter - -import java.util.regex.Pattern - -import static io.codearte.accurest.util.ContentUtils.extractValue -import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromContent -import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHeader +import io.codearte.accurest.util.MapConverter +import io.codearte.accurest.util.JsonPathJsonConverter +import io.codearte.accurest.util.JsonPaths +import static io.codearte.accurest.util.ContentUtils.* /** * @author Jakub Kubrynski */ @@ -93,17 +85,34 @@ abstract class SpockMethodBodyBuilder { responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue }) } if (contentType == ContentType.JSON) { - bb.addLine("def responseBody = new JsonSlurper().parseText($responseAsString)") + appendJsonPath(bb, responseAsString) + JsonPaths jsonPaths = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(responseBody) + jsonPaths.each { + it.buildJsonPathComparison('parsedJson').each { + bb.addLine(it) + } + } processBodyElement(bb, "", responseBody) } else if (contentType == ContentType.XML) { bb.addLine("def responseBody = new XmlSlurper().parseText($responseAsString)") // TODO xml validation } else { bb.addLine("def responseBody = ($responseAsString)") - processBodyElement(bb, "", responseBody) + processText(bb, "", responseBody as String) } } + protected void processText(BlockBuilder blockBuilder, String property, String value) { + if (value.startsWith('$')) { + value = value.substring(1).replaceAll('\\$value', "responseBody$property") + blockBuilder.addLine(value) + } else { + blockBuilder.addLine("responseBody$property == \"${value}\"") + } + } + + protected String + protected String getBodyAsString() { Object bodyValue = extractServerValueFromBody(request.body.serverValue) return trimRepeatedQuotes(new JsonOutput().toJson(bodyValue)) @@ -117,7 +126,7 @@ abstract class SpockMethodBodyBuilder { if (bodyValue instanceof GString) { bodyValue = extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue }) } else { - bodyValue = JsonConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it }) + bodyValue = MapConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it }) } return bodyValue } @@ -147,28 +156,15 @@ abstract class SpockMethodBodyBuilder { } protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) { - blockBuilder.addLine("responseBody$property == ${value}") + } - protected void processBodyElement(BlockBuilder blockBuilder, String property, String value) { - if (value.startsWith('$')) { - value = value.substring(1).replaceAll('\\$value', "responseBody$property") - blockBuilder.addLine(value) - } else { - blockBuilder.addLine("responseBody$property == '''${value}'''") - } - } - - protected void processBodyElement(BlockBuilder blockBuilder, String property, Pattern pattern) { - blockBuilder.addLine("responseBody$property ==~ java.util.regex.Pattern.compile('${pattern.pattern()}')") - } - - protected void processBodyElement(BlockBuilder blockBuilder, String property, DslProperty dslProperty) { - processBodyElement(blockBuilder, property, dslProperty.serverValue) + protected void appendJsonPath(BlockBuilder blockBuilder, String json) { + blockBuilder.addLine("DocumentContext parsedJson = JsonPath.parse($json)") } protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("responseBody$property")}") + blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") } protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWireMockStubStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWireMockStubStrategy.groovy index 0afb66273b..c69e5539fa 100755 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWireMockStubStrategy.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWireMockStubStrategy.groovy @@ -10,7 +10,7 @@ import io.codearte.accurest.util.ContentType import java.util.regex.Pattern import static io.codearte.accurest.util.ContentUtils.extractValue -import static io.codearte.accurest.util.JsonConverter.transformValues +import static io.codearte.accurest.util.MapConverter.transformValues @TypeChecked abstract class BaseWireMockStubStrategy { 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 d540069484..923b614f7a 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 @@ -1,21 +1,21 @@ package io.codearte.accurest.dsl +import com.github.tomakehurst.wiremock.http.RequestMethod +import com.github.tomakehurst.wiremock.matching.RequestPattern +import com.github.tomakehurst.wiremock.matching.ValuePattern +import groovy.json.JsonOutput import groovy.transform.PackageScope import groovy.transform.TypeChecked -import io.codearte.accurest.dsl.internal.Body -import io.codearte.accurest.dsl.internal.ClientRequest -import io.codearte.accurest.dsl.internal.DslProperty -import io.codearte.accurest.dsl.internal.MatchingStrategy -import io.codearte.accurest.dsl.internal.QueryParameter -import io.codearte.accurest.dsl.internal.QueryParameters -import io.codearte.accurest.dsl.internal.Request +import groovy.transform.TypeCheckingMode +import io.codearte.accurest.dsl.internal.* import io.codearte.accurest.util.ContentType +import io.codearte.accurest.util.ContentUtils +import io.codearte.accurest.util.JsonPathJsonConverter +import io.codearte.accurest.util.JsonPaths +import io.codearte.accurest.util.MapConverter import java.util.regex.Pattern -import static io.codearte.accurest.util.ContentUtils.getEqualsTypeFromContentType -import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromContent -import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHeader -import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromMatchingStrategy +import static io.codearte.accurest.util.ContentUtils.* import static io.codearte.accurest.util.RegexpBuilders.buildGStringRegexpMatch import static io.codearte.accurest.util.RegexpBuilders.buildJSONRegexpMatch @@ -30,74 +30,144 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy { } @PackageScope - Map buildClientRequestContent() { - return buildRequestContent(new ClientRequest(request)) + RequestPattern buildClientRequestContent() { + RequestPattern requestPattern = new RequestPattern() + appendMethod(requestPattern) + appendHeaders(requestPattern) + appendUrl(requestPattern) + appendQueryParameters(requestPattern) + appendBody(requestPattern) + return requestPattern } - private Map buildRequestContent(ClientRequest request) { - return ([method : request?.method?.clientValue, - headers : buildClientRequestHeadersSection(request.headers) - ] << appendUrl(request) << appendQueryParameters(request) << appendBody(request)).findAll { it.value } + private void appendMethod(RequestPattern requestPattern) { + if(!request.method) { + return + } + requestPattern.setMethod(RequestMethod.fromString(request.method.clientValue?.toString())) } - private Map appendUrl(ClientRequest clientRequest) { - Object urlPath = clientRequest?.urlPath?.clientValue + private void appendBody(RequestPattern requestPattern) { + if (!request.body) { + return + } + ContentType contentType = tryToGetContentType() + if (contentType == ContentType.JSON) { + JsonPaths values = JsonPathJsonConverter.transformToJsonPathWithStubsSideValues(getMatchingStrategyFromBody(request.body)?.clientValue) + if (values.empty) { + requestPattern.bodyPatterns = [new ValuePattern(jsonCompareMode: org.skyscreamer.jsonassert.JSONCompareMode.LENIENT, + equalToJson: JsonOutput.toJson(getMatchingStrategy(request.body.clientValue).clientValue) ) ] + } else { + requestPattern.bodyPatterns = values.collect { new ValuePattern(matchesJsonPath: it.jsonPath) } ?: null + } + } else if (contentType == ContentType.XML) { + requestPattern.bodyPatterns = [new ValuePattern(equalToXml: getMatchingStrategy(request.body.clientValue).clientValue.toString())] + } else if (containsPattern(request?.body)) { + MatchingStrategy matchingStrategy = appendBodyRegexpMatchPattern(request.body) + requestPattern.bodyPatterns = [convertToValuePattern(matchingStrategy)] + } else { + requestPattern.bodyPatterns = [convertToValuePattern(getMatchingStrategy(request.body.clientValue))] + } + } + + private ContentType tryToGetContentType() { + ContentType contentType = recognizeContentTypeFromHeader(request.headers) + if (contentType == ContentType.UNKNOWN) { + if (!request.body.clientValue) { + return ContentType.UNKNOWN + } + return ContentUtils.getClientContentType(request.body.clientValue) + } + return contentType + } + + private void appendHeaders(RequestPattern requestPattern) { + if(!request.headers) { + return + } + request.headers.entries.each { + requestPattern.addHeader(it.name, convertToValuePattern(it.clientValue)) + } + } + + private void appendUrl(RequestPattern requestPattern) { + Object urlPath = request?.urlPath?.clientValue if (urlPath) { - return [urlPath: urlPath] + requestPattern.setUrlPath(urlPath.toString()) } - Object url = clientRequest?.url?.clientValue - return url instanceof Pattern ? [urlPattern: url.pattern()] : [url: url] - } - - private Map appendQueryParameters(ClientRequest clientRequest) { - QueryParameters queryParameters = clientRequest?.urlPath?.queryParameters ?: clientRequest?.url?.queryParameters - return queryParameters && !queryParameters.parameters.isEmpty() ? - [queryParameters: buildUrlPathQueryParameters(queryParameters)] : [:] - } - - private Map buildUrlPathQueryParameters(QueryParameters queryParameters) { - return queryParameters.parameters.collectEntries { QueryParameter param -> - parseQueryParameter(param.name, param.clientValue) + if(!request.url) { + return + } + Object url = request?.url?.clientValue + if(url instanceof Pattern) { + requestPattern.setUrlPattern(url.pattern()) + } else { + requestPattern.setUrl(url.toString()) } } - protected Map parseQueryParameter(String name, MatchingStrategy matchingStrategy) { - return buildQueryParameter(name, matchingStrategy.clientValue, matchingStrategy.type) + private void appendQueryParameters(RequestPattern requestPattern) { + QueryParameters queryParameters = request?.urlPath?.queryParameters ?: request?.url?.queryParameters + queryParameters?.parameters?.each { + requestPattern.addQueryParam(it.name, convertToValuePattern(it.clientValue)) + } } - protected Map parseQueryParameter(String name, Object value) { - return buildQueryParameter(name, value, MatchingStrategy.Type.EQUAL_TO) + @TypeChecked(TypeCheckingMode.SKIP) + private static ValuePattern convertToValuePattern(Object object) { + switch (object) { + case Pattern: + Pattern value = object as Pattern + return ValuePattern.matches(value.pattern()) + case MatchingStrategy: + MatchingStrategy value = object as MatchingStrategy + switch (value.type) { + case MatchingStrategy.Type.NOT_MATCHING: + return new ValuePattern(doesNotMatch: value.clientValue) + case MatchingStrategy.Type.ABSENT: + return ValuePattern.absent() + default: + return ValuePattern."${value.type.name}"(value.clientValue) + } + default: + return ValuePattern.equalTo(object.toString()) + } } - protected Map parseQueryParameter(String name, Pattern pattern) { - return buildQueryParameter(name, pattern.pattern(), MatchingStrategy.Type.MATCHING) + private MatchingStrategy getMatchingStrategyFromBody(Body body) { + if(!body) { + return null + } + return getMatchingStrategy(body.clientValue) } - private Map buildQueryParameter(String name, Pattern pattern, MatchingStrategy.Type type) { - return buildQueryParameter(name, pattern.pattern(), type) + private MatchingStrategy getMatchingStrategy(MatchingStrategy matchingStrategy) { + return getMatchingStrategyIncludingContentType(matchingStrategy) + } + private MatchingStrategy getMatchingStrategy(GString gString) { + if (!gString) { + return new MatchingStrategy("", MatchingStrategy.Type.EQUAL_TO) + } + def extractedValue = ContentUtils.extractValue(gString) { + it instanceof DslProperty ? it.clientValue : getStringFromGString(it) + } + def value = getStringFromGString(extractedValue) + return getMatchingStrategy(value) } - private Map buildQueryParameter(String name, Object value, MatchingStrategy.Type type) { - return [(name): [(type.name) : value]] + private def getStringFromGString(Object object) { + return object instanceof GString ? object.toString() : object } - private Map appendBody(ClientRequest clientRequest) { - return clientRequest.body? appendBody(clientRequest.body) : [:] + private MatchingStrategy getMatchingStrategy(Object bodyValue) { + return tryToFindMachingStrategy(bodyValue) } - private Map appendBody(Body body) { - return [bodyPatterns: (appendBodyPatterns(body.clientValue))] + private MatchingStrategy tryToFindMachingStrategy(Object bodyValue) { + return new MatchingStrategy(MapConverter.transformToClientValues(bodyValue), getEqualsTypeFromContentTypeHeader()) } - private List> appendBodyPatterns(MatchingStrategy matchingStrategy) { - return [appendBodyPattern(matchingStrategy)] - } - - private List> appendBodyPatterns(Object bodyValue) { - return appendBodyPatterns(new MatchingStrategy(bodyValue, getEqualsTypeFromContentTypeHeader())) - } - - private Map appendBodyPattern(MatchingStrategy matchingStrategy) { + private MatchingStrategy getMatchingStrategyIncludingContentType(MatchingStrategy matchingStrategy) { MatchingStrategy.Type type = matchingStrategy.type Object value = matchingStrategy.clientValue ContentType contentType = recognizeContentTypeFromMatchingStrategy(type) @@ -105,29 +175,22 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy { contentType = recognizeContentTypeFromContent(value) type = getEqualsTypeFromContentType(contentType) } - if (containsPattern(value)) { - return appendBodyRegexpMatchPattern(value, contentType) - } - return buildMatchPattern(new MatchingStrategy(parseBody(value, contentType), type)) + return new MatchingStrategy(parseBody(value, contentType), type) } - private Map appendBodyRegexpMatchPattern(Object value, ContentType contentType) { + private MatchingStrategy appendBodyRegexpMatchPattern(Object value, ContentType contentType) { switch (contentType) { case ContentType.JSON: - return buildMatchPattern(new MatchingStrategy(buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING)) + return new MatchingStrategy(buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING) case ContentType.UNKNOWN: - return buildMatchPattern(new MatchingStrategy(buildGStringRegexpMatch(value), MatchingStrategy.Type.MATCHING)) + return new MatchingStrategy(buildGStringRegexpMatch(value), MatchingStrategy.Type.MATCHING) case ContentType.XML: throw new IllegalStateException("XML pattern matching is not implemented yet") } } - private Map buildMatchPattern(MatchingStrategy matchingStrategy) { - Map result = [(matchingStrategy.type.name): matchingStrategy.clientValue.toString()] - if (matchingStrategy.type == MatchingStrategy.Type.EQUAL_TO_JSON && matchingStrategy.jsonCompareMode) { - return result << [jsonCompareMode : (matchingStrategy.jsonCompareMode.toString())] - } - return result + private MatchingStrategy appendBodyRegexpMatchPattern(Object value) { + return appendBodyRegexpMatchPattern(value, ContentType.UNKNOWN) } private boolean containsPattern(GString bodyAsValue) { 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 3cb9a58155..5af5898257 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 @@ -1,7 +1,9 @@ package io.codearte.accurest.dsl +import com.github.tomakehurst.wiremock.http.HttpHeader +import com.github.tomakehurst.wiremock.http.HttpHeaders +import com.github.tomakehurst.wiremock.http.ResponseDefinition import groovy.transform.PackageScope import groovy.transform.TypeChecked -import io.codearte.accurest.dsl.internal.ClientResponse import io.codearte.accurest.dsl.internal.Request import io.codearte.accurest.dsl.internal.Response import io.codearte.accurest.util.ContentType @@ -22,23 +24,31 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy { } @PackageScope - Map buildClientResponseContent() { - return buildResponseContent(new ClientResponse(response)) + ResponseDefinition buildClientResponseContent() { + ResponseDefinition responseDefinition = new ResponseDefinition() + responseDefinition.setStatus(response.status.clientValue as Integer) + appendHeaders(responseDefinition) + appendBody(responseDefinition) + return responseDefinition } - private Map buildResponseContent(ClientResponse response) { - return ([status : response?.status?.clientValue, - headers: buildClientResponseHeadersSection(response.headers) - ] << appendBody(response)).findAll { it.value } + private void appendHeaders(ResponseDefinition responseDefinition) { + if(!(response.headers)) { + return + } + responseDefinition.setHeaders(new HttpHeaders(response.headers.entries?.collect { new HttpHeader(it.name, it.clientValue.toString()) })) } - private Map appendBody(ClientResponse response) { - Object body = response?.body?.clientValue + private void appendBody(ResponseDefinition responseDefinition) { + if (!response.body) { + return + } + Object body = response.body.clientValue ContentType contentType = recognizeContentTypeFromHeader(response.headers) if (contentType == ContentType.UNKNOWN) { contentType = recognizeContentTypeFromContent(body) } - return body != null ? [body: parseBody(body, contentType)] : [:] + responseDefinition.setBody(parseBody(body, contentType)) } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockStubStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockStubStrategy.groovy index acff79a11a..337f7b8557 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockStubStrategy.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockStubStrategy.groovy @@ -1,6 +1,8 @@ package io.codearte.accurest.dsl -import groovy.json.JsonOutput +import com.github.tomakehurst.wiremock.http.ResponseDefinition +import com.github.tomakehurst.wiremock.matching.RequestPattern +import com.github.tomakehurst.wiremock.stubbing.StubMapping import groovy.transform.CompileDynamic import groovy.transform.CompileStatic @@ -19,11 +21,14 @@ class WireMockStubStrategy { @CompileDynamic String toWireMockClientStub() { - def wiremockStubDefinition = [request : wireMockRequestStubStrategy.buildClientRequestContent(), - response: wireMockResponseStubStrategy.buildClientResponseContent()] + StubMapping stubMapping = new StubMapping() + RequestPattern request = wireMockRequestStubStrategy.buildClientRequestContent() + ResponseDefinition response = wireMockResponseStubStrategy.buildClientResponseContent() if (priority) { - wiremockStubDefinition.priority = priority + stubMapping.priority = priority } - return JsonOutput.prettyPrint(JsonOutput.toJson(wiremockStubDefinition)) + stubMapping.request = request + stubMapping.response = response + return StubMapping.buildJsonStringFor(stubMapping) } } \ No newline at end of file diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/JsonStructureConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/JsonStructureConverter.groovy index f5860bfaad..b6b6f79eee 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/JsonStructureConverter.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/JsonStructureConverter.groovy @@ -2,7 +2,7 @@ package io.codearte.accurest.dsl.internal import groovy.json.JsonOutput import groovy.transform.CompileStatic -import io.codearte.accurest.util.JsonConverter +import io.codearte.accurest.util.MapConverter import java.util.regex.Pattern @@ -17,7 +17,7 @@ class JsonStructureConverter { Closure performAdditionalLogicOnSerializedJson, Closure convertSerializedJsonToSth) { LinkedList queue = new LinkedList<>() - def transformedJson = JsonConverter.transformValues(parsedJson, { + def transformedJson = MapConverter.transformValues(parsedJson, { if(retrievePlaceholders(it)) { queue.push(it) return TEMPORARY_PLACEHOLDER diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/MatchingStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/MatchingStrategy.groovy index c31c0b4bf6..191af8d7ee 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/MatchingStrategy.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/MatchingStrategy.groovy @@ -34,7 +34,7 @@ class MatchingStrategy extends DslProperty { enum Type { - EQUAL_TO("equalTo"), CONTAINS("contains"), MATCHING("matches"), NOT_MATCHING("doesNotMatch"), + EQUAL_TO("equalTo"), CONTAINS("containing"), MATCHING("matches"), NOT_MATCHING("doesNotMatch"), EQUAL_TO_JSON("equalToJson"), EQUAL_TO_XML("equalToXml"), ABSENT("absent") final String name diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/ContentUtils.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/ContentUtils.groovy index b42cadcf5c..a7e66f9ec3 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/util/ContentUtils.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/ContentUtils.groovy @@ -1,5 +1,6 @@ package io.codearte.accurest.util import groovy.json.JsonException +import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.transform.TypeChecked import groovy.util.logging.Slf4j @@ -18,6 +19,10 @@ import static org.apache.commons.lang3.StringEscapeUtils.escapeXml11 @Slf4j class ContentUtils { + public static final Closure GET_STUB_SIDE = { + it instanceof DslProperty ? it.clientValue : it + } + private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile('REGEXP>>(.*)<<') private static final String JSON_VALUE_PATTERN_FOR_REGEX = 'REGEXP>>%s<<' @@ -57,7 +62,57 @@ class ContentUtils { return extractValueForGString(bodyAsValue, valueProvider) } } + } + public static ContentType getClientContentType(GString bodyAsValue) { + try { + extractValueForJSON(bodyAsValue, GET_STUB_SIDE) + return ContentType.JSON + } catch(JsonException e) { + try { + new XmlSlurper().parseText(extractValueForXML(bodyAsValue, GET_STUB_SIDE).toString()) + return ContentType.XML + } catch (Exception exception) { + extractValueForGString(bodyAsValue, GET_STUB_SIDE) + return ContentType.UNKNOWN + } + } + } + + public static ContentType getClientContentType(String bodyAsValue) { + try { + new JsonSlurper().parseText(bodyAsValue) + return ContentType.JSON + } catch(JsonException e) { + try { + new XmlSlurper().parseText(bodyAsValue) + return ContentType.XML + } catch (Exception exception) { + return ContentType.UNKNOWN + } + } + } + + public static ContentType getClientContentType(Object bodyAsValue) { + return ContentType.UNKNOWN + } + + public static ContentType getClientContentType(Map bodyAsValue) { + try { + JsonOutput.toJson(bodyAsValue) + return ContentType.JSON + } catch (Exception ignore) { + return ContentType.UNKNOWN + } + } + + public static ContentType getClientContentType(List bodyAsValue) { + try { + JsonOutput.toJson(bodyAsValue) + return ContentType.JSON + } catch (Exception ignore) { + return ContentType.UNKNOWN + } } private static GStringImpl extractValueForGString(GString bodyAsValue, Closure valueProvider) { @@ -108,7 +163,7 @@ class ContentUtils { } private static Object convertAllTemporaryRegexPlaceholdersBackToPatterns(parsedJson) { - JsonConverter.transformValues(parsedJson, { Object value -> + MapConverter.transformValues(parsedJson, { Object value -> if (value instanceof String) { String string = (String) value Matcher matcher = TEMPORARY_PATTERN_HOLDER.matcher(string) diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathEntry.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathEntry.groovy new file mode 100644 index 0000000000..0e0f928f22 --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathEntry.groovy @@ -0,0 +1,41 @@ +package io.codearte.accurest.util + +import java.util.regex.Pattern + +class JsonPathEntry { + final String jsonPath + final String optionalSuffix + final Object value + + JsonPathEntry(String jsonPath, String optionalSuffix, Object value) { + this.jsonPath = jsonPath + this.optionalSuffix = optionalSuffix + this.value = value + } + + List buildJsonPathComparison(String parsedJsonVariable) { + if (optionalSuffix) { + return ["!${parsedJsonVariable}.read('''${jsonPath}''', JSONArray).empty"] + } else if (traversesOverCollections()) { + return ["${parsedJsonVariable}.read('''${jsonPath}''', JSONArray).size() == 1", + "${parsedJsonVariable}.read('''${jsonPath}''', JSONArray).get(0) ${operator()} ${potentiallyWrappedWithQuotesValue()}"] + } + return ["${parsedJsonVariable}.read('''${jsonPath}''') ${operator()} ${potentiallyWrappedWithQuotesValue()}"] + } + + private boolean traversesOverCollections() { + return jsonPath.contains('[*]') + } + + String operator() { + return value instanceof Pattern ? "==~" : "==" + } + + String potentiallyWrappedWithQuotesValue() { + return value instanceof Number ? value : "'''$value'''" + } + + static JsonPathEntry simple(String jsonPath, Object value) { + return new JsonPathEntry(jsonPath, "", value) + } +} diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathJsonConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathJsonConverter.groovy new file mode 100644 index 0000000000..28625a1cbf --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathJsonConverter.groovy @@ -0,0 +1,153 @@ +package io.codearte.accurest.util + +import groovy.json.JsonSlurper +import io.codearte.accurest.dsl.internal.DslProperty +import io.codearte.accurest.dsl.internal.ExecutionProperty + +import java.util.regex.Pattern +/** + * @author Marcin Grzejszczak + */ +class JsonPathJsonConverter { + + private static final Boolean SERVER_SIDE = false + private static final Boolean CLIENT_SIDE = true + + public static final String ROOT_JSON_PATH_ELEMENT = '$' + public static final String ALL_ELEMENTS = "[*]" + + public static JsonPaths transformToJsonPathWithTestsSideValues(def json) { + return transformToJsonPathWithValues(json, SERVER_SIDE) + } + + public static JsonPaths transformToJsonPathWithStubsSideValues(def json) { + return transformToJsonPathWithValues(json, CLIENT_SIDE) + } + + private static JsonPaths transformToJsonPathWithValues(def json, boolean clientSide) { + if(!json) { + return new JsonPaths() + } + JsonPaths pathsAndValues = [] as Set + Object convertedJson = getClientOrServerSideValues(json, clientSide) + traverseRecursivelyForKey(convertedJson, ROOT_JSON_PATH_ELEMENT) { String key, Object value -> + if (value instanceof ExecutionProperty) { + return + } + JsonPathEntry entry = getValueToInsert(key, value) + pathsAndValues.add(entry) + } + return pathsAndValues + } + + private static Object getClientOrServerSideValues(json, boolean clientSide) { + return MapConverter.transformValues(json) { + boolean dslProp = it instanceof DslProperty + if (dslProp) { + DslProperty dslProperty = ((DslProperty) it) + return clientSide ? + getClientOrServerSideValues(dslProperty.clientValue, clientSide) : getClientOrServerSideValues(dslProperty.serverValue, clientSide) + } + return it + } + } + + protected static def traverseRecursively(Class parentType, String key, def value, Closure closure) { + if (value instanceof String && value) { + try { + def json = new JsonSlurper().parseText(value) + if (json instanceof Map) { + return convertWithKey(parentType, key, json, closure) + } + } catch (Exception ignore) { + return closure(key, value) + } + } else if (isAnEntryWithNonCollectionLikeValue(value)) { + return convertWithKey(List, key, value as Map, closure) + } else if (isAnEntryWithoutNestedStructures(value)) { + return convertWithKey(List, key, value as Map, closure) + } else if (value instanceof Map) { + return convertWithKey(Map, key, value as Map, closure) + } else if (value instanceof List) { + value.each { def element -> + traverseRecursively(List, "$key[*]", element, closure) + } + return value + } + try { + return closure(key, value) + } catch (Exception ignore) { + return value + } + } + + private static boolean isAnEntryWithNonCollectionLikeValue(def value) { + if (!(value instanceof Map)) { + return false + } + Map valueAsMap = ((Map) value) + boolean mapHasOneEntry = valueAsMap.size() == 1 + if (!mapHasOneEntry) { + return false + } + Object valueOfEntry = valueAsMap.entrySet().first().value + return !(valueOfEntry instanceof Map || valueOfEntry instanceof List) + } + + private static boolean isAnEntryWithoutNestedStructures(def value) { + if (!(value instanceof Map)) { + return false + } + Map valueAsMap = ((Map) value) + return valueAsMap.entrySet().every { Map.Entry entry -> + [String, Number].any { entry.value.getClass().isAssignableFrom(it) } + } + } + + private static Map convertWithKey(Class parentType, String parentKey, Map map, Closure closureToExecute) { + return map.collectEntries { + String entrykey, value -> + [entrykey, traverseRecursively(parentType, "${parentKey}.${entrykey}", value, closureToExecute)] + } + } + + private static void traverseRecursivelyForKey(def json, String rootKey, Closure closure) { + traverseRecursively(Map, rootKey, json, closure) + } + + private static JsonPathEntry getValueToInsert(String key, Object value) { + return convertToListElementFiltering(key, value) + } + + protected static JsonPathEntry convertToListElementFiltering(String key, Object value) { + if (key.endsWith(ALL_ELEMENTS)) { + int lastAllElements = key.lastIndexOf(ALL_ELEMENTS) + String keyWithoutAllElements = key.substring(0, lastAllElements) + return JsonPathEntry.simple("""$keyWithoutAllElements[?(@ ${compareWith(value)})]""".toString(), value) + } + return getKeyForTraversalOfListWithNonPrimitiveTypes(key, value) + } + + private static JsonPathEntry getKeyForTraversalOfListWithNonPrimitiveTypes(String key, Object value) { + int lastDot = key.lastIndexOf('.') + String keyWithoutLastElement = key.substring(0, lastDot) + String lastElement = key.substring(lastDot + 1).replaceAll(~/\[\*\]/, "") + return new JsonPathEntry( + """$keyWithoutLastElement[?(@.$lastElement ${compareWith(value)})]""".toString(), + lastElement, + value + ) + } + + protected static String compareWith(Object value) { + if (value instanceof Pattern) { + return """=~ /${(value as Pattern).pattern()}/""" + } + return """== ${potentiallyWrappedWithQuotesValue(value)}""" + } + + protected static String potentiallyWrappedWithQuotesValue(Object value) { + return value instanceof Number ? value : "'$value'" + } + +} diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPaths.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPaths.groovy new file mode 100644 index 0000000000..6c4aad1214 --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPaths.groovy @@ -0,0 +1,23 @@ +package io.codearte.accurest.util + +class JsonPaths extends HashSet { + + Object getAt(String key) { + return find { + it.jsonPath == key + }?.value + } + + Object putAt(String key, Object value) { + JsonPathEntry entry = find { + it.jsonPath == key + } + if (!entry) { + return null + } + Object oldValue = entry.value + add(new JsonPathEntry(entry.jsonPath, entry.optionalSuffix, value)) + return oldValue + } +} + diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy similarity index 79% rename from accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy rename to accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy index 208a3aefa3..14568e7584 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonConverter.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy @@ -1,15 +1,16 @@ package io.codearte.accurest.util import groovy.json.JsonSlurper +import io.codearte.accurest.dsl.internal.DslProperty + /** * @author Marcin Grzejszczak */ -class JsonConverter { +class MapConverter { - private static Map convert(Map map, Closure closure) { - return map.collectEntries { - key, value -> - [key, transformValues(value, closure)] + static def transformToClientValues(def value) { + return transformValues(value) { + it instanceof DslProperty ? it.clientValue : it } } @@ -35,4 +36,11 @@ class JsonConverter { } } + private static Map convert(Map map, Closure closure) { + return map.collectEntries { + key, value -> + [key, transformValues(value, closure)] + } + } + } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBuilderSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBuilderSpec.groovy index 07123d6265..8bd272b7ac 100644 --- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBuilderSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBuilderSpec.groovy @@ -26,8 +26,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2 == '''b'''") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$[?(@.property2 == 'b')]") } @Issue("#79") @@ -54,9 +54,9 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2[0].a == '''sth'''") - blockBuilder.toString().contains("responseBody.property2[1].b == '''sthElse'''") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$.property2[*][?(@.a == 'sth')]") + blockBuilder.toString().contains("\$.property2[*][?(@.b == 'sthElse')]") } @Issue("#82") @@ -128,8 +128,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody[0].property1 == '''a'''") - blockBuilder.toString().contains("responseBody[1].property2 == '''b'''") + blockBuilder.toString().contains("\$[*][?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$[*][?(@.property2 == 'b')]") } def "should generate assertions for array inside response body element"() { @@ -154,8 +154,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1[0].property2 == '''test1'''") - blockBuilder.toString().contains("responseBody.property1[1].property3 == '''test2'''") + blockBuilder.toString().contains("\$.property1[*][?(@.property3 == 'test2')]") + blockBuilder.toString().contains("\$.property1[*][?(@.property2 == 'test1')]") } def "should generate assertions for nested objects in response body"() { @@ -180,8 +180,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2.property3 == '''b'''") + blockBuilder.toString().contains("\$.property2[?(@.property3 == 'b')]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should generate regex assertions for map objects in response body"() { @@ -212,8 +212,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2 ==~ java.util.regex.Pattern.compile('[0-9]{3}')") + blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should generate regex assertions for string objects in response body"() { @@ -238,8 +238,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2 ==~ java.util.regex.Pattern.compile('[0-9]{3}')") + blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should ignore 'Accept' header and use 'request' method"() { @@ -335,8 +335,8 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { spockTest.contains("queryParam('age', '99'") spockTest.contains("queryParam('name', 'Denis.Stepanov'") spockTest.contains("queryParam('email', 'bob@email.com'") - spockTest.contains("responseBody.property1 == '''a'''") - spockTest.contains("responseBody.property2 == '''b'''") + spockTest.contains('$[?(@.property2 == \'b\')]') + spockTest.contains('$[?(@.property1 == \'a\')]') } def "should generate test for empty body"() { @@ -372,12 +372,14 @@ class JaxRsClientSpockMethodBuilderSpec extends Specification { body "test" } } - JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) def spockTest = blockBuilder.toString() then: - spockTest.contains("responseBody == '''test'''") + spockTest.contains('def responseBody = (response.body.asString())') + spockTest.contains('responseBody == "test"') } + } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBuilderSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBuilderSpec.groovy index df36f3058f..dcbf988168 100644 --- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBuilderSpec.groovy +++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBuilderSpec.groovy @@ -3,15 +3,13 @@ package io.codearte.accurest.builder import io.codearte.accurest.dsl.GroovyDsl import spock.lang.Issue import spock.lang.Specification -import spock.lang.Unroll /** * @author Jakub Kubrynski */ class MockMvcSpockMethodBuilderSpec extends Specification { - @Unroll - def "should generate assertions for simple response body for [#spockMethodBuilder]"() { + def "should generate assertions for simple response body"() { given: GroovyDsl contractDsl = GroovyDsl.make { request { @@ -26,13 +24,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { }""" } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2 == '''b'''") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$[?(@.property2 == 'b')]") } @Issue("#79") @@ -54,14 +52,14 @@ class MockMvcSpockMethodBuilderSpec extends Specification { ) } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2[0].a == '''sth'''") - blockBuilder.toString().contains("responseBody.property2[1].b == '''sthElse'''") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$.property2[*][?(@.a == 'sth')]") + blockBuilder.toString().contains("\$.property2[*][?(@.b == 'sthElse')]") } @Issue("#82") @@ -79,7 +77,7 @@ class MockMvcSpockMethodBuilderSpec extends Specification { status 200 } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) @@ -102,7 +100,7 @@ class MockMvcSpockMethodBuilderSpec extends Specification { status 200 } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) @@ -128,13 +126,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { }]""" } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody[0].property1 == '''a'''") - blockBuilder.toString().contains("responseBody[1].property2 == '''b'''") + blockBuilder.toString().contains("\$[*][?(@.property1 == 'a')]") + blockBuilder.toString().contains("\$[*][?(@.property2 == 'b')]") } def "should generate assertions for array inside response body element"() { @@ -154,13 +152,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { }""" } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1[0].property2 == '''test1'''") - blockBuilder.toString().contains("responseBody.property1[1].property3 == '''test2'''") + blockBuilder.toString().contains("\$.property1[*][?(@.property3 == 'test2')]") + blockBuilder.toString().contains("\$.property1[*][?(@.property2 == 'test1')]") } def "should generate assertions for nested objects in response body"() { @@ -180,13 +178,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { ''' } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("responseBody.property1 == '''a'''") - blockBuilder.toString().contains("responseBody.property2.property3 == '''b'''") + blockBuilder.toString().contains("\$.property2[?(@.property3 == 'b')]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should generate regex assertions for map objects in response body"() { @@ -212,13 +210,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(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}')") + blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should generate regex assertions for string objects in response body"() { @@ -238,14 +236,13 @@ class MockMvcSpockMethodBuilderSpec extends Specification { } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(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}')") - + blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]") + blockBuilder.toString().contains("\$[?(@.property1 == 'a')]") } def "should generate a call with an url path and query parameters"() { @@ -278,15 +275,15 @@ class MockMvcSpockMethodBuilderSpec extends Specification { """ } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) def spockTest = blockBuilder.toString() then: spockTest.contains('get("/users?limit=10&offset=20&filter=email&sort=name&search=55&age=99&name=Denis.Stepanov&email=bob@email.com")') - spockTest.contains("responseBody.property1 == '''a'''") - spockTest.contains("responseBody.property2 == '''b'''") + spockTest.contains('$[?(@.property2 == \'b\')]') + spockTest.contains('$[?(@.property1 == \'a\')]') } def "should generate test for empty body"() { @@ -301,7 +298,7 @@ class MockMvcSpockMethodBuilderSpec extends Specification { status 406 } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) @@ -322,45 +319,14 @@ class MockMvcSpockMethodBuilderSpec extends Specification { body "test" } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) def spockTest = blockBuilder.toString() then: spockTest.contains('def responseBody = (response.body.asString())') - spockTest.contains("responseBody == '''test'''") - } - - @Issue("#127") - def 'should use "stub" as an alias for "client"'() { - given: - GroovyDsl contractDsl = GroovyDsl.make { - request { - method "GET" - url "test" - } - response { - status 200 - body( - property: value( - stub(123), - test(123) - ) - ) - headers { - header('Content-Type': 'application/json') - - } - - } - } - MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - when: - builder.appendTo(blockBuilder) - then: - blockBuilder.toString().contains("responseBody.property == 123") + spockTest.contains('responseBody == "test"') } @Issue('113') @@ -387,7 +353,7 @@ class MockMvcSpockMethodBuilderSpec extends Specification { } } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) @@ -420,7 +386,7 @@ class MockMvcSpockMethodBuilderSpec extends Specification { } } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) @@ -429,31 +395,38 @@ class MockMvcSpockMethodBuilderSpec extends Specification { spockTest.contains('''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''') } - @Issue('124') - def "should create proper response body matching for multiline strings"() { + def "should work with more complex stuff and jsonpaths"() { given: GroovyDsl contractDsl = GroovyDsl.make { - + priority 10 request { method 'POST' - url '/invitations' + url '/validation/client' + headers { + header 'Content-Type': 'application/json' + } + body( + bank_account_number: '0014282912345698765432161182', + email: 'foo@bar.com', + phone_number: '100299300', + personal_id: 'ABC123456' + ) } response { - status 422 - body( - message: "First line\n" + - " Second line" - ) + status 200 + body(errors: [ + [property: "bank_account_number", message: "incorrect_format"] + ]) } } - SpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) + MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: builder.appendTo(blockBuilder) def spockTest = blockBuilder.toString() then: - spockTest.contains("""responseBody.message == '''First line - Second line'''""") + spockTest.contains('''$.errors[*][?(@.property == 'bank_account_number')]''') + spockTest.contains('''$.errors[*][?(@.message == 'incorrect_format')]''') } } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockGroovyDslResponseSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockGroovyDslResponseSpec.groovy deleted file mode 100644 index 07eb9aebda..0000000000 --- a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockGroovyDslResponseSpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package io.codearte.accurest.dsl - -import groovy.json.JsonSlurper -import spock.lang.Specification - -class WireMockGroovyDslResponseSpec extends Specification { - - def 'should generate response without body for client side'() { - given: - GroovyDsl dsl = GroovyDsl.make { - response { - status 200 - } - } - expect: - new WireMockResponseStubStrategy(dsl).buildClientResponseContent() == new JsonSlurper().parseText(expectedStub) - where: - expectedStub << [''' - { - "status": 200 - } - ''', - - ''' - { - "status": 200 - } - '''] - } - - def 'should generate headers for response for client side'() { - given: - GroovyDsl dsl = GroovyDsl.make { - response { - headers { - header 'Content-Type', $(client('text/xml'), server('text/*')) - } - status 200 - } - } - expect: - new WireMockResponseStubStrategy(dsl).buildClientResponseContent() == new JsonSlurper().parseText(''' - { - "headers": { - "Content-Type": "text/xml" - }, - "status": 200 - } - ''') - } - -} 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 cb0a75255a..3356c1a7c9 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 @@ -1,7 +1,7 @@ package io.codearte.accurest.dsl - import groovy.json.JsonBuilder import groovy.json.JsonSlurper +import org.skyscreamer.jsonassert.JSONAssert import spock.lang.Issue class WireMockGroovyDslSpec extends WireMockSpec { @@ -35,21 +35,21 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' -{ - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}" - }, - "response": { - "status": 200, - "body": "{\\"id\\":\\"123\\",\\"surname\\":\\"Kowalsky\\",\\"name\\":\\"Jan\\",\\"created\\":\\"2014-02-02 12:23:43\\"}", - "headers": { - "Content-Type": "text/plain" - } - } -} -''') + JSONAssert.assertEquals(''' + { + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET" + }, + "response" : { + "status" : 200, + "body" : "{\\"id\\":\\"123\\",\\"surname\\":\\"Kowalsky\\",\\"name\\":\\"Jan\\",\\"created\\":\\"2014-02-02 12:23:43\\"}", + "headers" : { + "Content-Type" : "text/plain" + } + } + } + ''', wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -80,23 +80,23 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals(''' { - "request": { - "method": "GET", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.pl.devoxx.aggregatr.v1+json" - } - }, - "url": "/ingredients" - }, - "response": { - "status": 200, - "body": "{\\"ingredients\\":[{\\"type\\":\\"MALT\\",\\"quantity\\":100},{\\"type\\":\\"WATER\\",\\"quantity\\":200},{\\"type\\":\\"HOP\\",\\"quantity\\":300},{\\"type\\":\\"YIEST\\",\\"quantity\\":400}]}" + "request" : { + "url" : "/ingredients", + "method" : "GET", + "headers" : { + "Content-Type" : { + "equalTo" : "application/vnd.pl.devoxx.aggregatr.v1+json" + } } + }, + "response" : { + "status" : 200, + "body" : "{\\"ingredients\\":[{\\"type\\":\\"MALT\\",\\"quantity\\":100},{\\"type\\":\\"WATER\\",\\"quantity\\":200},{\\"type\\":\\"HOP\\",\\"quantity\\":300},{\\"type\\":\\"YIEST\\",\\"quantity\\":400}]}" + } } -''') +''', wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -128,7 +128,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals(''' { "request": { "method": "POST", @@ -149,7 +149,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "body": "{\\"paymentId\\":\\"4\\",\\"foundExistingPayment\\":false}" } } -''') +''', wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -180,21 +180,21 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals((''' { - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}" - }, - "response": { - "status": 200, - "body": "{\\"created\\":\\"2014-02-02 12:23:43\\",\\"id\\":\\"123\\",\\"name\\":\\"Jan\\",\\"surname\\":\\"Kowalsky\\"}", - "headers": { - "Content-Type": "text/plain" - } + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET" + }, + "response" : { + "status" : 200, + "body" : "{\\"created\\":\\"2014-02-02 12:23:43\\",\\"id\\":\\"123\\",\\"name\\":\\"Jan\\",\\"surname\\":\\"Kowalsky\\"}", + "headers" : { + "Content-Type" : "text/plain" } + } } -''') +'''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -227,26 +227,24 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals(''' { - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}", - "bodyPatterns": [ - { - "equalToJson":"{\\"name\\":\\"Jan\\"}" - } - ] - }, - "response": { - "status": 200, - "body": "{\\"name\\":\\"Jan\\"}", - "headers": { - "Content-Type": "text/plain" - } + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.name == 'Jan')]" + } ] + }, + "response" : { + "status" : 200, + "body" : "{\\"name\\":\\"Jan\\"}", + "headers" : { + "Content-Type" : "text/plain" } + } } -''') +''', wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -277,22 +275,26 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' - { - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}", - "bodyPatterns": [ - { - "equalToJson": "{\\"id\\":\\"123\\",\\"surname\\":\\"Kowalsky\\",\\"name\\":\\"Jan\\",\\"created\\":\\"2014-02-02 12:23:43\\"}" - } - ] - }, - "response": { - "status": 200, - } - } - ''') + JSONAssert.assertEquals((''' +{ + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.created == '2014-02-02 12:23:43')]" + }, { + "matchesJsonPath" : "$[?(@.surname == 'Kowalsky')]" + }, { + "matchesJsonPath" : "$[?(@.name == 'Jan')]" + }, { + "matchesJsonPath" : "$[?(@.id == '123')]" + } ] + }, + "response" : { + "status" : 200 + } +} + '''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -319,27 +321,25 @@ class WireMockGroovyDslSpec extends WireMockSpec { 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 - } - } - ''') + JSONAssert.assertEquals((''' +{ + "request" : { + "url" : "/users", + "method" : "GET", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.name == 'Jan')]" + } ], + "headers" : { + "Content-Type" : { + "equalTo" : "customtype/json" + } + } + }, + "response" : { + "status" : 200 + } +} + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -364,7 +364,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -384,7 +384,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200 } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -406,7 +406,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -421,7 +421,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200 } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -443,7 +443,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -454,7 +454,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "body":"Jozo<test>" } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -474,7 +474,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -489,7 +489,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200 } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -511,7 +511,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -526,7 +526,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200 } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -559,24 +559,24 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals((''' { - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}", - "bodyPatterns": [ - {"matches": "\\\\s*\\\\{\\\\s*\\\"personalId\\\"\\\\s*:\\\\s*\\\"?^[0-9]{11}$\\\"?\\\\s*\\\\}\\\\s*"} - ] - }, - "response": { - "status": 200, - "body": "{\\"name\\":\\"Jan\\"}", - "headers": { - "Content-Type": "text/plain" - } + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.personalId =~ /^[0-9]{11}$/)]" + } ] + }, + "response" : { + "status" : 200, + "body" : "{\\"name\\":\\"Jan\\"}", + "headers" : { + "Content-Type" : "text/plain" } + } } -''') +'''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -614,84 +614,35 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals((''' { - "request": { - "method": "PUT", - "headers": { - "Content-Type": { - "equalTo": "application/vnd.fraud.v1+json" - } - }, - "url": "/fraudcheck", - "bodyPatterns": [ - {"matches": "\\\\s*\\\\{\\\\s*\\"clientPesel\\"\\\\s*:\\\\s*\\"?[0-9]{10}\\"?\\\\s*,\\\\s*\\"loanAmount\\"\\\\s*:\\\\s*\\"?123.123\\"?\\\\s*\\\\}\\\\s*"} - ] - }, - "response": { - "status": 200, - "headers": { - "Content-Type": "application/vnd.fraud.v1+json" - }, - "body": "{\\"fraudCheckStatus\\":\\"OK\\",\\"rejectionReason\\":null}" + "request" : { + "url" : "/fraudcheck", + "method" : "PUT", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.loanAmount == 123.123)]" + }, { + "matchesJsonPath" : "$[?(@.clientPesel =~ /[0-9]{10}/)]" + } ], + "headers" : { + "Content-Type" : { + "equalTo" : "application/vnd.fraud.v1+json" + } } + }, + "response" : { + "status" : 200, + "body" : "{\\"fraudCheckStatus\\":\\"OK\\",\\"rejectionReason\\":null}", + "headers" : { + "Content-Type" : "application/vnd.fraud.v1+json" + } + } } -''') +'''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } - - def "should generate stub with GET"() { - given: - GroovyDsl groovyDsl = GroovyDsl.make { - request { - method("GET") - } - } - expect: - new WireMockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText(''' - { - "method":"GET" - } - ''') - } - - def "should generate request when two elements are provided "() { - given: - GroovyDsl groovyDsl = GroovyDsl.make { - request { - method("GET") - url("/sth") - } - } - expect: - new WireMockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText(''' - { - "method":"GET", - "url":"/sth" - } - ''') - } - - def "should generate request with urlPattern for client side"() { - given: - GroovyDsl groovyDsl = GroovyDsl.make { - request { - url $( - client(~/^\/[0-9]{2}$/), - server('/12') - ) - } - } - expect: - new WireMockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText(''' - { - "urlPattern":"^/[0-9]{2}$" - } - ''') - } - def "should generate request with urlPath and queryParameters for client side"() { given: GroovyDsl groovyDsl = GroovyDsl.make { @@ -717,7 +668,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -753,7 +704,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200, } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -772,7 +723,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -782,7 +733,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200, } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -801,7 +752,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -811,7 +762,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200, } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } @@ -947,7 +898,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "GET", @@ -965,46 +916,11 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200, } } - ''') + '''), json, false) and: stubMappingIsValidWireMockStub(json) } - def "should generate stub with some headers section for client side"() { - given: - GroovyDsl groovyDsl = GroovyDsl.make { - request { - headers { - header('Content-Type': 'text/xml') - header('Accept': $( - client(regex('text/.*')), - server('text/plain') - )) - header('X-Custom-Header': $( - client(regex('^.*2134.*$')), - server('121345') - )) - } - } - } - expect: - new WireMockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText(''' - { - "headers": { - "Content-Type": { - "equalTo": "text/xml" - }, - "Accept": { - "matches": "text/.*" - }, - "X-Custom-Header": { - "matches": "^.*2134.*$" - } - } - } - ''') - } - def 'should convert groovy dsl stub with rich tree Body as String to wireMock stub for the client side'() { given: GroovyDsl groovyDsl = GroovyDsl.make { @@ -1046,25 +962,38 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' - { - "request": { - "method": "GET", - "urlPattern": "/[0-9]{2}", - "bodyPatterns": [ - { - "matches": "\\\\s*\\\\{\\\\s*\\"birthDate\\"\\\\s*:\\\\s*\\"?[0-9]{4}-[0-9]{2}-[0-9]{2}\\"?\\\\s*,\\\\s*\\"errors\\"\\\\s*:\\\\s*\\\\[\\\\s*\\\\{\\\\s*\\"propertyName\\"\\\\s*:\\\\s*\\"?[0-9]{2}\\"?\\\\s*,\\\\s*\\"providerValue\\"\\\\s*:\\\\s*\\"?Test\\"?\\\\s*\\\\}\\\\s*,\\\\s*\\\\{\\\\s*\\"propertyName\\"\\\\s*:\\\\s*\\"?[0-9]{2}\\"?\\\\s*,\\\\s*\\"providerValue\\"\\\\s*:\\\\s*\\"?Test\\"?\\\\s*\\\\}\\\\s*\\\\]\\\\s*,\\\\s*\\"firstName\\"\\\\s*:\\\\s*\\"?.*\\"?\\\\s*,\\\\s*\\"lastName\\"\\\\s*:\\\\s*\\"?.*\\"?\\\\s*,\\\\s*\\"personalId\\"\\\\s*:\\\\s*\\"?[0-9]{11}\\"?\\\\s*\\\\}\\\\s*" - } - ] }, - "response": { - "status": 200, - "body": "{\\"name\\":\\"Jan\\"}", - "headers": { - "Content-Type": "text/plain" - } - } - } - ''') + JSONAssert.assertEquals((''' +{ + "request" : { + "urlPattern" : "/[0-9]{2}", + "method" : "GET", + "bodyPatterns" : [ { + "matchesJsonPath" : "$.errors[*][?(@.propertyName =~ /[0-9]{2}/)]" + }, { + "matchesJsonPath" : "$.errors[*][?(@.providerValue == 'Test')]" + }, { + "matchesJsonPath" : "$.errors[*][?(@.providerValue == 'Test')]" + }, { + "matchesJsonPath" : "$[?(@.lastName =~ /.*/)]" + }, { + "matchesJsonPath" : "$.errors[*][?(@.propertyName =~ /[0-9]{2}/)]" + }, { + "matchesJsonPath" : "$[?(@.birthDate =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/)]" + }, { + "matchesJsonPath" : "$[?(@.personalId =~ /[0-9]{11}/)]" + }, { + "matchesJsonPath" : "$[?(@.firstName =~ /.*/)]" + } ] + }, + "response" : { + "status" : 200, + "body" : "{\\"name\\":\\"Jan\\"}", + "headers" : { + "Content-Type" : "text/plain" + } + } +} + '''), wireMockStub, false) } def 'should use regexp matches when request body match is defined using a map with a pattern'() { @@ -1097,26 +1026,34 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' - { - "request": { - "method": "POST", - "url": "/reissue-payment-order", - "bodyPatterns": [ - { - "matches": "\\\\s*\\\\{\\\\s*\\"loanNumber\\"\\\\s*:\\\\s*\\"?999997001\\"?\\\\s*,\\\\s*\\"amount\\"\\\\s*:\\\\s*\\"?[0-9.]+\\"?\\\\s*,\\\\s*\\"currency\\"\\\\s*:\\\\s*\\"?DKK\\"?\\\\s*,\\\\s*\\"applicationName\\"\\\\s*:\\\\s*\\"?.*\\"?\\\\s*,\\\\s*\\"username\\"\\\\s*:\\\\s*\\"?.*\\"?\\\\s*,\\\\s*\\"cardId\\"\\\\s*:\\\\s*\\"?1\\"?\\\\s*\\\\}\\\\s*" - } - ] - }, - "response": { - "status": 200, - "body": "{\\"status\\":\\"OK\\"}", - "headers": { - "Content-Type": "application/json" - } - } - } - ''') + JSONAssert.assertEquals((''' +{ + "request" : { + "url" : "/reissue-payment-order", + "method" : "POST", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.loanNumber == '999997001')]" + }, { + "matchesJsonPath" : "$[?(@.username =~ /.*/)]" + }, { + "matchesJsonPath" : "$[?(@.amount =~ /[0-9.]+/)]" + }, { + "matchesJsonPath" : "$[?(@.cardId == 1)]" + }, { + "matchesJsonPath" : "$[?(@.currency == 'DKK')]" + }, { + "matchesJsonPath" : "$[?(@.applicationName =~ /.*/)]" + } ] + }, + "response" : { + "status" : 200, + "body" : "{\\"status\\":\\"OK\\"}", + "headers" : { + "Content-Type" : "application/json" + } + } +} + '''), json, false) } def "should generate stub for empty body"() { @@ -1134,7 +1071,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "request": { "method": "POST", @@ -1149,7 +1086,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 406 } } -''') +'''), json, false) } def "should generate stub with priority"() { @@ -1167,7 +1104,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: def json = toWireMockClientJsonStub(groovyDsl) then: - parseJson(json) == parseJson(''' + JSONAssert.assertEquals((''' { "priority": 9, "request": { @@ -1178,7 +1115,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 406 } } - ''') + '''), json, false) } @Issue("#127") @@ -1198,21 +1135,19 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' - { - "request": { - "method": "POST", - "bodyPatterns": [ - { - "equalToJson": "{\\"property\\":\\"value\\"}" - } - ] - }, - "response": { - "status": 200 - } - } - ''') + JSONAssert.assertEquals((''' +{ + "request" : { + "method" : "POST", + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.property == 'value')]" + } ] + }, + "response" : { + "status" : 200 + } +} + '''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } @@ -1234,7 +1169,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { when: String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub() then: - new JsonSlurper().parseText(wireMockStub) == new JsonSlurper().parseText(''' + JSONAssert.assertEquals((''' { "request": { "method": "POST", @@ -1248,7 +1183,7 @@ class WireMockGroovyDslSpec extends WireMockSpec { "status": 200 } } - ''') + '''), wireMockStub, false) and: stubMappingIsValidWireMockStub(wireMockStub) } diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonPathJsonConverterSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonPathJsonConverterSpec.groovy new file mode 100644 index 0000000000..a7e9f621d7 --- /dev/null +++ b/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonPathJsonConverterSpec.groovy @@ -0,0 +1,199 @@ +package io.codearte.accurest.util +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import com.jayway.jsonpath.Configuration +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import com.jayway.jsonpath.Option +import net.minidev.json.JSONArray +import spock.lang.Specification +import spock.lang.Unroll + +import java.util.regex.Pattern + +class JsonPathJsonConverterSpec extends Specification { + + @Unroll + def 'should convert a json with list as root to a map of path to value'() { + when: + JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) + then: + pathAndValues['''$[*].some.nested[?(@.json == 'with value')]'''] == 'with value' + pathAndValues['''$[*].some.nested[?(@.anothervalue == 4)]'''] == 4 + pathAndValues['''$[*].some.nested.withlist[*][?(@.name == 'name1')]'''] == 'name1' + pathAndValues['''$[*].some.nested.withlist[*][?(@.name == 'name2')]'''] == 'name2' + pathAndValues['''$[*].some.nested.withlist[*].anothernested[?(@.name == 'name3')]'''] == 'name3' + and: + assertThatJsonPathsInMapAreValid(json, pathAndValues) + where: + json << [ + ''' + [ { + "some" : { + "nested" : { + "json" : "with value", + "anothervalue": 4, + "withlist" : [ + { "name" :"name1"} , {"name": "name2"}, {"anothernested": { "name": "name3"} } + ] + } + } + }, + { + "someother" : { + "nested" : { + "json" : "with value", + "anothervalue": 4, + "withlist" : [ + { "name" :"name1"} , {"name": "name2"} + ] + } + } + } + ] + ''', + ''' + [{ + "someother" : { + "nested" : { + "json" : "with value", + "anothervalue": 4, + "withlist" : [ + { "name" :"name1"} , {"name": "name2"} + ] + } + } + }, + { + "some" : { + "nested" : { + "json" : "with value", + "anothervalue": 4, + "withlist" : [ + {"name": "name2"}, {"anothernested": { "name": "name3"} }, { "name" :"name1"} + ] + } + } + } + ]'''] + } + + def 'should convert a json with a map as root to a map of path to value'() { + given: + String json = ''' + { + "some" : { + "nested" : { + "json" : "with value", + "anothervalue": 4, + "withlist" : [ + { "name" :"name1"} , {"name": "name2"} + ] + } + } + } +''' + when: + JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) + then: + pathAndValues['''$.some.nested[?(@.json == 'with value')]'''] == 'with value' + pathAndValues['''$.some.nested[?(@.anothervalue == 4)]'''] == 4 + pathAndValues['''$.some.nested.withlist[*][?(@.name == 'name1')]'''] == 'name1' + pathAndValues['''$.some.nested.withlist[*][?(@.name == 'name2')]'''] == 'name2' + and: + assertThatJsonPathsInMapAreValid(json, pathAndValues) + } + + def 'should convert a json with a list'() { + given: + String json = ''' + { + "items" : ["HOP"] + } +''' + when: + JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) + then: + pathAndValues['''$.items[?(@ == 'HOP')]'''] == 'HOP' + and: + assertThatJsonPathsInMapAreValid(json, pathAndValues) + } + + + def 'should convert a json with a list of errors'() { + given: + String json = ''' + { + "errors" : [ + { "property" : "email", "message" : "inconsistent value" }, + { "property" : "email", "message" : "inconsistent value2" } + ] + } +''' + when: + JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) + then: + pathAndValues['''$.errors[*][?(@.property == 'email')]'''] == 'email' + pathAndValues['''$.errors[*][?(@.message == 'inconsistent value')]'''] == 'inconsistent value' + pathAndValues['''$.errors[*][?(@.message == 'inconsistent value2')]'''] == 'inconsistent value2' + pathAndValues['''$.errors[*][?(@.property == 'email')]'''] == 'email' + and: + assertThatJsonPathsInMapAreValid(json, pathAndValues) + } + + + def 'should convert a map json with a regex pattern'() { + given: + List json = [ + [some: + [nested: [ + json: "with value", + anothervalue: 4, + withlist: + [ + [name: "name2"], + [name: "name1"], + [anothernested: + [name: Pattern.compile('[a-zA-Z]+')] + ], + [age: "123456789"] + ] + ] + ] + ], + [someother: + [nested: [ + json: "with value", + anothervalue: 4, + withlist: + [ + [name: "name2"], + [name: "name1"] + ] + ] + ] + ] + ] + when: + JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(json) + then: + pathAndValues['''$[*].some.nested[?(@.json == 'with value')]'''] == 'with value' + pathAndValues['''$[*].some.nested[?(@.anothervalue == 4)]'''] == 4 + pathAndValues['''$[*].some.nested.withlist[*][?(@.name == 'name1')]'''] == 'name1' + pathAndValues['''$[*].some.nested.withlist[*][?(@.name == 'name2')]'''] + (pathAndValues['''$[*].some.nested.withlist[*].anothernested[?(@.name =~ /[a-zA-Z]+/)]'''] as Pattern).pattern() == '[a-zA-Z]+' + when: + pathAndValues['''$[*].some.nested.withlist[*].anothernested[?(@.name =~ /[a-zA-Z]+/)]'''] = "Kowalski" + json.some.nested.withlist[0][2].anothernested.name = "Kowalski" + then: + assertThatJsonPathsInMapAreValid(JsonOutput.prettyPrint(JsonOutput.toJson(json)), pathAndValues) + } + + private void assertThatJsonPathsInMapAreValid(String json, JsonPaths pathAndValues) { + DocumentContext parsedJson = JsonPath.using(Configuration.builder().options(Option.ALWAYS_RETURN_LIST).build()).parse(json); + pathAndValues.each { + assert parsedJson.read(it.jsonPath, JSONArray).getAt(it.optionalSuffix ?: 0) == it.optionalSuffix ? [it.value] : it.value + } + } + +} diff --git a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy index dcec7b2f61..f93809b40a 100644 --- a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy +++ b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/AccurestGradlePlugin.groovy @@ -4,6 +4,7 @@ import io.codearte.accurest.config.AccurestConfigProperties import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.artifacts.DependencyResolveDetails /** * @author Jakub Kubrynski @@ -29,6 +30,21 @@ class AccurestGradlePlugin implements Plugin { createGenerateTestsTask(extension) createAndConfigureGenerateWireMockClientStubsFromDslTask(extension) deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask() + project.dependencies.add("testCompile", "io.codearte.accurest:accurest-core:+") + project.dependencies.add("testCompile", "com.blogspot.toomuchcoding:wiremock:0.0.1") + project.repositories { jcenter() } + project.configurations { + all { + resolutionStrategy { + eachDependency { DependencyResolveDetails details -> + if (details.requested.group == 'com.github.tomakehurst' && details.requested.name == "wiremock") { + details.useTarget("com.blogspot.toomuchcoding:wiremock:0.0.1") + } + } + } + } + } + project.afterEvaluate { def hasIdea = project.plugins.findPlugin(IDEA_PLUGIN_CLASS) diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle index 068c0f6e47..aa4e17339c 100644 --- a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle +++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle @@ -18,7 +18,6 @@ ext { subprojects { apply plugin: 'groovy' - repositories { mavenCentral() mavenLocal() diff --git a/build.gradle b/build.gradle index 8b8d47bb77..b77eab32f6 100644 --- a/build.gradle +++ b/build.gradle @@ -48,6 +48,7 @@ subprojects { repositories { mavenLocal() mavenCentral() + jcenter() } //Dependencies in all subprojects - http://solidsoft.wordpress.com/2014/11/13/gradle-tricks-display-dependencies-for-all-subprojects-in-multi-project-build/ @@ -84,15 +85,21 @@ subprojects { } project(':accurest-core') { + dependencies { compile 'org.slf4j:slf4j-api:[1.6.0,)' compile 'org.codehaus.plexus:plexus-utils:[3.0.0,)' compile 'commons-io:commons-io:[2.0,)' compile 'org.apache.commons:commons-lang3:[3.3,)' + compile 'com.google.code.gson:gson:2.3.1' + compile 'com.fasterxml.jackson.core:jackson-databind:2.4.5' + compile 'asm:asm:3.3.1' + compile 'com.blogspot.toomuchcoding:wiremock:0.0.1' testCompile 'cglib:cglib-nodep:2.2' testCompile 'org.objenesis:objenesis:2.1' - testCompile 'com.github.tomakehurst:wiremock:1.57' + testCompile 'org.skyscreamer:jsonassert:1.2.3' } + } project(':accurest-converters') { @@ -101,7 +108,7 @@ project(':accurest-converters') { compile 'org.apache.commons:commons-lang3:[3.0,)' compile 'commons-io:commons-io:[2.0,)' compile 'dk.brics.automaton:automaton:1.11-8' // needed for Xeger - testCompile 'com.github.tomakehurst:wiremock:1.57' + testCompile 'com.blogspot.toomuchcoding:wiremock:0.0.1' testCompile 'org.hamcrest:hamcrest-all:1.3' } } diff --git a/gradle/release.gradle b/gradle/release.gradle index 34e8ae08ef..3300caac3c 100644 --- a/gradle/release.gradle +++ b/gradle/release.gradle @@ -12,7 +12,7 @@ task sourcesJar(type: Jar) { } artifacts { - archives javadocJar, sourcesJar + archives javadocJar, sourcesJar, repackagedJar } signing {