[PPL-202] Fixed GString support in body with regex
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)}"""
|
||||
}
|
||||
@@ -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*/
|
||||
|
||||
@@ -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}\\\\]/)]''')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user