[PPL-202] Fixed GString support in body with regex

This commit is contained in:
Marcin Grzejszczak
2015-09-03 14:17:59 +02:00
parent 7782d82ba4
commit f824415523
8 changed files with 88 additions and 24 deletions

View File

@@ -6,7 +6,7 @@ import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.*
import io.codearte.accurest.util.ContentType
import io.codearte.accurest.util.MapConverter
import io.codearte.accurest.util.JsonPathJsonConverter
import io.codearte.accurest.util.JsonToJsonPathsConverter
import io.codearte.accurest.util.JsonPaths
import static io.codearte.accurest.util.ContentUtils.*
@@ -86,7 +86,7 @@ abstract class SpockMethodBodyBuilder {
}
if (contentType == ContentType.JSON) {
appendJsonPath(bb, responseAsString)
JsonPaths jsonPaths = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(responseBody)
JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(responseBody)
jsonPaths.each {
it.buildJsonPathComparison('parsedJson').each {
bb.addLine(it)

View File

@@ -9,14 +9,14 @@ 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.JsonToJsonPathsConverter
import io.codearte.accurest.util.JsonPaths
import io.codearte.accurest.util.MapConverter
import java.util.regex.Pattern
import static io.codearte.accurest.util.ContentUtils.*
import static io.codearte.accurest.util.RegexpBuilders.buildGStringRegexpMatch
import static io.codearte.accurest.util.RegexpBuilders.buildGStringRegexpForStubSide
import static io.codearte.accurest.util.RegexpBuilders.buildJSONRegexpMatch
@TypeChecked
@@ -53,7 +53,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
}
ContentType contentType = tryToGetContentType()
if (contentType == ContentType.JSON) {
JsonPaths values = JsonPathJsonConverter.transformToJsonPathWithStubsSideValues(getMatchingStrategyFromBody(request.body)?.clientValue)
JsonPaths values = JsonToJsonPathsConverter.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) ) ]
@@ -183,7 +183,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
case ContentType.JSON:
return new MatchingStrategy(buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING)
case ContentType.UNKNOWN:
return new MatchingStrategy(buildGStringRegexpMatch(value), MatchingStrategy.Type.MATCHING)
return new MatchingStrategy(buildGStringRegexpForStubSide(value), MatchingStrategy.Type.MATCHING)
case ContentType.XML:
throw new IllegalStateException("XML pattern matching is not implemented yet")
}

View File

@@ -9,7 +9,7 @@ class RegexPatterns {
private static final Pattern IP_ADDRESS = Pattern.compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])');
private static final Pattern HOSTNAME_PATTERN = Pattern.compile('((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?');
private static final Pattern EMAIL = Pattern.compile('[_]*([a-z0-9]+(\\.|_*)?)+@([a-z][a-z0-9-]+(\\.|-*\\.))+[a-z]{2,6}');
private static final Pattern EMAIL = Pattern.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}');
private static final Pattern URL = Pattern.compile('((www\\.|(http|https|ftp|news|file)+\\:\\/\\/)[_.a-z0-9-]+\\.[a-z0-9\\/_:@=.+?,##%&~-]*[^.|\\\'|\\# |!|\\(|?|,| |>|<|;|\\)])');
String ipAddress() {

View File

@@ -8,7 +8,7 @@ import java.util.regex.Pattern
/**
* @author Marcin Grzejszczak
*/
class JsonPathJsonConverter {
class JsonToJsonPathsConverter {
private static final Boolean SERVER_SIDE = false
private static final Boolean CLIENT_SIDE = true
@@ -42,11 +42,18 @@ class JsonPathJsonConverter {
private static Object getClientOrServerSideValues(json, boolean clientSide) {
return MapConverter.transformValues(json) {
boolean dslProp = it instanceof DslProperty
if (dslProp) {
if (it instanceof DslProperty) {
DslProperty dslProperty = ((DslProperty) it)
return clientSide ?
getClientOrServerSideValues(dslProperty.clientValue, clientSide) : getClientOrServerSideValues(dslProperty.serverValue, clientSide)
} else if (it instanceof GString) {
return ContentUtils.extractValue(it , null, {
if (it instanceof DslProperty) {
return clientSide ?
getClientOrServerSideValues((it as DslProperty).clientValue, clientSide) : getClientOrServerSideValues((it as DslProperty).serverValue, clientSide)
}
return it
})
}
return it
}
@@ -142,6 +149,8 @@ class JsonPathJsonConverter {
protected static String compareWith(Object value) {
if (value instanceof Pattern) {
return """=~ /${(value as Pattern).pattern()}/"""
} else if (value instanceof GString) {
return """=~ /${RegexpBuilders.buildGStringRegexpForTestSide(value)}/"""
}
return """== ${potentiallyWrappedWithQuotesValue(value)}"""
}

View File

@@ -10,29 +10,48 @@ import static org.apache.commons.lang3.StringEscapeUtils.escapeJson
public class RegexpBuilders {
public static String buildGStringRegexpMatch(GString gString) {
public static String buildGStringRegexpForStubSide(GString gString) {
new GStringImpl(
gString.values.collect(this.&buildGStringRegexpMatch) as Object[],
gString.values.collect(this.&buildGStringRegexpForStubSide) as Object[],
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
)
}
public static String buildGStringRegexpMatch(Pattern pattern) {
public static String buildGStringRegexpForStubSide(Pattern pattern) {
return pattern.pattern()
}
public static String buildGStringRegexpMatch(DslProperty dslProperty) {
return buildGStringRegexpMatch(dslProperty.clientValue)
public static String buildGStringRegexpForStubSide(DslProperty dslProperty) {
return buildGStringRegexpForStubSide(dslProperty.clientValue)
}
public static String buildGStringRegexpMatch(Object o) {
public static String buildGStringRegexpForStubSide(Object o) {
return escapeSpecialRegexChars(o.toString())
}
public static String buildGStringRegexpForTestSide(GString gString) {
new GStringImpl(
gString.values.collect(this.&buildGStringRegexpForTestSide) as Object[],
gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
)
}
public static String buildGStringRegexpForTestSide(Pattern pattern) {
return pattern.pattern()
}
public static String buildGStringRegexpForTestSide(DslProperty dslProperty) {
return buildGStringRegexpForTestSide(dslProperty.clientValue)
}
public static String buildGStringRegexpForTestSide(Object o) {
return o.toString().replaceAll('\\\\', '\\\\\\\\')
}
private final static Pattern SPECIAL_REGEX_CHARS = Pattern.compile('[{}()\\[\\].+*?^$\\\\|]')
private static String escapeSpecialRegexChars(String str) {
return SPECIAL_REGEX_CHARS.matcher(str).replaceAll('\\\\$0')
return SPECIAL_REGEX_CHARS.matcher(str).replaceAll('\\\\\\\\$0')
}
private final static String WS = /\s*/

View File

@@ -429,4 +429,39 @@ class MockMvcSpockMethodBuilderSpec extends Specification {
spockTest.contains('''$.errors[*][?(@.property == 'bank_account_number')]''')
spockTest.contains('''$.errors[*][?(@.message == 'incorrect_format')]''')
}
def "should resolve properties in GString with regular expression"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
header 'Content-Type': 'application/json'
}
body(
email: $(client(regex(email())), server('not.existing@user.com')),
callback_url: $(client(regex(hostname())), server('http://partners.com'))
)
}
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
code: 4,
message: "User not found by email = [${value(server(regex(email())), client('not.existing@user.com'))}]"
)
}
}
MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def spockTest = blockBuilder.toString()
then:
spockTest.contains('''$[?(@.message =~ /User not found by email = \\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}\\\\]/)]''')
}
}

View File

@@ -11,12 +11,12 @@ import spock.lang.Unroll
import java.util.regex.Pattern
class JsonPathJsonConverterSpec extends Specification {
class JsonToJsonPathsConverterSpec 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))
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues['''$[*].some.nested[?(@.json == 'with value')]'''] == 'with value'
pathAndValues['''$[*].some.nested[?(@.anothervalue == 4)]'''] == 4
@@ -94,7 +94,7 @@ class JsonPathJsonConverterSpec extends Specification {
}
'''
when:
JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues['''$.some.nested[?(@.json == 'with value')]'''] == 'with value'
pathAndValues['''$.some.nested[?(@.anothervalue == 4)]'''] == 4
@@ -112,7 +112,7 @@ class JsonPathJsonConverterSpec extends Specification {
}
'''
when:
JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues['''$.items[?(@ == 'HOP')]'''] == 'HOP'
and:
@@ -131,7 +131,7 @@ class JsonPathJsonConverterSpec extends Specification {
}
'''
when:
JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json))
then:
pathAndValues['''$.errors[*][?(@.property == 'email')]'''] == 'email'
pathAndValues['''$.errors[*][?(@.message == 'inconsistent value')]'''] == 'inconsistent value'
@@ -175,7 +175,7 @@ class JsonPathJsonConverterSpec extends Specification {
]
]
when:
JsonPaths pathAndValues = JsonPathJsonConverter.transformToJsonPathWithTestsSideValues(json)
JsonPaths pathAndValues = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(json)
then:
pathAndValues['''$[*].some.nested[?(@.json == 'with value')]'''] == 'with value'
pathAndValues['''$[*].some.nested[?(@.anothervalue == 4)]'''] == 4

View File

@@ -24,7 +24,8 @@ scmVersion {
}
allprojects {
project.version = scmVersion.version
//project.version = scmVersion.version
project.version = '0.9.1-SNAPSHOT'
}
apply plugin: 'io.codearte.nexus-staging'