Merge pull request #153 from Codearte/issues/72-make-execution-work-with-gstring

[#71, #72, #101] Make execution method work with GString
This commit is contained in:
Marcin Grzejszczak
2015-10-05 21:31:55 +02:00
2 changed files with 91 additions and 7 deletions

View File

@@ -5,6 +5,7 @@ import groovy.json.JsonSlurper
import groovy.transform.TypeChecked
import groovy.util.logging.Slf4j
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.ExecutionProperty
import io.codearte.accurest.dsl.internal.Headers
import io.codearte.accurest.dsl.internal.MatchingStrategy
import org.codehaus.groovy.runtime.GStringImpl
@@ -24,7 +25,9 @@ class ContentUtils {
}
private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile('REGEXP>>(.*)<<')
private static final Pattern TEMPORARY_EXECUTION_PATTERN_HOLDER = Pattern.compile('EXECUTION>>(.*)<<')
private static final String JSON_VALUE_PATTERN_FOR_REGEX = 'REGEXP>>%s<<'
private static final String JSON_VALUE_PATTERN_FOR_EXECUTION = '"EXECUTION>>%s<<"'
/**
* Due to the fact that we allow users to have a body with GString and different values inside
@@ -154,6 +157,10 @@ class ContentUtils {
return String.format(JSON_VALUE_PATTERN_FOR_REGEX, pattern.pattern())
}
private static String transformJSONStringValue(ExecutionProperty property, Closure valueProvider) {
return String.format(JSON_VALUE_PATTERN_FOR_EXECUTION, property.executionCommand)
}
private static String transformXMLStringValue(Object obj, Closure valueProvider) {
return escapeXml11(obj.toString())
}
@@ -166,18 +173,52 @@ class ContentUtils {
MapConverter.transformValues(parsedJson, { Object value ->
if (value instanceof String) {
String string = (String) value
Matcher matcher = TEMPORARY_PATTERN_HOLDER.matcher(string.trim())
if (matcher.matches()) {
List val = matcher[0] as List
String pattern = val[1]
return Pattern.compile(pattern)
}
return value
return returnParsedObject(string)
}
return value
})
}
/**
* <p>
* If you wonder why there is val[1] without null-check then take a look at this:
* </p>
* <p>
* Example:
* </p>
* <p>
* Our string equals: {@code EXECUTION>>assertThatRejectionReasonIsNull($it)<<}
* The matcher matches this group with the pattern {@code EXECUTION>>(.*)<<}
* </p>
* <p>
* So {@code executionMatcher[0]} returns 2 elements:
* <ul>
* <li> index0: EXECUTION>>assertThatRejectionReasonIsNull($it)<< </li>
* <li> index1: assertThatRejectionReasonIsNull($it)<< </li>
* </ul>
* </p>
* <p>
* Thus one can safely write {@code executionMatcher[0][1]} to retrieve the matched group
* </p>
* @param string to match the regexps against
* @return object converted from temporary holders
*/
static Object returnParsedObject(String string) {
Matcher matcher = TEMPORARY_PATTERN_HOLDER.matcher(string.trim())
if (matcher.matches()) {
List val = matcher[0] as List
String pattern = val[1]
return Pattern.compile(pattern)
}
Matcher executionMatcher = TEMPORARY_EXECUTION_PATTERN_HOLDER.matcher(string.trim())
if (executionMatcher.matches()) {
List val = executionMatcher[0] as List
String pattern = val[1]
return new ExecutionProperty(pattern)
}
return string
}
public static ContentType recognizeContentTypeFromHeader(Headers headers) {
String content = headers?.entries.find { it.name == "Content-Type" } ?.clientValue?.toString()
if (content?.endsWith("json")) {

View File

@@ -551,4 +551,47 @@ class MockMvcSpockMethodBuilderSpec extends Specification implements WireMockStu
then:
spockTest.contains('''$[?(@.message =~ /User not found by email = \\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}\\\\]/)]''')
}
@Issue('72')
def "should make the execute method work"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method """PUT"""
url """/fraudcheck"""
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":123.123
}
"""
)
headers {
header("""Content-Type""", """application/vnd.fraud.v1+json""")
}
}
response {
status 200
body( """{
"fraudCheckStatus": "OK",
"rejectionReason": ${value(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))}
}""")
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}
MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def spockTest = blockBuilder.toString()
then:
spockTest.contains('''assertThatRejectionReasonIsNull(parsedJson.read('$.rejectionReason'))''')
}
}