diff --git a/.travis.yml b/.travis.yml
index 7a0dff7140..bdf2cb280b 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
+script: ./gradlew check funcTest --stacktrace --info --continue
diff --git a/README.md b/README.md
index 7cead077d6..923a398c25 100644
--- a/README.md
+++ b/README.md
@@ -2,13 +2,20 @@ Accurate REST
=============
[](https://travis-ci.org/Codearte/accurest) [](https://maven-badges.herokuapp.com/maven-central/io.codearte.accurest/accurest-gradle-plugin)
+[](https://gitter.im/Codearte/accurest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Consumer Driven Contracts verifier for Java
-Just to make long story short - AccuREST is a tool for Consumer Driven Contract (CDC) development. AccuREST ships easy DSL for describing REST contracts for JVM-based applications. The contract DSL is used by AccuREST for two things:
+To make a long story short - AccuREST is a tool for Consumer Driven Contract (CDC) development. AccuREST ships an easy DSL for describing REST contracts for JVM-based applications. The contract DSL is used by AccuREST for two things:
-generating Wiremock's JSON stub definitions, allowing rapid development of the consumer side,
+1. generating WireMock's JSON stub definitions, allowing rapid development of the consumer side,
generating Spock's acceptance tests for the server - to verify if your API implementation is compliant with the contract.
-By using AccuREST you can move TDD to an architecture level.
+2. moving TDD to an architecture level.
-For more information please follow to the [Wiki](https://github.com/Codearte/accurest/wiki/1.-Introduction)
+For more information please go to the [Wiki](https://github.com/Codearte/accurest/wiki/1.-Introduction)
+
+## Requirements
+
+### Wiremock
+
+In order to use Accurest with Wiremock you have to have __Wiremock in version at least 2.0.0-beta__ . Of course the higher the better :)
diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverter.groovy
new file mode 100644
index 0000000000..619bd8b235
--- /dev/null
+++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverter.groovy
@@ -0,0 +1,13 @@
+package io.codearte.accurest.wiremock
+
+import groovy.transform.CompileStatic
+import io.codearte.accurest.dsl.WireMockStubStrategy
+
+@CompileStatic
+class DslToWireMockClientConverter extends DslToWireMockConverter {
+
+ @Override
+ String convertContent(String dslBody) {
+ return new WireMockStubStrategy(createGroovyDSLfromStringContent(dslBody)).toWireMockClientStub()
+ }
+}
diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockConverter.groovy
similarity index 62%
rename from accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockConverter.groovy
rename to accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockConverter.groovy
index 5804010090..89b2b381ce 100644
--- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockConverter.groovy
+++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWireMockConverter.groovy
@@ -2,9 +2,10 @@ package io.codearte.accurest.wiremock
import groovy.transform.CompileStatic
import io.codearte.accurest.dsl.GroovyDsl
+import org.codehaus.groovy.control.CompilerConfiguration
@CompileStatic
-abstract class DslToWiremockConverter implements SingleFileConverter {
+abstract class DslToWireMockConverter implements SingleFileConverter {
@Override
boolean canHandleFileName(String fileName) {
@@ -17,6 +18,6 @@ abstract class DslToWiremockConverter implements SingleFileConverter {
}
protected GroovyDsl createGroovyDSLfromStringContent(String groovyDslAsString) {
- return (GroovyDsl) new GroovyShell(this.class.classLoader).evaluate("$groovyDslAsString")
+ return (GroovyDsl) new GroovyShell(this.class.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding:'UTF-8')).evaluate("$groovyDslAsString")
}
}
diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverter.groovy
deleted file mode 100644
index 8156f17cf6..0000000000
--- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverter.groovy
+++ /dev/null
@@ -1,13 +0,0 @@
-package io.codearte.accurest.wiremock
-
-import groovy.transform.CompileStatic
-import io.codearte.accurest.dsl.WiremockStubStrategy
-
-@CompileStatic
-class DslToWiremockClientConverter extends DslToWiremockConverter {
-
- @Override
- String convertContent(String dslBody) {
- return new WiremockStubStrategy(createGroovyDSLfromStringContent(dslBody)).toWiremockClientStub()
- }
-}
diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/RecursiveFilesConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/RecursiveFilesConverter.groovy
index 5eb8f81d45..8f71f8955b 100644
--- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/RecursiveFilesConverter.groovy
+++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/RecursiveFilesConverter.groovy
@@ -4,6 +4,7 @@ import groovy.io.FileType
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
+import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
@@ -28,12 +29,12 @@ class RecursiveFilesConverter {
if (!singleFileConverter.canHandleFileName(sourceFile.name)) {
return
}
- String convertedContent = singleFileConverter.convertContent(sourceFile.text)
+ String convertedContent = singleFileConverter.convertContent(sourceFile.getText(StandardCharsets.UTF_8.toString()))
Path absoluteTargetPath = createAndReturnTargetDirectory(sourceFile)
File newGroovyFile = createTargetFileWithProperName(absoluteTargetPath, sourceFile)
- newGroovyFile.text = convertedContent
+ newGroovyFile.setText(convertedContent, StandardCharsets.UTF_8.toString())
} catch (Exception e) {
- throw new ConversionAccurestException("Unable to convertion of ${sourceFile.name}", e)
+ throw new ConversionAccurestException("Unable to make convertion of ${sourceFile.name}", e)
}
}
}
diff --git a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WireMockToDslConverter.groovy
similarity index 53%
rename from accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy
rename to accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WireMockToDslConverter.groovy
index bfc58cc17d..4107d2dcdf 100644
--- a/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WiremockToDslConverter.groovy
+++ b/accurest-converters/src/main/groovy/io/codearte/accurest/wiremock/WireMockToDslConverter.groovy
@@ -1,52 +1,68 @@
package io.codearte.accurest.wiremock
+
import groovy.io.FileType
import groovy.json.JsonOutput
+import groovy.json.JsonParserType
import groovy.json.JsonSlurper
import groovy.xml.XmlUtil
import io.codearte.accurest.dsl.GroovyDsl
+import nl.flotsam.xeger.Xeger
+
+import java.nio.charset.StandardCharsets
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava
-class WiremockToDslConverter {
- static String fromWiremockStub(String wiremockStringStub) {
- return new WiremockToDslConverter().convertFromWiremockStub(wiremockStringStub)
+class WireMockToDslConverter {
+ static String fromWireMockStub(String wireMockStringStub) {
+ return new WireMockToDslConverter().convertFromWireMockStub(wireMockStringStub)
}
- private String convertFromWiremockStub(String wiremockStringStub) {
- Object wiremockStub = new JsonSlurper().parseText(wiremockStringStub)
- def request = wiremockStub.request
- def response = wiremockStub.response
+ private String convertFromWireMockStub(String wireMockStringStub) {
+ Object wireMockStub = parseStubDefinition(wireMockStringStub)
+ Integer priority = wireMockStub.priority
+ def request = wireMockStub.request
+ def response = wireMockStub.response
+ def bodyPatterns = request.bodyPatterns
+ String urlPattern = request.urlPattern
return """\
- request {
- ${request.method ? "method \"\"\"$request.method\"\"\"" : ""}
- ${request.url ? "url \"\"\"$request.url\"\"\"" : ""}
- ${request.urlPattern ? "url \$(client(regex('${escapeJava(request.urlPattern)}')), server(''))" : ""}
- ${request.urlPath ? "url \"\"\"$request.urlPath\"\"\"" : ""}
- ${
- request.headers ? """headers {
- ${
- request.headers.collect {
- def assertion = it.value
- String headerName = it.key as String
- def entry = assertion.entrySet().first()
- """header(\"\"\"$headerName\"\"\", ${buildHeader(entry.key, entry.value)})\n"""
- }.join('')
+ ${priority ? "priority ${priority}" : ''}
+ request {
+ ${request.method ? "method \"\"\"$request.method\"\"\"" : ""}
+ ${request.url ? "url \"\"\"$request.url\"\"\"" : ""}
+ ${urlPattern ? "url \$(client(regex('${escapeJava(urlPattern)}')), server('${new Xeger(escapeJava(urlPattern)).generate()}'))" : ""}
+ ${request.urlPath ? "url \"\"\"$request.urlPath\"\"\"" : ""}
+ ${
+ request.headers ? """headers {
+ ${
+ request.headers.collect {
+ def assertion = it.value
+ String headerName = it.key as String
+ def entry = assertion.entrySet().first()
+ """header(\"\"\"$headerName\"\"\", ${buildHeader(entry.key, entry.value)})\n"""
+ }.join('')
+ }
+ }
+ """ : ""
+ }
+ ${bodyPatterns?.equalTo?.every { it } ? "body('''${bodyPatterns.equalTo[0]}''')" : ''}
+ ${bodyPatterns?.equalToJson?.every { it } ? "body('''${bodyPatterns.equalToJson[0]}''')" : ''}
+ ${bodyPatterns?.matches?.every { it } ? "body \$(client(regex('${escapeJava(bodyPatterns.matches[0])}')), server('${new Xeger(escapeJava(bodyPatterns.matches[0])).generate()}'))" : ""}
}
- }
- """ : ""
- }
- }
- response {
- ${response.status ? "status $response.status" : ""}
- ${response.body ? "body( ${buildBody(response.body)})" : ""}
- ${
+ response {
+ ${response.status ? "status $response.status" : ""}
+ ${response.body ? "body( ${buildBody(response.body)})" : ""}
+ ${
response.headers ? """headers {
- ${response.headers.collect { "header('$it.key': '${it.value}')\n" }.join('')}
- }
- """ : ""
+ ${response.headers.collect { "header('$it.key': '${it.value}')\n" }.join('')}
+ }
+ """ : ""
}
- }
- """
+ }
+ """
+ }
+
+ private Object parseStubDefinition(String wireMockStringStub) {
+ new JsonSlurper().setType(JsonParserType.LAX).parseText(wireMockStringStub)
}
private String buildHeader(String method, Object value) {
@@ -140,11 +156,11 @@ class WiremockToDslConverter {
if (!it.name.endsWith('json')) {
return
}
- String dslFromWiremockStub = fromWiremockStub(it.text)
- String dslWrappedWithFactoryMethod = wrapWithFactoryMethod(dslFromWiremockStub)
+ String dslFromWireMockStub = fromWireMockStub(it.getText(StandardCharsets.UTF_8.toString()))
+ String dslWrappedWithFactoryMethod = wrapWithFactoryMethod(dslFromWireMockStub)
File newGroovyFile = new File(it.parent, it.name.replaceAll('json', 'groovy'))
println("Creating new groovy file [$newGroovyFile.path]")
- newGroovyFile.text = dslWrappedWithFactoryMethod
+ newGroovyFile.setText(dslWrappedWithFactoryMethod, StandardCharsets.UTF_8.toString())
} catch (Exception e) {
System.err.println(e)
}
@@ -152,10 +168,10 @@ class WiremockToDslConverter {
}
}
- static String wrapWithFactoryMethod(String dslFromWiremockStub) {
+ static String wrapWithFactoryMethod(String dslFromWireMockStub) {
return """\
${GroovyDsl.name}.make {
- $dslFromWiremockStub
+ $dslFromWireMockStub
}
"""
}
diff --git a/accurest-converters/src/main/groovy/nl/flotsam/xeger/Xeger.java b/accurest-converters/src/main/groovy/nl/flotsam/xeger/Xeger.java
new file mode 100644
index 0000000000..9bd42a674a
--- /dev/null
+++ b/accurest-converters/src/main/groovy/nl/flotsam/xeger/Xeger.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2009 Wilfred Springer
+ * Copyright 2012 Jason Pell
+ * Copyright 2013 Antonio García-Domínguez
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * The class is bundled together with our code because it has not been
+ * released to any central repository.
+ *
+ */
+package nl.flotsam.xeger;
+
+import dk.brics.automaton.Automaton;
+import dk.brics.automaton.RegExp;
+import dk.brics.automaton.State;
+import dk.brics.automaton.Transition;
+
+import java.util.List;
+import java.util.Random;
+
+/**
+ * An object that will generate text from a regular expression. In a way, it's the opposite of a regular expression
+ * matcher: an instance of this class will produce text that is guaranteed to match the regular expression passed in.
+ */
+public class Xeger {
+
+ private final Automaton automaton;
+ private Random random;
+
+ /**
+ * Constructs a new instance, accepting the regular expression and the randomizer.
+ *
+ * @param regex The regular expression. (Not null.)
+ * @param random The object that will randomize the way the String is generated. (Not null.)
+ * @throws IllegalArgumentException If the regular expression is invalid.
+ */
+ public Xeger(String regex, Random random) {
+ assert regex != null;
+ assert random != null;
+ this.automaton = new RegExp(regex).toAutomaton();
+ this.random = random;
+ }
+
+ /**
+ * As {@link nl.flotsam.xeger.Xeger#Xeger(String, java.util.Random)}, creating a {@link java.util.Random} instance
+ * implicityly.
+ *
+ * @param regex as string
+ */
+ public Xeger(String regex) {
+ this(regex, new Random());
+ }
+
+ /**
+ * Generates a random String that is guaranteed to match the regular expression passed to the constructor.
+ * @return generated regexp
+ */
+ public String generate() {
+ StringBuilder builder = new StringBuilder();
+ generate(builder, automaton.getInitialState());
+ return builder.toString();
+ }
+
+ private void generate(StringBuilder builder, State state) {
+ List transitions = state.getSortedTransitions(false);
+ if (transitions.size() == 0) {
+ assert state.isAccept();
+ return;
+ }
+ int nroptions = state.isAccept() ? transitions.size() : transitions.size() - 1;
+ int option = Xeger.getRandomInt(0, nroptions, random);
+ if (state.isAccept() && option == 0) { // 0 is considered stop
+ return;
+ }
+ // Moving on to next transition
+ Transition transition = transitions.get(option - (state.isAccept() ? 1 : 0));
+ appendChoice(builder, transition);
+ generate(builder, transition.getDest());
+ }
+
+ private void appendChoice(StringBuilder builder, Transition transition) {
+ char c = (char) Xeger.getRandomInt(transition.getMin(), transition.getMax(), random);
+ builder.append(c);
+ }
+
+ public Random getRandom() {
+ return random;
+ }
+
+ public void setRandom(Random random) {
+ this.random = random;
+ }
+
+ /**
+ * Generates a random number within the given bounds.
+ *
+ * @param min The minimum number (inclusive).
+ * @param max The maximum number (inclusive).
+ * @param random The object used as the randomizer.
+ * @return A random number in the given range.
+ */
+ static int getRandomInt(int min, int max, Random random) {
+ // Use random.nextInt as it guarantees a uniform distribution
+ int maxForRandom=max-min+1;
+ return random.nextInt(maxForRandom) + min;
+ }
+}
\ 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
new file mode 100755
index 0000000000..61c6b7c29b
--- /dev/null
+++ b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWireMockClientConverterSpec.groovy
@@ -0,0 +1,142 @@
+package io.codearte.accurest.wiremock
+
+import org.skyscreamer.jsonassert.JSONAssert
+import spock.lang.Specification
+
+class DslToWireMockClientConverterSpec extends Specification {
+
+ def "should convert DSL file to WireMock JSON"() {
+ given:
+ def converter = new DslToWireMockClientConverter()
+ and:
+ String dslBody = """
+ io.codearte.accurest.dsl.GroovyDsl.make {
+ request {
+ method('PUT')
+ url \$(client(~/\\/[0-9]{2}/), server('/12'))
+ }
+ response {
+ status 200
+ }
+ }
+"""
+ when:
+ String json = converter.convertContent(dslBody)
+ then:
+ JSONAssert.assertEquals('''
+{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}}
+''', json, false)
+ }
+
+
+ def "should convert DSL file with a nested list to WireMock JSON"() {
+ given:
+ def converter = new DslToWireMockClientConverter()
+ and:
+ String dslBody = """
+ io.codearte.accurest.dsl.GroovyDsl.make {
+ request {
+ method 'PUT'
+ url '/api/12'
+ headers {
+ header 'Content-Type': 'application/vnd.com.ofg.twitter-places-analyzer.v1+json'
+
+ }
+ body '''
+ [{
+ "created_at": "Sat Jul 26 09:38:57 +0000 2014",
+ "id": 492967299297845248,
+ "id_str": "492967299297845248",
+ "text": "Gonna see you at Warsaw",
+ "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"
+ }
+ }]
+ '''
+ }
+ response {
+ status 200
+ }
+ }
+"""
+ when:
+ String json = converter.convertContent(dslBody)
+ then:
+ 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-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverterSpec.groovy b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverterSpec.groovy
deleted file mode 100755
index 2f20546014..0000000000
--- a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/DslToWiremockClientConverterSpec.groovy
+++ /dev/null
@@ -1,101 +0,0 @@
-package io.codearte.accurest.wiremock
-
-import groovy.json.JsonSlurper
-import spock.lang.Specification
-
-class DslToWiremockClientConverterSpec extends Specification {
-
- def "should convert DSL file to Wiremock JSON"() {
- given:
- def converter = new DslToWiremockClientConverter()
- and:
- String dslBody = """
- io.codearte.accurest.dsl.GroovyDsl.make {
- request {
- method('PUT')
- url \$(client(~/\\/[0-9]{2}/), server('/12'))
- }
- response {
- status 200
- }
- }
-"""
- when:
- String json = converter.convertContent(dslBody)
- then:
- new JsonSlurper().parseText(json) == new JsonSlurper().parseText("""
-{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}}""")
- }
-
-
- def "should convert DSL file with a nested list to Wiremock JSON"() {
- given:
- def converter = new DslToWiremockClientConverter()
- and:
- String dslBody = """
- io.codearte.accurest.dsl.GroovyDsl.make {
- request {
- method 'PUT'
- url '/api/12'
- headers {
- header 'Content-Type': 'application/vnd.com.ofg.twitter-places-analyzer.v1+json'
-
- }
- body '''
- [{
- "created_at": "Sat Jul 26 09:38:57 +0000 2014",
- "id": 492967299297845248,
- "id_str": "492967299297845248",
- "text": "Gonna see you at Warsaw",
- "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"
- }
- }]
- '''
- }
- response {
- status 200
- }
- }
-"""
- when:
- String json = converter.convertContent(dslBody)
- then:
- new JsonSlurper().parseText(json) == new JsonSlurper().parseText("""{
- "request":{
- "method":"PUT",
- "url":"/api/12",
- "bodyPatterns": [
- { "equalTo": "[{\\"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}
- }
-""")
- }
-}
diff --git a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WireMockToDslConverterSpec.groovy b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WireMockToDslConverterSpec.groovy
new file mode 100755
index 0000000000..80e8592276
--- /dev/null
+++ b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WireMockToDslConverterSpec.groovy
@@ -0,0 +1,542 @@
+package io.codearte.accurest.wiremock
+
+import com.github.tomakehurst.wiremock.stubbing.StubMapping
+import io.codearte.accurest.dsl.GroovyDsl
+import spock.lang.Specification
+
+class WireMockToDslConverterSpec extends Specification {
+
+ def 'should produce a Groovy DSL from WireMock stub'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "GET",
+ "url": "/path",
+ "headers" : {
+ "Accept": {
+ "matches": "text/.*"
+ },
+ "X-Custom-Header": {
+ "contains": "2134"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "body": '{"id": { "value": "132" }, "surname": "Kowalsky", "name": "Jan", "created": "2014-02-02 12:23:43" }',
+ "headers": {
+ "Content-Type": "text/plain"
+ }
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url '/path'
+ headers {
+ header('Accept': $(
+ client(regex('text/.*')),
+ server('text/plain')
+ ))
+ header('X-Custom-Header': $(
+ client(regex('^.*2134.*$')),
+ server('121345')
+ ))
+
+ }
+ }
+ response {
+ status 200
+ body(
+ id: [value: '132'],
+ surname: 'Kowalsky',
+ name: 'Jan',
+ created: '2014-02-02 12:23:43'
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+
+ }
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""") == expectedGroovyDsl
+ }
+
+
+ def 'should convert WireMock stub with response body containing JSON with escaped double quotes'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "DELETE",
+ "urlPattern": "/credit-card-verification-data/[0-9]+",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.mymoid-adapter.v2+json; charset=UTF-8"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "body": "{\\"status\\": \\"OK\\"}",
+ "headers": {
+ "Content-Type": "application/json"
+ }
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'DELETE'
+ url $(client(~/\/credit-card-verification-data\/[0-9]+/), server('/credit-card-verification-data/1'))
+ headers {
+ header('Content-Type': 'application/vnd.mymoid-adapter.v2+json; charset=UTF-8')
+ }
+ }
+ response {
+ status 200
+ body("""{
+ "status": "OK"
+}""")
+ headers {
+ header 'Content-Type': 'application/json'
+
+ }
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""") == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with response body containing integer'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "POST",
+ "url": "/charge/count",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.creditcard-reporter.v1+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "body": 200,
+ "headers": {
+ "Content-Type": "application/json"
+ }
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/charge/count'
+ headers {
+ header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
+ }
+ }
+ response {
+ status 200
+ body(200)
+ headers {
+ header 'Content-Type': 'application/json'
+
+ }
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""") == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with response body as a list'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "POST",
+ "url": "/charge/count",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.creditcard-reporter.v1+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "body": '[ {"a":1, "c":"3"}, "b", "a" ]',
+ "headers": {
+ "Content-Type": "application/json"
+ }
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/charge/count'
+ headers {
+ header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
+ }
+ }
+ response {
+ status 200
+ body([
+ [a: 1, c: '3'],
+ 'b',
+ 'a'
+ ])
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""") == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with response body containing a nested list'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "POST",
+ "url": "/charge/search?pageNumber=0&size=2147483647",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.creditcard-reporter.v1+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "body": '[{"amount":1.01, "name":"Name", "info":{"title":"title1", "payload":null}, "booleanvalue":true, "user":null}, {"amount":2.01, "name":"Name2", "info":{"title":"title2", "payload":null}, "booleanvalue":true, "user":null}]'
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/charge/search?pageNumber=0&size=2147483647'
+ headers {
+ header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
+ }
+ }
+ response {
+ status 200
+ body("""[
+ {
+ "amount": 1.01,
+ "name": "Name",
+ "info": {
+ "title": "title1",
+ "payload": null
+ },
+ "booleanvalue": true,
+ "user": null
+ },
+ {
+ "amount": 2.01,
+ "name": "Name2",
+ "info": {
+ "title": "title2",
+ "payload": null
+ },
+ "booleanvalue": true,
+ "user": null
+ }
+]""")
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""") == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with request body checking equality to Json'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "POST",
+ "url": "/test",
+ "bodyPatterns": [{
+ "equalTo": '{"property1":"abc", "property2":"2017-01", "property3":"666", "property4":1428566412}'
+ }]
+ },
+ "response": {
+ "status": 200
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/test'
+ body ('''{"property1":"abc","property2":"2017-01","property3":"666","property4":1428566412}''')
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with request body checking matching to Json'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request": {
+ "method": "POST",
+ "url": "/test",
+ "bodyPatterns": [{
+ "matches": "[0-9]{5}"
+ }]
+ },
+ "response": {
+ "status": 200
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/test'
+ body $(client(~/[0-9]{5}/), server('12345'))
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with request body with equalToJson'() {
+ given:
+ String wireMockStub = '''\
+{
+ "request" : {
+ "url" : "/test",
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "equalToJson" : '{"pan":"4855141150107894", "expirationDate":"2017-01", "dcvx":"178"}',
+ "jsonCompareMode" : "LENIENT"
+ } ]
+ },
+ "response" : {
+ "status" : 200
+ }
+}
+'''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/test'
+ body '''{"pan":"4855141150107894","expirationDate":"2017-01","dcvx":"178"}'''
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with request body with equalTo'() {
+ given:
+ String wireMockStub = '''\
+ {
+ "request" : {
+ "url" : "/test",
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "equalTo" : '{"pan":"4855141150107894", "expirationDate":"2017-01", "dcvx":"178"}'
+ } ]
+ },
+ "response" : {
+ "status" : 200
+ }
+ }
+ '''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/test'
+ body '''{"pan":"4855141150107894","expirationDate":"2017-01","dcvx":"178"}'''
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with request body with matches'() {
+ given:
+ String wireMockStub = '''\
+ {
+ "request" : {
+ "url" : "/test",
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "matches" : "[0-9]{2}"
+ } ]
+ },
+ "response" : {
+ "status" : 200
+ }
+ }
+ '''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/test'
+ body $(client(~/[0-9]{2}/), server('12'))
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ def 'should convert WireMock stub with priorities'() {
+ given:
+ String wireMockStub = '''\
+ {
+ "priority" : 2,
+ "request" : {
+ "url" : "/test",
+ "method" : "POST"
+ },
+ "response" : {
+ "status" : 200
+ }
+ }
+ '''
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ and:
+ GroovyDsl expectedGroovyDsl = GroovyDsl.make {
+ priority 2
+ request {
+ method 'POST'
+ url '/test'
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String groovyDsl = WireMockToDslConverter.fromWireMockStub(wireMockStub)
+ then:
+ GroovyDsl evaluatedGroovyDsl = new GroovyShell(this.class.classLoader).evaluate(
+ """ io.codearte.accurest.dsl.GroovyDsl.make {
+ $groovyDsl
+ }""")
+ and:
+ evaluatedGroovyDsl == expectedGroovyDsl
+ }
+
+ void stubMappingIsValidWireMockStub(String mappingDefinition) {
+ StubMapping.buildFrom(mappingDefinition)
+ }
+}
diff --git a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy b/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy
deleted file mode 100755
index 7466b2e7f5..0000000000
--- a/accurest-converters/src/test/groovy/io/codearte/accurest/wiremock/WiremockToDslConverterSpec.groovy
+++ /dev/null
@@ -1,290 +0,0 @@
-package io.codearte.accurest.wiremock
-
-import io.codearte.accurest.dsl.GroovyDsl
-import spock.lang.Specification
-
-class WiremockToDslConverterSpec extends Specification {
-
- def 'should produce a Groovy DSL from Wiremock stub'() {
- given:
- String wiremockStub = '''\
-{
- "request": {
- "method": "GET",
- "url": "/path",
- "headers" : {
- "Accept": {
- "matches": "text/.*"
- },
- "X-Custom-Header": {
- "contains": "2134"
- }
- }
- },
- "response": {
- "status": 200,
- "body": "{ \\"id\\": { \\"value\\": \\"132\\" }, \\"surname\\": \\"Kowalsky\\", \\"name\\": \\"Jan\\", \\"created\\": \\"2014-02-02 12:23:43\\" }",
- "headers": {
- "Content-Type": "text/plain",
- }
- }
-}
-'''
- and:
- GroovyDsl expectedGroovyDsl = GroovyDsl.make {
- request {
- method 'GET'
- url '/path'
- headers {
- header('Accept': $(
- client(regex('text/.*')),
- server('text/plain')
- ))
- header('X-Custom-Header': $(
- client(regex('^.*2134.*$')),
- server('121345')
- ))
-
- }
- }
- response {
- status 200
- body(
- id: [value: '132'],
- surname: 'Kowalsky',
- name: 'Jan',
- created: '2014-02-02 12:23:43'
- )
- headers {
- header 'Content-Type': 'text/plain'
-
- }
- }
- }
- when:
- String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
- then:
- new GroovyShell(this.class.classLoader).evaluate(
- """ io.codearte.accurest.dsl.GroovyDsl.make {
- $groovyDsl
- }""") == expectedGroovyDsl
- }
-
-
- def 'should convert Wiremock stub with body containing simple JSON'() {
- given:
- String wiremockStub = '''\
-{
- "request": {
- "method": "DELETE",
- "urlPattern": "/credit-card-verification-data/[0-9]+",
- "headers": {
- "Content-Type": {
- "equalTo": "application/vnd.mymoid-adapter.v2+json; charset=UTF-8"
- }
- }
- },
- "response": {
- "status": 200,
- "body": "{\\"status\\": \\"OK\\"}",
- "headers": {
- "Content-Type": "application/json"
- }
- }
-}
-'''
- and:
- GroovyDsl expectedGroovyDsl = GroovyDsl.make {
- request {
- method 'DELETE'
- url $(client(~/\/credit-card-verification-data\/[0-9]+/), server(''))
- headers {
- header('Content-Type': 'application/vnd.mymoid-adapter.v2+json; charset=UTF-8')
- }
- }
- response {
- status 200
- body("""{
- "status": "OK"
-}""")
- headers {
- header 'Content-Type': 'application/json'
-
- }
- }
- }
- when:
- String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
- then:
- new GroovyShell(this.class.classLoader).evaluate(
- """ io.codearte.accurest.dsl.GroovyDsl.make {
- $groovyDsl
- }""") == expectedGroovyDsl
- }
-
- def 'should convert Wiremock stub with body containing integer'() {
- given:
- String wiremockStub = '''\
-{
- "request": {
- "method": "POST",
- "url": "/charge/count",
- "headers": {
- "Content-Type": {
- "equalTo": "application/vnd.creditcard-reporter.v1+json"
- }
- }
- },
- "response": {
- "status": 200,
- "body": 200,
- "headers": {
- "Content-Type": "application/json"
- }
- }
-}
-'''
- and:
- GroovyDsl expectedGroovyDsl = GroovyDsl.make {
- request {
- method 'POST'
- url '/charge/count'
- headers {
- header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
- }
- }
- response {
- status 200
- body(200)
- headers {
- header 'Content-Type': 'application/json'
-
- }
- }
- }
- when:
- String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
- then:
- new GroovyShell(this.class.classLoader).evaluate(
- """ io.codearte.accurest.dsl.GroovyDsl.make {
- $groovyDsl
- }""") == expectedGroovyDsl
- }
-
- def 'should convert Wiremock stub with body as a list'() {
- given:
- String wiremockStub = '''\
-{
- "request": {
- "method": "POST",
- "url": "/charge/count",
- "headers": {
- "Content-Type": {
- "equalTo": "application/vnd.creditcard-reporter.v1+json"
- }
- }
- },
- "response": {
- "status": 200,
- "body": "[ {\\"a\\":1, \\"c\\":\\"3\\"}, \\"b\\", \\"a\\" ]",
- "headers": {
- "Content-Type": "application/json"
- }
- }
-}
-'''
- and:
- GroovyDsl expectedGroovyDsl = GroovyDsl.make {
- request {
- method 'POST'
- url '/charge/count'
- headers {
- header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
- }
- }
- response {
- status 200
- body([
- [a: 1, c: '3'],
- 'b',
- 'a'
- ])
- headers {
- header 'Content-Type': 'application/json'
- }
- }
- }
- when:
- String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
- then:
- new GroovyShell(this.class.classLoader).evaluate(
- """ io.codearte.accurest.dsl.GroovyDsl.make {
- $groovyDsl
- }""") == expectedGroovyDsl
- }
-
-
- def 'should convert Wiremock stub with body containing a nested list'() {
- given:
- String wiremockStub = '''\
-{
- "request": {
- "method": "POST",
- "url": "/charge/search?pageNumber=0&size=2147483647",
- "headers": {
- "Content-Type": {
- "equalTo": "application/vnd.creditcard-reporter.v1+json"
- }
- }
- },
- "response": {
- "status": 200,
- "body":"[{\\"amount\\":1.01,\\"name\\":\\"Name\\",\\"info\\":{\\"title\\":\\"title1\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null},{\\"amount\\":2.01,\\"name\\":\\"Name2\\",\\"info\\":{\\"title\\":\\"title2\\",\\"payload\\":null},\\"booleanvalue\\":true,\\"user\\":null}]"
- }
-}
-'''
- and:
- GroovyDsl expectedGroovyDsl = GroovyDsl.make {
- request {
- method 'POST'
- url '/charge/search?pageNumber=0&size=2147483647'
- headers {
- header('Content-Type': 'application/vnd.creditcard-reporter.v1+json')
- }
- }
- response {
- status 200
- body("""[
- {
- "amount": 1.01,
- "name": "Name",
- "info": {
- "title": "title1",
- "payload": null
- },
- "booleanvalue": true,
- "user": null
- },
- {
- "amount": 2.01,
- "name": "Name2",
- "info": {
- "title": "title2",
- "payload": null
- },
- "booleanvalue": true,
- "user": null
- }
-]""")
- }
- }
- when:
- String groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
- then:
- new GroovyShell(this.class.classLoader).evaluate(
- """ io.codearte.accurest.dsl.GroovyDsl.make {
- $groovyDsl
- }""") == expectedGroovyDsl
- }
-
-}
diff --git a/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerTest.java b/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerTest.java
new file mode 100644
index 0000000000..f60e4bf5db
--- /dev/null
+++ b/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerTest.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2009 Wilfred Springer
+ * Copyright 2012 Jason Pell
+ * Copyright 2013 Antonio García-Domínguez
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package nl.flotsam.xeger;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class XegerTest {
+
+ @Test
+ public void shouldGenerateTextCorrectly() {
+ String regex = "[ab]{4,6}c";
+ Xeger generator = new Xeger(regex);
+ for (int i = 0; i < 100; i++) {
+ String text = generator.generate();
+ assertTrue(text.matches(regex));
+ }
+ }
+
+ @Test
+ public void testRepeatableRegex() {
+ for (int x = 0; x < 1000; x++) {
+ Xeger generator = new Xeger("[ab]{4,6}c", new Random(1000));
+ Xeger generator2 = new Xeger("[ab]{4,6}c", new Random(1000));
+
+ List firstRegexList = generateRegex(generator, 100);
+ List secondRegexList = generateRegex(generator2, 100);
+
+ for (int i = 0; i < firstRegexList.size(); i++) {
+ assertEquals("Index mismatch: " + i, firstRegexList.get(i),
+ secondRegexList.get(i));
+ }
+ }
+ }
+
+ private List generateRegex(Xeger generator, int count) {
+ List regexList = new ArrayList();
+ for (int i = 0; i < count; i++) {
+ regexList.add(generator.generate());
+ }
+ return regexList;
+ }
+}
\ No newline at end of file
diff --git a/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerUtilsTest.java b/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerUtilsTest.java
new file mode 100644
index 0000000000..ccabfeb54d
--- /dev/null
+++ b/accurest-converters/src/test/groovy/nl/flotsam/xeger/XegerUtilsTest.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2009 Wilfred Springer
+ * Copyright 2012 Jason Pell
+ * Copyright 2013 Antonio García-Domínguez
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package nl.flotsam.xeger;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import java.util.Random;
+
+import static org.junit.Assert.assertThat;
+
+public class XegerUtilsTest {
+
+ @Test
+ public void shouldGenerateRandomNumberCorrectly() {
+ Random random = new Random();
+ for (int i = 0; i < 100; i++) {
+ int number = Xeger.getRandomInt(3, 7, random);
+ assertThat(number, Matchers.greaterThanOrEqualTo(3));
+ assertThat(number, Matchers.lessThanOrEqualTo(7));
+ }
+ }
+
+}
\ No newline at end of file
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 bc6f35adde..fb2d135419 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/SingleTestGenerator.groovy
@@ -11,6 +11,7 @@ import static io.codearte.accurest.builder.MethodBuilder.createTestMethod
import static io.codearte.accurest.util.NamesUtil.capitalize
class SingleTestGenerator {
+
private final AccurestConfigProperties configProperties
SingleTestGenerator(AccurestConfigProperties configProperties) {
@@ -34,7 +35,9 @@ class SingleTestGenerator {
}
}
- if (configProperties.testMode == TestMode.MOCKMVC) {
+ if (configProperties.testMode == TestMode.JAXRSCLIENT) {
+ clazz.addStaticImport('javax.ws.rs.client.Entity.*')
+ } else if (configProperties.testMode == TestMode.MOCKMVC) {
clazz.addStaticImport('com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*')
} else {
clazz.addStaticImport('com.jayway.restassured.RestAssured.*')
@@ -47,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.targetFramework))
+ 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/TestGenerator.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/TestGenerator.groovy
index a502448bc4..719b5cadca 100755
--- a/accurest-core/src/main/groovy/io/codearte/accurest/TestGenerator.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/TestGenerator.groovy
@@ -4,6 +4,7 @@ import io.codearte.accurest.config.AccurestConfigProperties
import org.apache.commons.io.FilenameUtils
import org.codehaus.plexus.util.DirectoryScanner
+import java.nio.charset.StandardCharsets
import java.util.concurrent.atomic.AtomicInteger
import static io.codearte.accurest.util.NamesUtil.afterLast
@@ -66,19 +67,19 @@ class TestGenerator {
if (filesToClass.size()) {
def className = afterLast(includedDirectoryRelativePath, File.separator) + configProperties.targetFramework.classNameSuffix
def packageName = buildPackage(packageNameForClass, includedDirectoryRelativePath)
- def classBytes = generator.buildClass(filesToClass, className, packageName).bytes
+ def classBytes = generator.buildClass(filesToClass, className, packageName).getBytes(StandardCharsets.UTF_8)
saver.saveClassFile(className, packageName, classBytes)
counter.incrementAndGet()
}
}
}
- private static String buildPackage(final String packageNameForClass, final String includedDirectoryRelativePath) {
- String directory = beforeLast(includedDirectoryRelativePath, File.separator)
- return "$packageNameForClass.${directoryToPackage(directory)}"
- }
+ private static String buildPackage(final String packageNameForClass, final String includedDirectoryRelativePath) {
+ String directory = beforeLast(includedDirectoryRelativePath, File.separator)
+ return "$packageNameForClass.${directoryToPackage(directory)}"
+ }
- private static String normalizePath(String path) {
- return FilenameUtils.separatorsToUnix(path)
- }
+ private static String normalizePath(String path) {
+ return FilenameUtils.separatorsToUnix(path)
+ }
}
\ No newline at end of file
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/JaxRsClientSpockMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBodyBuilder.groovy
new file mode 100644
index 0000000000..91ba58e4f0
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBodyBuilder.groovy
@@ -0,0 +1,95 @@
+package io.codearte.accurest.builder
+
+import groovy.transform.PackageScope
+import groovy.transform.TypeChecked
+import io.codearte.accurest.dsl.GroovyDsl
+import io.codearte.accurest.dsl.internal.Header
+import io.codearte.accurest.dsl.internal.QueryParameter
+
+@PackageScope
+@TypeChecked
+class JaxRsClientSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
+
+ JaxRsClientSpockMethodBodyBuilder(GroovyDsl stubDefinition) {
+ super(stubDefinition)
+ }
+
+ @Override
+ protected void givenBlock(BlockBuilder bb) {
+ }
+
+ @Override
+ protected void when(BlockBuilder bb) {
+ bb.addLine("def response = webTarget")
+ bb.indent()
+
+ appendUrlPathAndQueryParameters(bb)
+ appendRequestWithRequiredResponseContentType(bb)
+ appendHeaders(bb)
+ appendMethodAndBody(bb)
+
+ bb.unindent()
+
+ bb.addEmptyLine()
+ bb.addLine("String responseAsString = response.readEntity(String)")
+ }
+
+ protected void appendRequestWithRequiredResponseContentType(BlockBuilder bb) {
+ String acceptHeader = getHeader("Accept")
+ if (acceptHeader) {
+ bb.addLine(".request('$acceptHeader')")
+ } else {
+ bb.addLine(".request()")
+ }
+ }
+
+ protected void appendUrlPathAndQueryParameters(BlockBuilder bb) {
+ if (request.url) {
+ bb.addLine(".path('$request.url.serverValue')")
+ } else if (request.urlPath) {
+ bb.addLine(".path('$request.urlPath.serverValue')")
+ request.urlPath.queryParameters?.parameters.findAll(this.&allowedQueryParameter).each { QueryParameter param ->
+ bb.addLine(".queryParam('$param.name', '${resolveParamValue(param).toString()}')")
+ }
+ }
+ }
+
+ protected void appendMethodAndBody(BlockBuilder bb) {
+ String method = request.method.serverValue.toString().toLowerCase()
+ if (request.body) {
+ String contentType = getHeader('Content-Type') ?: getRequestContentType().mimeType
+ bb.addLine(".method('$method', entity('$bodyAsString', '$contentType'))")
+ } else {
+ bb.addLine(".method('$method')")
+ }
+ }
+
+ protected appendHeaders(BlockBuilder bb) {
+ request.headers?.collect { Header header ->
+ if (header.name == 'Content-Type' || header.name == 'Accept') return // Particular headers are set via 'request' / 'entity' methods
+ bb.addLine(".header('${header.name}', '${header.serverValue}')")
+ }
+ }
+
+ protected String getHeader(String name) {
+ return request.headers?.entries.find { it.name == name }?.serverValue
+ }
+
+ @Override
+ protected void validateResponseCodeBlock(BlockBuilder bb) {
+ bb.addLine("response.status == $response.status.serverValue")
+ }
+
+ @Override
+ protected void validateResponseHeadersBlock(BlockBuilder bb) {
+ response.headers?.collect { Header header ->
+ bb.addLine("response.getHeaderString('$header.name') == '$header.serverValue'")
+ }
+ }
+
+ @Override
+ protected String getResponseAsString() {
+ return 'responseAsString'
+ }
+
+}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBuilder.groovy
index dd791fb666..55a0f66f36 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBuilder.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBuilder.groovy
@@ -1,9 +1,12 @@
package io.codearte.accurest.builder
import groovy.util.logging.Slf4j
+import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
+import io.codearte.accurest.config.TestMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.util.NamesUtil
+import org.codehaus.groovy.control.CompilerConfiguration
/**
* @author Jakub Kubrynski
@@ -13,28 +16,36 @@ class MethodBuilder {
private final String methodName
private final GroovyDsl stubContent
- private final TestFramework lang
+ private final AccurestConfigProperties configProperties
- private MethodBuilder(String methodName, GroovyDsl stubContent, TestFramework lang) {
+ private MethodBuilder(String methodName, GroovyDsl stubContent, AccurestConfigProperties configProperties) {
this.stubContent = stubContent
this.methodName = methodName
- this.lang = lang
+ this.configProperties = configProperties
}
- static MethodBuilder createTestMethod(File stubsFile, TestFramework lang) {
+ static MethodBuilder createTestMethod(File stubsFile, AccurestConfigProperties configProperties) {
log.debug("Stub content from file [${stubsFile.text}]")
- GroovyDsl stubContent = new GroovyShell(this.classLoader).evaluate(stubsFile)
+ GroovyDsl stubContent = new GroovyShell(this.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding:'UTF-8')).evaluate(stubsFile)
log.debug("Stub content Groovy DSL [$stubContent]")
String methodName = NamesUtil.camelCase(NamesUtil.toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator)))
- return new MethodBuilder(methodName, stubContent, lang)
+ return new MethodBuilder(methodName, stubContent, configProperties)
}
void appendTo(BlockBuilder blockBuilder) {
- if (lang == TestFramework.JUNIT) {
+ if (configProperties.targetFramework == TestFramework.JUNIT) {
blockBuilder.addLine('@Test')
}
- blockBuilder.addLine(lang.methodModifier + "$methodName() {")
- new SpockMethodBodyBuilder(stubContent).appendTo(blockBuilder)
+ blockBuilder.addLine(configProperties.targetFramework.methodModifier + "$methodName() {")
+ getMethodBodyBuilder().appendTo(blockBuilder)
blockBuilder.addLine('}')
}
+
+ private SpockMethodBodyBuilder getMethodBodyBuilder() {
+ if (configProperties.testMode == TestMode.JAXRSCLIENT) {
+ return new JaxRsClientSpockMethodBodyBuilder(stubContent)
+ }
+ return new MockMvcSpockMethodBodyBuilder(stubContent)
+ }
+
}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBodyBuilder.groovy
new file mode 100644
index 0000000000..af84103be2
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBodyBuilder.groovy
@@ -0,0 +1,90 @@
+package io.codearte.accurest.builder
+
+import groovy.transform.PackageScope
+import groovy.transform.TypeChecked
+import groovy.transform.TypeCheckingMode
+import io.codearte.accurest.dsl.GroovyDsl
+import io.codearte.accurest.dsl.internal.Header
+import io.codearte.accurest.dsl.internal.QueryParameter
+import io.codearte.accurest.dsl.internal.Request
+import io.codearte.accurest.dsl.internal.UrlPath
+
+import java.util.regex.Pattern
+
+@PackageScope
+@TypeChecked
+class MockMvcSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
+
+ MockMvcSpockMethodBodyBuilder(GroovyDsl stubDefinition) {
+ super(stubDefinition)
+ }
+
+ protected void given(BlockBuilder bb) {
+ bb.addLine('def request = given()')
+ bb.indent()
+ request.headers?.collect { Header header ->
+ bb.addLine(".header('${getTestSideValue(header.name)}', '${getTestSideValue(header.serverValue)}')")
+ }
+ if (request.body) {
+ bb.addLine(".body('$bodyAsString')")
+ }
+ bb.unindent()
+ }
+
+ protected void when(BlockBuilder bb) {
+ bb.addLine('def response = given().spec(request)')
+ bb.indent()
+
+ String url = buildUrl(request)
+ String method = request.method.serverValue.toString().toLowerCase()
+
+ bb.addLine(/.${method}("$url")/)
+ bb.unindent()
+ }
+
+ protected void validateResponseCodeBlock(BlockBuilder bb) {
+ bb.addLine("response.statusCode == $response.status.serverValue")
+ }
+
+ protected void validateResponseHeadersBlock(BlockBuilder bb) {
+ response.headers?.collect { Header header ->
+ bb.addLine("response.header('$header.name') ${convertHeaderComparison(header.serverValue)}")
+ }
+ }
+
+ private String convertHeaderComparison(Object headerValue) {
+ return " == '$headerValue'"
+ }
+
+ private String convertHeaderComparison(Pattern headerValue) {
+ return "==~ java.util.regex.Pattern.compile('$headerValue')"
+ }
+
+ @Override
+ protected String getResponseAsString() {
+ return 'response.body.asString()'
+ }
+
+ protected String buildUrl(Request request) {
+ if (request.url)
+ return getTestSideValue(request.url.serverValue)
+ if (request.urlPath)
+ return getTestSideValue(buildUrlFromUrlPath(request.urlPath))
+ throw new IllegalStateException("URL is not set!")
+ }
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ protected String buildUrlFromUrlPath(UrlPath urlPath) {
+ String params = ""
+ if (urlPath.queryParameters) {
+ params = urlPath.queryParameters.parameters
+ .findAll(this.&allowedQueryParameter)
+ .inject([] as List) { List result, QueryParameter param ->
+ result << "${param.name}=${resolveParamValue(param).toString()}"
+ }
+ .join('&')
+ }
+ return "$urlPath.serverValue?$params"
+ }
+
+}
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 532e429952..618398ad5b 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
@@ -1,104 +1,216 @@
package io.codearte.accurest.builder
import groovy.json.JsonOutput
+import groovy.json.StringEscapeUtils
import groovy.transform.PackageScope
+import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.GroovyDsl
-import io.codearte.accurest.dsl.internal.ExecutionProperty
-import io.codearte.accurest.dsl.internal.Header
-
-import java.util.regex.Pattern
+import io.codearte.accurest.dsl.internal.*
+import io.codearte.accurest.util.ContentType
+import io.codearte.accurest.util.MapConverter
+import io.codearte.accurest.util.JsonToJsonPathsConverter
+import io.codearte.accurest.util.JsonPaths
+import static io.codearte.accurest.util.ContentUtils.*
/**
* @author Jakub Kubrynski
*/
@PackageScope
-class SpockMethodBodyBuilder {
- private final GroovyDsl stubDefinition
+@TypeChecked
+abstract class SpockMethodBodyBuilder {
+
+ private static final Boolean TEST_SIDE = false
+
+ protected final Request request
+ protected final Response response
SpockMethodBodyBuilder(GroovyDsl stubDefinition) {
- this.stubDefinition = stubDefinition
+ this.request = stubDefinition.request
+ this.response = stubDefinition.response
}
void appendTo(BlockBuilder blockBuilder) {
blockBuilder.startBlock()
- blockBuilder.addLine('given:').startBlock()
- blockBuilder.addLine('def request = given()')
- blockBuilder.indent()
- stubDefinition.request.headers?.collect { Header header ->
- blockBuilder.addLine(".header('${header.name}', '${header.serverValue}')")
- }
- if (stubDefinition.request.body) {
- String matches = new JsonOutput().toJson(stubDefinition.request.body.serverValue)
- blockBuilder.addLine(".body('$matches')")
- }
- blockBuilder.unindent().endBlock().addEmptyLine()
-
- blockBuilder.addLine('when:').startBlock()
- blockBuilder.addLine('def response = given().spec(request)')
- blockBuilder.indent()
- blockBuilder.addLine(".${stubDefinition.request.method.serverValue.toLowerCase()}(\"$stubDefinition.request.url.serverValue\")")
- blockBuilder.unindent().endBlock().addEmptyLine()
-
- blockBuilder.addLine('then:').startBlock()
- blockBuilder.addLine("response.statusCode == $stubDefinition.response.status.serverValue")
-
- stubDefinition.response.headers?.collect { Header header ->
- blockBuilder.addLine("response.header('$header.name') == '$header.serverValue'")
- }
- if (stubDefinition.response.body) {
- blockBuilder.endBlock()
- blockBuilder.addLine('and:').startBlock()
- blockBuilder.addLine('def responseBody = new JsonSlurper().parseText(response.body.asString())')
- def responseBody = stubDefinition.response.body.serverValue
- if (responseBody instanceof List) {
- processArrayElements(responseBody, "", blockBuilder)
- } else {
- processMapElement(responseBody, blockBuilder, "")
- }
- }
- blockBuilder.endBlock()
+ givenBlock(blockBuilder)
+ whenBlock(blockBuilder)
+ thenBlock(blockBuilder)
blockBuilder.endBlock()
}
- private void processBodyElement(BlockBuilder blockBuilder, String rootProperty, def element) {
- def value = element.value
- String property = rootProperty + "." + element.key
- if (value instanceof String) {
- if (value.startsWith('$')) {
- value = value.substring(1).replaceAll('\\$value', "responseBody$property")
- blockBuilder.addLine(value)
- } else {
- blockBuilder.addLine("responseBody$property == \"${value}\"")
- }
- } else if (value instanceof Map) {
- processMapElement(value, blockBuilder, property)
- } else if (value instanceof List) {
- processArrayElements(value, property, blockBuilder)
- } else if (value instanceof Pattern) {
- blockBuilder.addLine("responseBody$property ==~ java.util.regex.Pattern.compile('${value}')")
- } else if (value instanceof ExecutionProperty) {
- ExecutionProperty exec = (ExecutionProperty) value
- blockBuilder.addLine("${exec.insertValue("responseBody$property")}")
- } else {
- blockBuilder.addLine("responseBody$property == ${value}")
+ protected void thenBlock(BlockBuilder bb) {
+ bb.addLine('then:')
+ bb.startBlock()
+ then(bb)
+ bb.endBlock()
+ }
+
+ protected void whenBlock(BlockBuilder bb) {
+ bb.addLine('when:')
+ bb.startBlock()
+ when(bb)
+ bb.endBlock().addEmptyLine()
+ }
+
+ protected void givenBlock(BlockBuilder bb) {
+ bb.addLine('given:')
+ bb.startBlock()
+ given(bb)
+ bb.endBlock().addEmptyLine()
+ }
+
+ protected void given(BlockBuilder bb) {}
+
+ protected abstract void when(BlockBuilder bb)
+
+ protected abstract void validateResponseCodeBlock(BlockBuilder bb)
+
+ protected abstract void validateResponseHeadersBlock(BlockBuilder bb)
+
+ protected abstract String getResponseAsString()
+
+ protected void then(BlockBuilder bb) {
+ validateResponseCodeBlock(bb)
+ if (response.headers) {
+ validateResponseHeadersBlock(bb)
+ }
+ if (response.body) {
+ bb.endBlock()
+ bb.addLine('and:').startBlock()
+ validateResponseBodyBlock(bb)
}
}
- private void processMapElement(def value, BlockBuilder blockBuilder, String property) {
- value.each { entry -> processBodyElement(blockBuilder, property, entry) }
- }
-
- private void processArrayElements(List responseBody, String property, BlockBuilder blockBuilder) {
- responseBody.eachWithIndex {
- listElement, listIndex ->
- listElement.each {
- entry -> processBodyElement(blockBuilder, property + "[$listIndex]", entry)
+ protected void validateResponseBodyBlock(BlockBuilder bb) {
+ def responseBody = response.body.serverValue
+ ContentType contentType = getResponseContentType()
+ if (responseBody instanceof GString) {
+ responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue })
+ }
+ if (contentType == ContentType.JSON) {
+ appendJsonPath(bb, responseAsString)
+ JsonPaths jsonPaths = JsonToJsonPathsConverter.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)")
+ processText(bb, "", responseBody as String)
}
}
- private void processClosure(Closure value, BlockBuilder blockBuilder, String property) {
- blockBuilder.addLine()
+
+ 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)
+ String json = new JsonOutput().toJson(bodyValue)
+ json = convertUnicodeEscapes(json)
+ return trimRepeatedQuotes(json)
+ }
+
+ protected String convertUnicodeEscapes(String json) {
+ return StringEscapeUtils.unescapeJavaScript(json)
+ }
+
+ protected String trimRepeatedQuotes(String toTrim) {
+ return toTrim.startsWith('"') ? toTrim.replaceAll('"', '') : toTrim
+ }
+
+ protected Object extractServerValueFromBody(bodyValue) {
+ if (bodyValue instanceof GString) {
+ bodyValue = extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue })
+ } else {
+ bodyValue = MapConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it })
+ }
+ return bodyValue
+ }
+
+ protected boolean allowedQueryParameter(QueryParameter param) {
+ return allowedQueryParameter(param.serverValue)
+ }
+
+ protected boolean allowedQueryParameter(MatchingStrategy matchingStrategy) {
+ return matchingStrategy.type != MatchingStrategy.Type.ABSENT
+ }
+
+ protected boolean allowedQueryParameter(Object o) {
+ return true
+ }
+
+ protected String resolveParamValue(QueryParameter param) {
+ return resolveParamValue(param.serverValue)
+ }
+
+ protected String resolveParamValue(Object value) {
+ return value.toString()
+ }
+
+ protected String resolveParamValue(MatchingStrategy matchingStrategy) {
+ return matchingStrategy.serverValue.toString()
+ }
+
+ protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) {
+
+ }
+
+ 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("parsedJson.read('\\\$$property')")}")
+ }
+
+ protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) {
+ processBodyElement(blockBuilder, property + "." + entry.key, entry.value)
+ }
+
+ protected void processBodyElement(BlockBuilder blockBuilder, String property, Map map) {
+ map.each {
+ processBodyElement(blockBuilder, property, it)
+ }
+ }
+
+ protected void processBodyElement(BlockBuilder blockBuilder, String property, List list) {
+ list.eachWithIndex { listElement, listIndex ->
+ String prop = "$property[$listIndex]" ?: ''
+ processBodyElement(blockBuilder, prop, listElement)
+ }
+ }
+
+ protected ContentType getRequestContentType() {
+ ContentType contentType = recognizeContentTypeFromHeader(request.headers)
+ if (contentType == ContentType.UNKNOWN) {
+ contentType = recognizeContentTypeFromContent(request.body.serverValue)
+ }
+ return contentType
+ }
+
+ protected ContentType getResponseContentType() {
+ ContentType contentType = recognizeContentTypeFromHeader(response.headers)
+ if (contentType == ContentType.UNKNOWN) {
+ contentType = recognizeContentTypeFromContent(response.body.serverValue)
+ }
+ return contentType
+ }
+
+ protected String getTestSideValue(Object object) {
+ return MapConverter.getClientOrServerSideValues(object, TEST_SIDE).toString()
}
}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy
index 965f3bf84a..9d69c3ee8e 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/config/AccurestConfigProperties.groovy
@@ -23,7 +23,7 @@ class AccurestConfigProperties {
File generatedTestSourcesDir
/**
- * Dir where the generated Wiremock stubs from Groovy DSL should be placed.
+ * Dir where the generated WireMock stubs from Groovy DSL should be placed.
* You can then mention them in your packaging task to create jar with stubs
*/
File stubsOutputDir
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/config/TestMode.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/config/TestMode.groovy
index e8a232e37c..1c7732d49e 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/config/TestMode.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/config/TestMode.groovy
@@ -4,5 +4,5 @@ package io.codearte.accurest.config
* @author Jakub Kubrynski
*/
enum TestMode {
- MOCKMVC, EXPLICIT
+ MOCKMVC, EXPLICIT, JAXRSCLIENT
}
\ No newline at end of file
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
new file mode 100755
index 0000000000..c485285281
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWireMockStubStrategy.groovy
@@ -0,0 +1,103 @@
+package io.codearte.accurest.dsl
+
+import groovy.json.JsonBuilder
+import groovy.transform.TypeChecked
+import io.codearte.accurest.dsl.internal.DslProperty
+import io.codearte.accurest.dsl.internal.Header
+import io.codearte.accurest.dsl.internal.Headers
+import io.codearte.accurest.util.ContentType
+import io.codearte.accurest.util.ContentUtils
+import io.codearte.accurest.util.MapConverter
+
+import java.util.regex.Pattern
+
+import static io.codearte.accurest.util.ContentUtils.extractValue
+import static io.codearte.accurest.util.MapConverter.transformValues
+
+@TypeChecked
+abstract class BaseWireMockStubStrategy {
+
+ private static final Boolean STUB_SIDE = true
+
+ protected getStubSideValue(Object object) {
+ return MapConverter.getClientOrServerSideValues(object, STUB_SIDE)
+ }
+
+ private static Closure transform = {
+ it instanceof DslProperty ? transformValues(it.clientValue, transform) : it
+ }
+
+ protected Map buildClientRequestHeadersSection(Headers headers) {
+ if (!headers) {
+ return null
+ }
+ return headers.entries.collectEntries { Header entry ->
+ parseHeader(entry.name, entry.clientValue)
+ }
+ }
+
+ protected Map buildClientResponseHeadersSection(Headers headers) {
+ if (!headers) {
+ return null
+ }
+ return headers.entries.collectEntries { Header entry ->
+ [(entry.name): entry.clientValue]
+ }
+ }
+
+ protected Map parseHeader(String entryKey, Object entry) {
+ return [(entryKey): [equalTo: entry]]
+ }
+
+ protected Map parseHeader(String entryKey, String entry) {
+ return [(entryKey): [equalTo: entry]]
+ }
+
+ protected Map parseHeader(String entryKey, Pattern entry) {
+ return [(entryKey): [matches: entry.pattern()]]
+ }
+
+ public String parseBody(Object value, ContentType contentType) {
+ return parseBody(value.toString(), contentType)
+ }
+
+ public Boolean parseBody(Boolean value, ContentType contentType) {
+ return value
+ }
+
+ public String parseBody(Map map, ContentType contentType) {
+ def transformedMap = MapConverter.getClientOrServerSideValues(map, true)
+ return parseBody(toJson(transformedMap), contentType)
+ }
+
+ public String parseBody(List list, ContentType contentType) {
+ return parseBody(toJson(list), contentType)
+ }
+
+ public String parseBody(GString value, ContentType contentType) {
+ Object processedValue = extractValue(value, contentType, { DslProperty dslProperty -> dslProperty.clientValue })
+ if (processedValue instanceof GString) {
+ return parseBody(processedValue.toString(), contentType)
+ }
+ return parseBody(processedValue, contentType)
+ }
+
+ public String parseBody(String value, ContentType contentType) {
+ return value
+ }
+
+ private static toJson(Object value) {
+ return new JsonBuilder(value).toString()
+ }
+
+ protected ContentType tryToGetContentType(Object body, Headers headers) {
+ ContentType contentType = ContentUtils.recognizeContentTypeFromHeader(headers)
+ if (contentType == ContentType.UNKNOWN) {
+ if (!body) {
+ return ContentType.UNKNOWN
+ }
+ return ContentUtils.getClientContentType(body)
+ }
+ return contentType
+ }
+}
\ No newline at end of file
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
deleted file mode 100755
index 77866f1437..0000000000
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/BaseWiremockStubStrategy.groovy
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.codearte.accurest.dsl
-import groovy.json.JsonOutput
-import groovy.json.JsonSlurper
-import groovy.transform.TypeChecked
-import groovy.xml.XmlUtil
-import io.codearte.accurest.dsl.internal.Header
-import io.codearte.accurest.dsl.internal.Headers
-
-import java.util.regex.Pattern
-
-import static groovy.json.StringEscapeUtils.escapeJava
-
-@TypeChecked
-abstract class BaseWiremockStubStrategy {
- protected Map buildClientRequestHeadersSection(Headers headers) {
- if (!headers) {
- return null
- }
- return headers.entries.collectEntries { Header entry ->
- parseHeader(entry.name, entry.clientValue)
- }
- }
-
- protected Map buildClientResponseHeadersSection(Headers headers) {
- if (!headers) {
- return null
- }
- return headers.entries.collectEntries { Header entry ->
- [(entry.name) : entry.clientValue]
- }
- }
-
- protected Map parseHeader(String entryKey, Object entry) {
- return [(entryKey): [equalTo : entry]]
- }
-
- protected Map parseHeader(String entryKey, String entry) {
- return [(entryKey): [equalTo : entry]]
- }
-
- protected Map parseHeader(String entryKey, Pattern entry) {
- return [(entryKey): [matches : entry.pattern()]]
- }
-
- protected String parseBody(Object body) {
- String bodyAsString = body as String
- try {
- def json = new JsonSlurper().parseText(bodyAsString)
- return escapeJava(JsonOutput.toJson(bodyAsString))
- } catch (Exception jsonException) {
- try {
- def xml = new XmlSlurper().parseText(bodyAsString)
- return escapeJava(XmlUtil.serialize(bodyAsString))
- } catch (Exception xmlException) {
- return escapeJava(bodyAsString)
- }
- }
- }
-
- protected String parseBody(List body) {
- return JsonOutput.toJson(body)
- }
-
- protected String parseBody(Map body) {
- return JsonOutput.toJson(body)
- }
-}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/GroovyDsl.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/GroovyDsl.groovy
index 717047341d..af046d188f 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/GroovyDsl.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/GroovyDsl.groovy
@@ -7,10 +7,11 @@ import io.codearte.accurest.dsl.internal.Request
import io.codearte.accurest.dsl.internal.Response
@TypeChecked
-@EqualsAndHashCode(includeFields = true)
+@EqualsAndHashCode
@ToString(includeFields = true, includePackage = false, includeNames = true)
class GroovyDsl {
+ Integer priority
Request request
Response response
@@ -21,6 +22,10 @@ class GroovyDsl {
return dsl
}
+ void priority(int priority) {
+ this.priority = priority
+ }
+
void request(@DelegatesTo(Request) Closure closure) {
this.request = new Request()
closure.delegate = request
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
new file mode 100755
index 0000000000..cf69737c95
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockRequestStubStrategy.groovy
@@ -0,0 +1,232 @@
+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 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.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.buildGStringRegexpForStubSide
+import static io.codearte.accurest.util.RegexpBuilders.buildJSONRegexpMatch
+
+@TypeChecked
+@PackageScope
+class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
+
+ private final Request request
+
+ WireMockRequestStubStrategy(GroovyDsl groovyDsl) {
+ this.request = groovyDsl.request
+ }
+
+ @PackageScope
+ RequestPattern buildClientRequestContent() {
+ RequestPattern requestPattern = new RequestPattern()
+ appendMethod(requestPattern)
+ appendHeaders(requestPattern)
+ appendUrl(requestPattern)
+ appendQueryParameters(requestPattern)
+ appendBody(requestPattern)
+ return requestPattern
+ }
+
+ private void appendMethod(RequestPattern requestPattern) {
+ if(!request.method) {
+ return
+ }
+ requestPattern.setMethod(RequestMethod.fromString(request.method.clientValue?.toString()))
+ }
+
+ private void appendBody(RequestPattern requestPattern) {
+ if (!request.body) {
+ return
+ }
+ ContentType contentType = tryToGetContentType(request.body.clientValue, request.headers)
+ if (contentType == ContentType.JSON) {
+ 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) ) ]
+ } 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 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) {
+ requestPattern.setUrlPath(getStubSideValue(urlPath.toString()).toString())
+ }
+ if(!request.url) {
+ return
+ }
+ Object url = getUrlIfGstring(request?.url?.clientValue)
+ if(url instanceof Pattern) {
+ requestPattern.setUrlPattern(url.pattern())
+ } else {
+ requestPattern.setUrl(url.toString())
+ }
+ }
+
+ private Object getUrlIfGstring(Object clientSide) {
+ if (clientSide instanceof GString) {
+ if (clientSide.values.any { getStubSideValue(it) instanceof Pattern }) {
+ return Pattern.compile(getStubSideValue(clientSide).toString())
+ } else {
+ return getStubSideValue(clientSide).toString()
+ }
+ }
+ return clientSide
+ }
+
+ private void appendQueryParameters(RequestPattern requestPattern) {
+ QueryParameters queryParameters = request?.urlPath?.queryParameters ?: request?.url?.queryParameters
+ queryParameters?.parameters?.each {
+ requestPattern.addQueryParam(it.name, convertToValuePattern(it.clientValue))
+ }
+ }
+
+ @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())
+ }
+ }
+
+ private MatchingStrategy getMatchingStrategyFromBody(Body body) {
+ if(!body) {
+ return null
+ }
+ return getMatchingStrategy(body.clientValue)
+ }
+
+ 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 def getStringFromGString(Object object) {
+ return object instanceof GString ? object.toString() : object
+ }
+
+ private MatchingStrategy getMatchingStrategy(Object bodyValue) {
+ return tryToFindMachingStrategy(bodyValue)
+ }
+
+ private MatchingStrategy tryToFindMachingStrategy(Object bodyValue) {
+ return new MatchingStrategy(MapConverter.transformToClientValues(bodyValue), getEqualsTypeFromContentTypeHeader())
+ }
+
+ private MatchingStrategy getMatchingStrategyIncludingContentType(MatchingStrategy matchingStrategy) {
+ MatchingStrategy.Type type = matchingStrategy.type
+ Object value = matchingStrategy.clientValue
+ ContentType contentType = recognizeContentTypeFromMatchingStrategy(type)
+ if (contentType == ContentType.UNKNOWN && type == MatchingStrategy.Type.EQUAL_TO) {
+ contentType = recognizeContentTypeFromContent(value)
+ type = getEqualsTypeFromContentType(contentType)
+ }
+ return new MatchingStrategy(parseBody(value, contentType), type)
+ }
+
+ private MatchingStrategy appendBodyRegexpMatchPattern(Object value, ContentType contentType) {
+ switch (contentType) {
+ case ContentType.JSON:
+ return new MatchingStrategy(buildJSONRegexpMatch(value), MatchingStrategy.Type.MATCHING)
+ case ContentType.UNKNOWN:
+ return new MatchingStrategy(buildGStringRegexpForStubSide(value), MatchingStrategy.Type.MATCHING)
+ case ContentType.XML:
+ throw new IllegalStateException("XML pattern matching is not implemented yet")
+ }
+ }
+
+ private MatchingStrategy appendBodyRegexpMatchPattern(Object value) {
+ return appendBodyRegexpMatchPattern(value, ContentType.UNKNOWN)
+ }
+
+ private boolean containsPattern(GString bodyAsValue) {
+ return containsPattern(bodyAsValue.values)
+ }
+
+ private boolean containsPattern(Map map) {
+ return containsPattern(map.entrySet())
+ }
+
+ private boolean containsPattern(Collection collection) {
+ return collection.collect(this.&containsPattern).inject('') { a, b -> a || b }
+ }
+
+ private boolean containsPattern(Object[] objects) {
+ return containsPattern(objects.toList())
+ }
+
+ private boolean containsPattern(Map.Entry entry) {
+ return containsPattern(entry.value)
+ }
+
+ private boolean containsPattern(DslProperty dslProperty) {
+ return containsPattern(dslProperty.clientValue)
+ }
+
+ private boolean containsPattern(Pattern pattern) {
+ return true
+ }
+
+ private boolean containsPattern(Object o) {
+ return false
+ }
+
+ private MatchingStrategy.Type getEqualsTypeFromContentTypeHeader() {
+ return getEqualsTypeFromContentType(recognizeContentTypeFromHeader(request.headers))
+ }
+
+}
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
new file mode 100755
index 0000000000..3f63e6433c
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockResponseStubStrategy.groovy
@@ -0,0 +1,57 @@
+package io.codearte.accurest.dsl
+
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder
+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.Request
+import io.codearte.accurest.dsl.internal.Response
+import io.codearte.accurest.util.ContentType
+
+import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromContent
+import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHeader
+
+@TypeChecked
+@PackageScope
+class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
+
+ private final Request request
+ private final Response response
+
+ WireMockResponseStubStrategy(GroovyDsl groovyDsl) {
+ this.response = groovyDsl.response
+ this.request = groovyDsl.request
+ }
+
+ @PackageScope
+ ResponseDefinition buildClientResponseContent() {
+ ResponseDefinitionBuilder builder = new ResponseDefinitionBuilder()
+ .withStatus(response.status.clientValue as Integer)
+ appendHeaders(builder)
+ appendBody(builder)
+ return builder.build()
+ }
+
+ private void appendHeaders(ResponseDefinitionBuilder builder) {
+ if (response.headers) {
+ builder.withHeaders(new HttpHeaders(response.headers.entries?.collect {
+ new HttpHeader(it.name, it.clientValue.toString())
+ }))
+ }
+ }
+
+ private void appendBody(ResponseDefinitionBuilder builder) {
+ if (response.body) {
+ Object body = response.body.clientValue
+ ContentType contentType = recognizeContentTypeFromHeader(response.headers)
+ if (contentType == ContentType.UNKNOWN) {
+ contentType = recognizeContentTypeFromContent(body)
+ }
+ builder.withBody(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
new file mode 100644
index 0000000000..337f7b8557
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WireMockStubStrategy.groovy
@@ -0,0 +1,34 @@
+package io.codearte.accurest.dsl
+
+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
+
+@CompileStatic
+class WireMockStubStrategy {
+
+ private final WireMockRequestStubStrategy wireMockRequestStubStrategy
+ private final WireMockResponseStubStrategy wireMockResponseStubStrategy
+ private final Integer priority
+
+ WireMockStubStrategy(GroovyDsl groovyDsl) {
+ this.wireMockRequestStubStrategy = new WireMockRequestStubStrategy(groovyDsl)
+ this.wireMockResponseStubStrategy = new WireMockResponseStubStrategy(groovyDsl)
+ this.priority = groovyDsl.priority
+ }
+
+ @CompileDynamic
+ String toWireMockClientStub() {
+ StubMapping stubMapping = new StubMapping()
+ RequestPattern request = wireMockRequestStubStrategy.buildClientRequestContent()
+ ResponseDefinition response = wireMockResponseStubStrategy.buildClientResponseContent()
+ if (priority) {
+ stubMapping.priority = priority
+ }
+ 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/WiremockRequestStubStrategy.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy
deleted file mode 100755
index 36f7ec1ab5..0000000000
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockRequestStubStrategy.groovy
+++ /dev/null
@@ -1,52 +0,0 @@
-package io.codearte.accurest.dsl
-import groovy.transform.PackageScope
-import groovy.transform.TypeChecked
-import io.codearte.accurest.dsl.internal.ClientRequest
-import io.codearte.accurest.dsl.internal.Request
-
-import java.util.regex.Pattern
-
-@TypeChecked
-@PackageScope
-class WiremockRequestStubStrategy extends BaseWiremockStubStrategy {
-
- private final Request request
-
- WiremockRequestStubStrategy(GroovyDsl groovyDsl) {
- this.request = groovyDsl.request
- }
-
- @PackageScope
- Map buildClientRequestContent() {
- return buildRequestContent(new ClientRequest(request))
- }
-
- private Map buildRequestContent(ClientRequest request) {
- return ([method : request?.method?.clientValue,
- headers : buildClientRequestHeadersSection(request.headers)
- ] << appendUrl(request) << appendBody(request)).findAll { it.value }
- }
-
- private Map appendUrl(ClientRequest clientRequest) {
- Object url = clientRequest?.url?.clientValue
- return url instanceof Pattern ? [urlPattern: ((Pattern)url).pattern()] : [url: url]
- }
-
- private Map appendBody(ClientRequest clientRequest) {
- Object body = clientRequest?.body?.clientValue
- if (body == null) {
- return [:]
- }
- if (containsRegex(body)) {
- return [bodyPatterns: [[matches: parseBody(body)]]]
- }
-
- return [bodyPatterns: [[equalTo: parseBody(body)]]]
- }
-
- boolean containsRegex(Object bodyObject) {
- String bodyString = bodyObject as String
- return (bodyString =~ /\^.*\$/).find()
- }
-
-}
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
deleted file mode 100755
index e0b7556547..0000000000
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockResponseStubStrategy.groovy
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.codearte.accurest.dsl
-import groovy.transform.PackageScope
-import groovy.transform.TypeChecked
-import io.codearte.accurest.dsl.internal.ClientResponse
-import io.codearte.accurest.dsl.internal.Response
-
-@TypeChecked
-@PackageScope
-class WiremockResponseStubStrategy extends BaseWiremockStubStrategy {
-
- private final Response response
-
- WiremockResponseStubStrategy(GroovyDsl groovyDsl) {
- this.response = groovyDsl.response
- }
-
- @PackageScope
- Map buildClientResponseContent() {
- return buildResponseContent(new ClientResponse(response))
- }
-
- private Map buildResponseContent(ClientResponse response) {
- return ([status : response?.status?.clientValue,
- headers: buildClientResponseHeadersSection(response.headers)
- ] << appendBody(response)).findAll { it.value }
- }
-
- private Map appendBody(ClientResponse response) {
- Object body = response?.body?.clientValue
- return body != null ? [body: parseBody(body)] : [:]
- }
-}
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
deleted file mode 100644
index a4bf3ee9c4..0000000000
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/WiremockStubStrategy.groovy
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.codearte.accurest.dsl
-
-import groovy.json.JsonOutput
-import groovy.transform.CompileStatic
-
-@CompileStatic
-class WiremockStubStrategy {
-
- private final WiremockRequestStubStrategy wiremockRequestStubStrategy
- private final WiremockResponseStubStrategy wiremockResponseStubStrategy
-
- WiremockStubStrategy(GroovyDsl groovyDsl) {
- this.wiremockRequestStubStrategy = new WiremockRequestStubStrategy(groovyDsl)
- this.wiremockResponseStubStrategy = new WiremockResponseStubStrategy(groovyDsl)
- }
-
- String toWiremockClientStub() {
- return JsonOutput.prettyPrint(JsonOutput.toJson([request : wiremockRequestStubStrategy.buildClientRequestContent(),
- response: wiremockResponseStubStrategy.buildClientResponseContent()]))
- }
-}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy
index 5e8d46ed98..df799d87f8 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Body.groovy
@@ -1,16 +1,16 @@
package io.codearte.accurest.dsl.internal
-import groovy.json.JsonSlurper
+import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
-import org.codehaus.groovy.runtime.GStringImpl
@ToString(includePackage = false, includeFields = true, includeNames = true)
@EqualsAndHashCode(includeFields = true)
+@CompileStatic
class Body extends DslProperty {
Body(Map body) {
- super(extractValue(body, {it.clientValue}), extractValue(body, {it.serverValue}))
+ super(extractValue(body, { DslProperty p -> p.clientValue}), extractValue(body, {DslProperty p -> p.serverValue}))
}
private static Map extractValue(Map body, Closure valueProvider) {
@@ -19,8 +19,8 @@ class Body extends DslProperty {
} as Map
}
- Body(List bodyAsList) {
- super(bodyAsList.collect { it.clientValue }, bodyAsList.collect { it.serverValue })
+ Body(List bodyAsList) {
+ super(bodyAsList.collect { DslProperty p -> p.clientValue }, bodyAsList.collect { DslProperty p -> p.serverValue })
}
Body(Object bodyAsValue) {
@@ -28,17 +28,16 @@ class Body extends DslProperty {
}
Body(GString bodyAsValue) {
- super(extractValue(bodyAsValue, {it.clientValue}), extractValue(bodyAsValue, {it.serverValue}))
+ super(bodyAsValue, bodyAsValue)
}
Body(DslProperty bodyAsValue) {
super(bodyAsValue.clientValue, bodyAsValue.serverValue)
}
- private static Object extractValue(GString bodyAsValue, Closure valueProvider) {
- GString clientGString = new GStringImpl(bodyAsValue.values.clone(), bodyAsValue.strings.clone())
- Object[] clientValues = bodyAsValue.values.collect { it instanceof DslProperty ? valueProvider(it) : it } as Object[]
- return new JsonSlurper().parseText(new GStringImpl(clientValues, clientGString.strings).toString())
+ Body(MatchingStrategy matchingStrategy) {
+ super(matchingStrategy, matchingStrategy)
}
-
+
+
}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Common.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Common.groovy
index 91549f6409..c96ff4b2d4 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Common.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Common.groovy
@@ -13,6 +13,8 @@ import java.util.regex.Pattern
@PackageScope
class Common {
+ @Delegate private final RegexPatterns regexPatterns = new RegexPatterns()
+
Map convertObjectsToDslProperties(Map body) {
return body.collectEntries {
Map.Entry entry ->
@@ -20,10 +22,10 @@ class Common {
} as Map
}
- List convertObjectsToDslProperties(List body) {
- return body.collect {
+ Collection convertObjectsToDslProperties(List body) {
+ return (body.collect {
Object element -> toDslProperty(element)
- } as List
+ } as List)
}
DslProperty toDslProperty(Object property) {
@@ -47,10 +49,16 @@ class Common {
}
DslProperty value(ClientDslProperty client, ServerDslProperty server) {
+ assertThatSidesMatch(client.clientValue, server.serverValue)
return new DslProperty(client.clientValue, server.serverValue)
}
+ DslProperty value(Object value) {
+ return new DslProperty(value)
+ }
+
DslProperty value(ServerDslProperty server, ClientDslProperty client) {
+ assertThatSidesMatch(client.clientValue, server.serverValue)
return new DslProperty(client.clientValue, server.serverValue)
}
@@ -66,6 +74,10 @@ class Common {
return Pattern.compile(regex)
}
+ OptionalProperty optional(Object object) {
+ return new OptionalProperty(object)
+ }
+
ExecutionProperty execute(String commandToExecute) {
return new ExecutionProperty(commandToExecute)
}
@@ -74,7 +86,53 @@ class Common {
return new ClientDslProperty(clientValue)
}
+ ClientDslProperty stub(Object clientValue) {
+ return new ClientDslProperty(clientValue)
+ }
+
ServerDslProperty server(Object serverValue) {
return new ServerDslProperty(serverValue)
}
+
+ ServerDslProperty test(Object serverValue) {
+ return new ServerDslProperty(serverValue)
+ }
+
+ void assertThatSidesMatch(OptionalProperty stubSide, Object testSide) {
+ assert testSide ==~ Pattern.compile(stubSide.optionalPattern())
+ }
+
+ void assertThatSidesMatch(Pattern pattern, String value) {
+ assert value ==~ pattern
+ }
+
+ void assertThatSidesMatch(String value, Pattern pattern) {
+ assert value ==~ pattern
+ }
+
+ void assertThatSidesMatch(MatchingStrategy firstSide, MatchingStrategy secondSide) {
+ if (firstSide.type == MatchingStrategy.Type.ABSENT && secondSide != MatchingStrategy.Type.ABSENT) {
+ throwAbsentError()
+ }
+ }
+
+ void assertThatSidesMatch(MatchingStrategy firstSide, Object secondSide) {
+ if (firstSide.type == MatchingStrategy.Type.ABSENT) {
+ throwAbsentError()
+ }
+ }
+
+ void assertThatSidesMatch(Object firstSide, MatchingStrategy secondSide) {
+ if (secondSide.type == MatchingStrategy.Type.ABSENT) {
+ throwAbsentError()
+ }
+ }
+
+ private void throwAbsentError() {
+ throw new IllegalStateException("Absent cannot only be used only on one side")
+ }
+
+ void assertThatSidesMatch(Object firstSide, Object secondSide) {
+ // do nothing
+ }
}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/ExecutionProperty.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/ExecutionProperty.groovy
index ccc7037575..866afdc18c 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/ExecutionProperty.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/ExecutionProperty.groovy
@@ -5,15 +5,15 @@ import groovy.transform.CompileStatic
@CompileStatic
class ExecutionProperty {
- private static final String PLACEHOLDER_VALUE = '\\$it'
+ private static final String PLACEHOLDER_VALUE = '\\$it'
- final String executionCommand
+ final String executionCommand
- ExecutionProperty(String executionCommand) {
- this.executionCommand = executionCommand
- }
+ ExecutionProperty(String executionCommand) {
+ this.executionCommand = executionCommand
+ }
- String insertValue(String valueToInsert) {
- return executionCommand.replaceAll(PLACEHOLDER_VALUE, valueToInsert)
- }
+ String insertValue(String valueToInsert) {
+ return executionCommand.replaceAll(PLACEHOLDER_VALUE, valueToInsert)
+ }
}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Header.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Header.groovy
index a7eefa180a..b72037cd03 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Header.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/Header.groovy
@@ -8,16 +8,16 @@ import groovy.transform.ToString
@CompileStatic
class Header extends DslProperty {
- String name
+ String name
- Header(String name, DslProperty dslProperty) {
- super(dslProperty.clientValue, dslProperty.serverValue)
- this.name = name
- }
+ Header(String name, DslProperty dslProperty) {
+ super(dslProperty.clientValue, dslProperty.serverValue)
+ this.name = name
+ }
- Header(String name, Object value) {
- super(value)
- this.name = name
- }
+ Header(String name, Object value) {
+ super(value)
+ this.name = name
+ }
}
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
new file mode 100644
index 0000000000..b6b6f79eee
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/dsl/internal/JsonStructureConverter.groovy
@@ -0,0 +1,32 @@
+package io.codearte.accurest.dsl.internal
+
+import groovy.json.JsonOutput
+import groovy.transform.CompileStatic
+import io.codearte.accurest.util.MapConverter
+
+import java.util.regex.Pattern
+
+@CompileStatic
+class JsonStructureConverter {
+
+ public static final String TEMPORARY_PLACEHOLDER = '###PLACEHOLDER###'
+ public static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.compile(TEMPORARY_PLACEHOLDER)
+
+ static Object convertJsonStructureToObjectUnderstandingStructure(Object parsedJson,
+ Closure retrievePlaceholders,
+ Closure performAdditionalLogicOnSerializedJson,
+ Closure convertSerializedJsonToSth) {
+ LinkedList
+ *
+ * Thus one can safely write {@code executionMatcher[0][1]} to retrieve the matched group
+ *
+ * @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()) {
+ return Pattern.compile(patternFromMatchingGroup(matcher))
+ }
+ Matcher executionMatcher = TEMPORARY_EXECUTION_PATTERN_HOLDER.matcher(string.trim())
+ if (executionMatcher.matches()) {
+ return new ExecutionProperty(patternFromMatchingGroup(executionMatcher))
+ }
+ Matcher optionalMatcher = TEMPORARY_OPTIONAL_PATTERN_HOLDER.matcher(string.trim())
+ if (optionalMatcher.matches()) {
+ String patternToMatch = patternFromMatchingGroup(optionalMatcher)
+ return Pattern.compile(new OptionalProperty(patternToMatch).optionalPattern())
+ }
+ return string
+ }
+
+ private static String patternFromMatchingGroup(Matcher matcher) {
+ List val = matcher[0] as List
+ return val[1]
+ }
+
+ public static ContentType recognizeContentTypeFromHeader(Headers headers) {
+ String content = headers?.entries.find { it.name == "Content-Type" } ?.clientValue?.toString()
+ if (content?.endsWith("json")) {
+ return ContentType.JSON
+ }
+ if (content?.endsWith("xml")) {
+ return ContentType.XML
+ }
+ return ContentType.UNKNOWN
+ }
+
+ public static MatchingStrategy.Type getEqualsTypeFromContentType(ContentType contentType) {
+ switch (contentType) {
+ case ContentType.JSON:
+ return MatchingStrategy.Type.EQUAL_TO_JSON
+ case ContentType.XML:
+ return MatchingStrategy.Type.EQUAL_TO_XML
+ }
+ return MatchingStrategy.Type.EQUAL_TO
+ }
+
+ public static ContentType recognizeContentTypeFromContent(GString gstring) {
+ if (isJsonType(gstring)) {
+ return ContentType.JSON
+ }
+ if (isXmlType(gstring)) {
+ return ContentType.XML
+ }
+ return ContentType.UNKNOWN
+ }
+
+ public static ContentType recognizeContentTypeFromContent(Map jsonMap) {
+ return ContentType.JSON
+ }
+
+ public static ContentType recognizeContentTypeFromContent(List jsonList) {
+ return ContentType.JSON
+ }
+
+ public static ContentType recognizeContentTypeFromContent(Object gstring) {
+ return ContentType.UNKNOWN
+ }
+
+ public static boolean isJsonType(GString gstring) {
+ if (gstring.isEmpty()) {
+ return false
+ }
+ GString stringWithoutValues = new GStringImpl(
+ gstring.values.collect({
+ it instanceof String || it instanceof GString ? it.toString() : escapeJson(it.toString())
+ }) as Object[],
+ gstring.strings.clone() as String[]
+ )
+ try {
+ new JsonSlurper().parseText(stringWithoutValues.toString())
+ return true
+ } catch (JsonException e) {
+ // Not JSON
+ }
+ return false
+ }
+
+ public static boolean isXmlType(GString gstring) {
+ GString stringWithoutValues = new GStringImpl(
+ gstring.values.collect({
+ it instanceof String || it instanceof GString ? it.toString() : escapeXml11(it.toString())
+ }) as Object[],
+ gstring.strings.clone() as String[]
+ )
+ try {
+ new XmlSlurper().parseText(stringWithoutValues.toString())
+ return true
+ } catch (Exception e) {
+ // Not XML
+ }
+ return false
+ }
+
+ public static ContentType recognizeContentTypeFromMatchingStrategy(MatchingStrategy.Type type) {
+ switch (type) {
+ case MatchingStrategy.Type.EQUAL_TO_XML:
+ return ContentType.XML
+ case MatchingStrategy.Type.EQUAL_TO_JSON:
+ return ContentType.JSON
+ }
+ return ContentType.UNKNOWN
+ }
+
+}
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..be1638027e
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonPathEntry.groovy
@@ -0,0 +1,40 @@
+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).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/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/JsonToJsonPathsConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonToJsonPathsConverter.groovy
new file mode 100644
index 0000000000..319e7ab660
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/JsonToJsonPathsConverter.groovy
@@ -0,0 +1,148 @@
+package io.codearte.accurest.util
+import java.util.regex.Pattern
+import groovy.json.JsonSlurper
+import io.codearte.accurest.dsl.internal.ExecutionProperty
+import io.codearte.accurest.dsl.internal.OptionalProperty
+
+/**
+ * @author Marcin Grzejszczak
+ */
+class JsonToJsonPathsConverter {
+
+ 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 = MapConverter.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
+ }
+
+ 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 patternComparison((value as Pattern).pattern())
+ } else if (value instanceof OptionalProperty) {
+ return patternComparison((value as OptionalProperty).optionalPattern())
+ } else if (value instanceof GString) {
+ return """=~ /${RegexpBuilders.buildGStringRegexpForTestSide(value)}/"""
+ }
+ return """== ${potentiallyWrappedWithQuotesValue(value)}"""
+ }
+
+ protected static String patternComparison(String pattern){
+ return """=~ /$pattern/"""
+ }
+
+ protected static String potentiallyWrappedWithQuotesValue(Object value) {
+ return value instanceof Number ? value : "'$value'"
+ }
+
+}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy
new file mode 100644
index 0000000000..7087f9c1d7
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/MapConverter.groovy
@@ -0,0 +1,76 @@
+package io.codearte.accurest.util
+import groovy.json.JsonSlurper
+import io.codearte.accurest.dsl.internal.DslProperty
+/**
+ * @author Marcin Grzejszczak
+ */
+class MapConverter {
+
+ static def transformToClientValues(def value) {
+ return transformValues(value) {
+ it instanceof DslProperty ? it.clientValue : it
+ }
+ }
+
+ static def transformValues(def value, Closure closure) {
+ if (value instanceof String && value) {
+ try {
+ def json = new JsonSlurper().parseText(value)
+ if (json instanceof Map) {
+ return convert(json, closure)
+ }
+ } catch (Exception ignore) {
+ }
+ return extractValue(value, closure);
+ } else if (value instanceof Map) {
+ return convert(value as Map, closure)
+ } else if (value instanceof List) {
+ return value.collect({ transformValues(it, closure) })
+ }
+ return transformValue(closure, value)
+ }
+
+ protected static Object transformValue(Closure closure, Object value) {
+ return extractValue(value, { Object val->
+ Object newValue = closure(val)
+ if (newValue instanceof Map || newValue instanceof List || newValue instanceof String && value) {
+ return transformValues(newValue, closure)
+ }
+ return newValue;
+ })
+ }
+
+ private static extractValue(Object value, Closure closure) {
+ try {
+ return closure(value)
+ } catch (Exception ignore) {
+ return value
+ }
+ }
+
+ private static Map convert(Map map, Closure closure) {
+ return map.collectEntries {
+ key, value ->
+ [key, transformValues(value, closure)]
+ }
+ }
+
+ static Object getClientOrServerSideValues(json, boolean clientSide) {
+ return transformValues(json) {
+ 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
+ }
+ }
+}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/NamesUtil.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/NamesUtil.groovy
index 88172ca90b..5b19c72645 100644
--- a/accurest-core/src/main/groovy/io/codearte/accurest/util/NamesUtil.groovy
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/NamesUtil.groovy
@@ -47,7 +47,7 @@ class NamesUtil {
}
static String packageToDirectory(String packageName) {
- return packageName.replaceAll('\\.', File.separator)
+ return packageName.replace('.' as char, File.separatorChar)
}
static String directoryToPackage(String directory) {
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/RegexpBuilders.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/RegexpBuilders.groovy
new file mode 100644
index 0000000000..6c8b703fca
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/RegexpBuilders.groovy
@@ -0,0 +1,91 @@
+package io.codearte.accurest.util
+
+import io.codearte.accurest.dsl.internal.DslProperty
+import org.codehaus.groovy.runtime.GStringImpl
+
+import java.util.regex.Pattern
+
+import static io.codearte.accurest.util.ContentUtils.extractValue
+import static org.apache.commons.lang3.StringEscapeUtils.escapeJson
+
+public class RegexpBuilders {
+
+ public static String buildGStringRegexpForStubSide(GString gString) {
+ new GStringImpl(
+ gString.values.collect(this.&buildGStringRegexpForStubSide) as Object[],
+ gString.strings.collect(this.&escapeSpecialRegexChars) as String[]
+ )
+ }
+
+ public static String buildGStringRegexpForStubSide(Pattern pattern) {
+ return pattern.pattern()
+ }
+
+ public static String buildGStringRegexpForStubSide(DslProperty dslProperty) {
+ return buildGStringRegexpForStubSide(dslProperty.clientValue)
+ }
+
+ 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')
+ }
+
+ private final static String WS = /\s*/
+
+ public static String buildJSONRegexpMatch(GString gString) {
+ return buildJSONRegexpMatch(extractValue(gString, ContentType.JSON, { DslProperty dslProperty -> dslProperty.clientValue }))
+ }
+
+ public static String buildJSONRegexpMatch(Map jsonMap) {
+ return WS + "\\{" + jsonMap.collect(this.&buildJSONRegexpMatch).join(",") + "\\}" + WS
+ }
+
+ public static String buildJSONRegexpMatch(List jsonList) {
+ return WS + "\\[" + jsonList.collect(this.&buildJSONRegexpMatch).join(",") + "\\]" + WS
+ }
+
+ public static String buildJSONRegexpMatch(Map.Entry entry) {
+ return buildJSONRegexpMatchString(escapeJson(entry.key)) + ":" + buildJSONRegexpMatch(entry.value)
+ }
+
+ public static String buildJSONRegexpMatch(Object value) {
+ return buildJSONRegexpMatchStringOptionalQuotes(escapeJson(value.toString()))
+ }
+
+ public static String buildJSONRegexpMatch(Pattern pattern) {
+ return buildJSONRegexpMatchStringOptionalQuotes(pattern.pattern())
+ }
+
+ public static String buildJSONRegexpMatchString(String value) {
+ return WS + '"' + value + '"' + WS
+ }
+
+ public static String buildJSONRegexpMatchStringOptionalQuotes(String value) {
+ return WS + '"?' + value + '"?' + WS
+ }
+
+}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy
deleted file mode 100644
index f1ce59959f..0000000000
--- a/accurest-core/src/main/groovy/io/codearte/accurest/util/StubMappingConverter.groovy
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.codearte.accurest.util
-
-import groovy.json.JsonException
-import groovy.json.JsonSlurper
-
-import java.util.regex.Pattern
-
-/**
- * @author Marcin Grzejszczak
- */
-class StubMappingConverter {
-
- private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile(/^\$\{(.*):(.*)\}$/)
- public static final int SERVER_SIDE_GROUP = 2
-
- static Map toStubMappingOnServerSide(File stubMapping) {
- def json = new JsonSlurper().parse(stubMapping)
- return convertPlaceholders(json as Map, { String value ->
- getGroupFromMatchingPattern(value)
- })
- }
-
- private static Map convertPlaceholders(Map map, Closure closure) {
- return map.collectEntries {
- key, value ->
- [key, transformValue(value, closure)]
- }
- }
-
- static def transformValue(def value, Closure closure) {
- if (value instanceof String && value) {
- try {
- def json = new JsonSlurper().parseText(value)
- if (json instanceof Map) {
- return convertPlaceholders(json, closure)
- }
- } catch (JsonException ignore) {
- return closure(value)
- }
- } else if (value instanceof Map) {
- return convertPlaceholders(value as Map, closure)
- } else if (value instanceof List) {
- return value.collect({ transformValue(it, closure) })
- }
-
- return value
- }
-
- private static Object getGroupFromMatchingPattern(String value) {
- return value.matches(PLACEHOLDER_PATTERN) ? PLACEHOLDER_PATTERN.matcher(value)[0][SERVER_SIDE_GROUP] : value
- }
-
-}
diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/util/ValidateUtils.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/util/ValidateUtils.groovy
new file mode 100644
index 0000000000..46e9706cfe
--- /dev/null
+++ b/accurest-core/src/main/groovy/io/codearte/accurest/util/ValidateUtils.groovy
@@ -0,0 +1,46 @@
+package io.codearte.accurest.util
+
+import groovy.transform.TypeChecked
+import io.codearte.accurest.dsl.internal.DslProperty
+import io.codearte.accurest.dsl.internal.MatchingStrategy
+
+import java.util.regex.Pattern
+
+import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.ABSENT
+import static io.codearte.accurest.dsl.internal.MatchingStrategy.Type.EQUAL_TO
+
+@TypeChecked
+class ValidateUtils {
+
+ static Object validateServerValueIsAvailable(Object value) {
+ validateServerValueIsAvailable(value, "Server value")
+ return value
+ }
+
+ static Object validateServerValueIsAvailable(Object value, String msg) {
+ validateServerValue(value, msg)
+ return value
+ }
+
+ static void validateServerValue(Pattern pattern, String msg) {
+ throw new IllegalStateException("$msg can't be a pattern for the server side")
+ }
+
+ static List ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE = [EQUAL_TO, ABSENT]
+
+ static void validateServerValue(MatchingStrategy matchingStrategy, String msg) {
+ if (!ALLOWED_MATCHING_TYPES_ON_SERVER_SIDE.contains(matchingStrategy.type)) {
+ throw new IllegalStateException("$msg can't be of a matching type: $matchingStrategy.type for the server side")
+ }
+ validateServerValue(matchingStrategy.serverValue, msg)
+ }
+
+ static void validateServerValue(DslProperty value, String msg) {
+ validateServerValue(value.serverValue, msg)
+ }
+
+ static void validateServerValue(Object value, String msg) {
+ // OK
+ }
+
+}
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
new file mode 100644
index 0000000000..aa5a26cb5d
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/JaxRsClientSpockMethodBuilderSpec.groovy
@@ -0,0 +1,414 @@
+package io.codearte.accurest.builder
+
+import io.codearte.accurest.dsl.GroovyDsl
+import io.codearte.accurest.dsl.WireMockStubStrategy
+import io.codearte.accurest.dsl.WireMockStubVerifier
+import spock.lang.Issue
+import spock.lang.Specification
+
+class JaxRsClientSpockMethodBuilderSpec extends Specification implements WireMockStubVerifier {
+
+ def "should generate assertions for simple response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """{
+ "property1": "a",
+ "property2": "b"
+}"""
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$[?(@.property2 == 'b')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#79")
+ def "should generate assertions for simple response body constructed from map with a list"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body(
+ property1: 'a',
+ property2: [
+ [a: 'sth'],
+ [b: 'sthElse']
+ ]
+ )
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$.property2[*][?(@.a == 'sth')]")
+ blockBuilder.toString().contains("\$.property2[*][?(@.b == 'sthElse')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#82")
+ def "should generate proper request when body constructed from map with a list"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ body(
+ items: ['HOP']
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("entity('{\"items\":[\"HOP\"]}', 'application/json')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#88")
+ def "should generate proper request when body constructed from GString"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ body(
+ "property1=VAL1"
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("entity('property1=VAL1', 'application/octet-stream')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for array in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """[
+{
+ "property1": "a"
+},
+{
+ "property2": "b"
+}]"""
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[*][?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$[*][?(@.property2 == 'b')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for array inside response body element"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """{
+ "property1": [
+ { "property2": "test1"},
+ { "property3": "test2"}
+ ]
+}"""
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$.property1[*][?(@.property3 == 'test2')]")
+ blockBuilder.toString().contains("\$.property1[*][?(@.property2 == 'test1')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for nested objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body '''\
+{
+ "property1": "a",
+ "property2": {"property3": "b"}
+}
+'''
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$.property2[?(@.property3 == 'b')]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate regex assertions for map objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body(
+ property1: "a",
+ property2: value(
+ client('123'),
+ server(regex('[0-9]{3}'))
+ )
+ )
+ headers {
+ header('Content-Type': 'application/json')
+
+ }
+
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate regex assertions for string objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body("""{"property1":"a","property2":"${value(client('123'), server(regex('[0-9]{3}')))}"}""")
+ headers {
+ header('Content-Type': 'application/json')
+
+ }
+
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should ignore 'Accept' header and use 'request' method"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ headers {
+ header("Accept", "text/plain")
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("request('text/plain')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should ignore 'Content-Type' header and use 'entity' method"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ headers {
+ header("Content-Type", "text/plain")
+ header("Timer", "123")
+ }
+ body ''
+ }
+ response {
+ status 200
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("entity('', 'text/plain')")
+ blockBuilder.toString().contains("header('Timer', '123')")
+ !blockBuilder.toString().contains("header('Content-Type'")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate a call with an url path and query parameters"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath('/users') {
+ queryParameters {
+ parameter 'limit': $(client(equalTo("20")), server(equalTo("10")))
+ parameter 'offset': $(client(containing("20")), server(equalTo("20")))
+ parameter 'filter': "email"
+ parameter 'sort': equalTo("name")
+ parameter 'search': $(client(notMatching(~/^\/[0-9]{2}$/)), server("55"))
+ parameter 'age': $(client(notMatching("^\\w*\$")), server("99"))
+ parameter 'name': $(client(matching("Denis.*")), server("Denis.Stepanov"))
+ parameter 'email': "bob@email.com"
+ parameter 'hello': $(client(matching("Denis.*")), server(absent()))
+ parameter 'hello': absent()
+ }
+ }
+ }
+ response {
+ status 200
+ body """
+ {
+ "property1": "a",
+ "property2": "b"
+ }
+ """
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains("queryParam('limit', '10'")
+ spockTest.contains("queryParam('offset', '20'")
+ spockTest.contains("queryParam('filter', 'email'")
+ spockTest.contains("queryParam('sort', 'name'")
+ spockTest.contains("queryParam('search', '55'")
+ spockTest.contains("queryParam('age', '99'")
+ spockTest.contains("queryParam('name', 'Denis.Stepanov'")
+ spockTest.contains("queryParam('email', 'bob@email.com'")
+ spockTest.contains('$[?(@.property2 == \'b\')]')
+ spockTest.contains('$[?(@.property1 == \'a\')]')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate test for empty body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ url("/ws/payments")
+ body("")
+ }
+ response {
+ status 406
+ }
+ }
+ JaxRsClientSpockMethodBodyBuilder builder = new JaxRsClientSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains("entity('', 'application/octet-stream')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate test for String in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "POST"
+ url "test"
+ }
+ response {
+ status 200
+ body "test"
+ }
+ }
+ 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"')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+}
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
new file mode 100644
index 0000000000..5e8139172f
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/builder/MockMvcSpockMethodBuilderSpec.groovy
@@ -0,0 +1,773 @@
+package io.codearte.accurest.builder
+
+import io.codearte.accurest.dsl.GroovyDsl
+import io.codearte.accurest.dsl.WireMockStubStrategy
+import io.codearte.accurest.dsl.WireMockStubVerifier
+import spock.lang.Issue
+import spock.lang.Specification
+import spock.lang.Unroll
+
+import java.util.regex.Pattern
+
+/**
+ * @author Jakub Kubrynski
+ */
+class MockMvcSpockMethodBuilderSpec extends Specification implements WireMockStubVerifier {
+
+ def "should generate assertions for simple response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """{
+ "property1": "a",
+ "property2": "b"
+}"""
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$[?(@.property2 == 'b')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#79")
+ def "should generate assertions for simple response body constructed from map with a list"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body(
+ property1: 'a',
+ property2: [
+ [a: 'sth'],
+ [b: 'sthElse']
+ ]
+ )
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$.property2[*][?(@.a == 'sth')]")
+ blockBuilder.toString().contains("\$.property2[*][?(@.b == 'sthElse')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#82")
+ def "should generate proper request when body constructed from map with a list"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ body(
+ items: ['HOP']
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains(".body('{\"items\":[\"HOP\"]}')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue("#88")
+ def "should generate proper request when body constructed from GString"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ body(
+ "property1=VAL1"
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains(".body('property1=VAL1')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for array in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """[
+{
+ "property1": "a"
+},
+{
+ "property2": "b"
+}]"""
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[*][?(@.property1 == 'a')]")
+ blockBuilder.toString().contains("\$[*][?(@.property2 == 'b')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for array inside response body element"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body """{
+ "property1": [
+ { "property2": "test1"},
+ { "property3": "test2"}
+ ]
+}"""
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$.property1[*][?(@.property3 == 'test2')]")
+ blockBuilder.toString().contains("\$.property1[*][?(@.property2 == 'test1')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate assertions for nested objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body '''\
+{
+ "property1": "a",
+ "property2": {"property3": "b"}
+}
+'''
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$.property2[?(@.property3 == 'b')]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate regex assertions for map objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body(
+ property1: "a",
+ property2: value(
+ client('123'),
+ server(regex('[0-9]{3}'))
+ )
+ )
+ headers {
+ header('Content-Type': 'application/json')
+
+ }
+
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate regex assertions for string objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body("""{"property1":"a","property2":"${value(client('123'), server(regex('[0-9]{3}')))}"}""")
+ headers {
+ header('Content-Type': 'application/json')
+
+ }
+
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property2 =~ /[0-9]{3}/)]")
+ blockBuilder.toString().contains("\$[?(@.property1 == 'a')]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue(["#126", "#143"])
+ def "should generate escaped regex assertions for string objects in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "GET"
+ url "test"
+ }
+ response {
+ status 200
+ body("""{"property":" ${value(client('123'), server(regex('\\d+')))}"}""")
+ headers {
+ header('Content-Type': 'application/json')
+ }
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ then:
+ blockBuilder.toString().contains("\$[?(@.property =~ /\\d+/)]")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate a call with an url path and query parameters"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath('/users') {
+ queryParameters {
+ parameter 'limit': $(client(equalTo("20")), server(equalTo("10")))
+ parameter 'offset': $(client(containing("20")), server(equalTo("20")))
+ parameter 'filter': "email"
+ parameter 'sort': equalTo("name")
+ parameter 'search': $(client(notMatching(~/^\/[0-9]{2}$/)), server("55"))
+ parameter 'age': $(client(notMatching("^\\w*\$")), server("99"))
+ parameter 'name': $(client(matching("Denis.*")), server("Denis.Stepanov"))
+ parameter 'email': "bob@email.com"
+ parameter 'hello': $(client(matching("Denis.*")), server(absent()))
+ parameter 'hello': absent()
+ }
+ }
+ }
+ response {
+ status 200
+ body """
+ {
+ "property1": "a",
+ "property2": "b"
+ }
+ """
+ }
+ }
+ 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('$[?(@.property2 == \'b\')]')
+ spockTest.contains('$[?(@.property1 == \'a\')]')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate test for empty body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ url("/ws/payments")
+ body("")
+ }
+ response {
+ status 406
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains(".body('')")
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should generate test for String in response body"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "POST"
+ url "test"
+ }
+ response {
+ status 200
+ body "test"
+ }
+ }
+ 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"')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue('113')
+ def "should generate regex test for String in response header"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url $(client(regex('/partners/[0-9]+/users')), server('/partners/1000/users'))
+ headers { header 'Content-Type': 'application/json' }
+ body(
+ first_name: 'John',
+ last_name: 'Smith',
+ personal_id: '12345678901',
+ phone_number: '500500500',
+ invitation_token: '00fec7141bb94793bfe7ae1d0f39bda0',
+ password: 'john'
+ )
+ }
+ response {
+ status 201
+ headers {
+ header 'Location': $(client('http://localhost/partners/1000/users/1001'), server(regex('http://localhost/partners/[0-9]+/users/[0-9]+')))
+ }
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains('''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ @Issue('115')
+ def "should generate regex with helper method"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url $(client(regex('/partners/[0-9]+/users')), server('/partners/1000/users'))
+ headers { header 'Content-Type': 'application/json' }
+ body(
+ first_name: 'John',
+ last_name: 'Smith',
+ personal_id: '12345678901',
+ phone_number: '500500500',
+ invitation_token: '00fec7141bb94793bfe7ae1d0f39bda0',
+ password: 'john'
+ )
+ }
+ response {
+ status 201
+ headers {
+ header 'Location': $(client('http://localhost/partners/1000/users/1001'), server(regex("^${hostname()}/partners/[0-9]+/users/[0-9]+")))
+ }
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains('''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should work with more complex stuff and jsonpaths"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+ priority 10
+ request {
+ method 'POST'
+ 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 200
+ body(errors: [
+ [property: "bank_account_number", message: "incorrect_format"]
+ ])
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains('''$.errors[*][?(@.property == 'bank_account_number')]''')
+ spockTest.contains('''$.errors[*][?(@.message == 'incorrect_format')]''')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ def "should work properly with GString url"() {
+ given:
+ GroovyDsl contractDsl = GroovyDsl.make {
+
+ request {
+ method 'PUT'
+ url "/partners/${value(client(regex('^[0-9]*$')), server('11'))}/agents/11/customers/09665703Z"
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ first_name: 'Josef',
+ )
+ }
+ response {
+ status 422
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains('''/partners/11/agents/11/customers/09665703Z''')
+ and:
+ stubMappingIsValidWireMockStub(new WireMockStubStrategy(contractDsl).toWireMockClientStub())
+ }
+
+ 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}\\\\]/)]''')
+ }
+
+ @Issue('42')
+ @Unroll
+ def "should not omit the optional field in the test creation"() {
+ given:
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains('''"email":"abc@abc.com"''')
+ spockTest.contains('''parsedJson.read(\'\'\'$[?(@.code =~ /(123123)?/)]''')
+ !spockTest.contains('''REGEXP''')
+ !spockTest.contains('''OPTIONAL''')
+ !spockTest.contains('''OptionalProperty''')
+ where:
+ contractDsl << [
+ GroovyDsl.make {
+ priority 1
+ request {
+ method 'POST'
+ url '/users/password'
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ email: $(stub(optional(regex(email()))), test('abc@abc.com')),
+ callback_url: $(stub(regex(hostname())), test('http://partners.com'))
+ )
+ }
+ response {
+ status 404
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ code: value(stub("123123"), test(optional("123123"))),
+ message: "User not found by email = [${value(test(regex(email())), stub('not.existing@user.com'))}]"
+ )
+ }
+ },
+ GroovyDsl.make {
+ priority 1
+ request {
+ method 'POST'
+ url '/users/password'
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ """ {
+ "email" : "${value(stub(optional(regex(email()))), test('abc@abc.com'))}",
+ "callback_url" : "${value(client(regex(hostname())), server('http://partners.com'))}"
+ }
+ """
+ )
+ }
+ response {
+ status 404
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ """ {
+ "code" : "${value(stub(123123), test(optional(123123)))}",
+ "message" : "User not found by email = [${value(server(regex(email())), client('not.existing@user.com'))}]"
+ }
+ """
+ )
+ }
+ }
+ ]
+ }
+
+ @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'))''')
+ }
+
+ def "should support inner map and list definitions"() {
+ given:
+
+ Pattern PHONE_NUMBER = Pattern.compile(/[+\w]*/)
+ Pattern ANYSTRING = Pattern.compile(/.*/)
+ Pattern NUMBERS = Pattern.compile(/[\d\.]*/)
+ Pattern DATETIME = ANYSTRING
+
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "PUT"
+ url "/v1/payments/e86df6f693de4b35ae648464c5b0dc09/client_data"
+ headers {
+ header('Content-Type': 'application/json')
+ }
+ body(
+ client: [
+ first_name: $(stub(regex(onlyAlphaUnicode())), test('Denis')),
+ last_name: $(stub(regex(onlyAlphaUnicode())), test('FakeName')),
+ email: $(stub(regex(email())), test('fakemail@fakegmail.com')),
+ fax: $(stub(PHONE_NUMBER), test('+xx001213214')),
+ phone: $(stub(PHONE_NUMBER), test('2223311')),
+ data_of_birth: $(stub(DATETIME), test('2002-10-22T00:00:00Z'))
+ ],
+ client_id_card: [
+ id: $(stub(ANYSTRING), test('ABC12345')),
+ date_of_issue: $(stub(ANYSTRING), test('2002-10-02T00:00:00Z')),
+ address: [
+ street: $(stub(ANYSTRING), test('Light Street')),
+ city: $(stub(ANYSTRING), test('Fire')),
+ region: $(stub(ANYSTRING), test('Skys')),
+ country: $(stub(ANYSTRING), test('HG')),
+ zip: $(stub(NUMBERS), test('658965'))
+ ]
+ ],
+ incomes_and_expenses: [
+ monthly_income: $(stub(NUMBERS), test('0.0')),
+ monthly_loan_repayments: $(stub(NUMBERS), test('100')),
+ monthly_living_expenses: $(stub(NUMBERS), test('22'))
+ ],
+ additional_info: [
+ allow_to_contact: $(stub(optional(regex(anyBoolean()))), test('true'))
+ ]
+ )
+ }
+ response {
+ status 200
+ headers {
+ header('Content-Type': 'application/json')
+ }
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ spockTest.contains '"street":"Light Street"'
+ !spockTest.contains("clientValue")
+ !spockTest.contains("cursor")
+ }
+
+
+ def "shouldn't generate unicode escape characters"() {
+ given:
+ Pattern ONLY_ALPHA_UNICODE = Pattern.compile(/[\p{L}]*/)
+
+ GroovyDsl contractDsl = GroovyDsl.make {
+ request {
+ method "PUT"
+ url "/v1/payments/e86df6f693de4b35ae648464c5b0dc09/енев"
+ headers {
+ header('Content-Type': 'application/json')
+ }
+ body(
+ client: [
+ first_name: $(stub(ONLY_ALPHA_UNICODE), test('Пенева')),
+ last_name : $(stub(ONLY_ALPHA_UNICODE), test('Пенева'))
+ ]
+ )
+ }
+ response {
+ status 200
+ headers {
+ header('Content-Type': 'application/json')
+ }
+ }
+ }
+ MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
+ BlockBuilder blockBuilder = new BlockBuilder(" ")
+ when:
+ builder.appendTo(blockBuilder)
+ def spockTest = blockBuilder.toString()
+ then:
+ !spockTest.contains("\\u041f")
+ }
+
+}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy
deleted file mode 100644
index c68a96a1e6..0000000000
--- a/accurest-core/src/test/groovy/io/codearte/accurest/builder/SpockMethodBuilderSpec.groovy
+++ /dev/null
@@ -1,113 +0,0 @@
-package io.codearte.accurest.builder
-
-import io.codearte.accurest.dsl.GroovyDsl
-import spock.lang.Specification
-
-/**
- * @author Jakub Kubrynski
- */
-class SpockMethodBuilderSpec extends Specification {
-
- def "should generate assertions for simple response body"() {
- given:
- GroovyDsl contractDsl = GroovyDsl.make {
- request {
- method "GET"
- url "test"
- }
- response {
- status 200
- body """{
- "property1": "a",
- "property2": "b"
-}"""
- }
- }
- SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(contractDsl)
- BlockBuilder blockBuilder = new BlockBuilder(" ")
- when:
- builder.appendTo(blockBuilder)
- then:
- blockBuilder.toString().contains("responseBody.property1 == \"a\"")
- blockBuilder.toString().contains("responseBody.property2 == \"b\"")
- }
-
- def "should generate assertions for array in response body"() {
- given:
- GroovyDsl contractDsl = GroovyDsl.make {
- request {
- method "GET"
- url "test"
- }
- response {
- status 200
- body """[
-{
- "property1": "a"
-},
-{
- "property2": "b"
-}]"""
- }
- }
- SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(contractDsl)
- BlockBuilder blockBuilder = new BlockBuilder(" ")
- when:
- builder.appendTo(blockBuilder)
- then:
- blockBuilder.toString().contains("responseBody[0].property1 == \"a\"")
- blockBuilder.toString().contains("responseBody[1].property2 == \"b\"")
- }
-
- def "should generate assertions for array inside response body element"() {
- given:
- GroovyDsl contractDsl = GroovyDsl.make {
- request {
- method "GET"
- url "test"
- }
- response {
- status 200
- body """{
- "property1": [
- { "property2": "test1"},
- { "property3": "test2"}
- ]
-}"""
- }
- }
- SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(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\"")
- }
-
- def "should generate assertions for nested objects in response body"() {
- given:
- GroovyDsl contractDsl = GroovyDsl.make {
- request {
- method "GET"
- url "test"
- }
- response {
- status 200
- body '''\
-{
- "property1": "a",
- "property2": {"property3": "b"}
-}
-'''
- }
- }
- SpockMethodBodyBuilder builder = new SpockMethodBodyBuilder(contractDsl)
- BlockBuilder blockBuilder = new BlockBuilder(" ")
- when:
- builder.appendTo(blockBuilder)
- then:
- blockBuilder.toString().contains("responseBody.property1 == \"a\"")
- blockBuilder.toString().contains("responseBody.property2.property3 == \"b\"")
- }
-}
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
new file mode 100755
index 0000000000..7502ada771
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockGroovyDslSpec.groovy
@@ -0,0 +1,1401 @@
+package io.codearte.accurest.dsl
+
+import groovy.json.JsonBuilder
+import groovy.json.JsonSlurper
+import io.codearte.accurest.util.AssertionUtil
+import spock.lang.Issue
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifier {
+
+ def 'should convert groovy dsl stub to wireMock stub for the client side'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(~/\/[0-9]{2}/), server('/12'))
+ }
+ response {
+ status 200
+ body(
+ id: value(
+ client('123'),
+ server({ regex('[0-9]+') })
+ ),
+ surname: $(
+ client('Kowalsky'),
+ server('Lewandowski')
+ ),
+ name: 'Jan',
+ created: $(client('2014-02-02 12:23:43'), server({ currentDate(it) }))
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+ }
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual('''
+ {
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ @Issue("#79")
+ def 'should convert groovy dsl stub to wireMock stub for the client side with a body containing a map'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url '/ingredients'
+ headers {
+ header 'Content-Type': '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]
+ ]
+ )
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual('''
+{
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ @Issue("#86")
+ def 'should convert groovy dsl stub with GString and regexp'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ url('/ws/payments')
+ headers {
+ header("Content-Type": 'application/x-www-form-urlencoded')
+ }
+ body("""paymentType=INCOMING&transferType=BANK&amount=${
+ value(client(regex('[0-9]{3}\\.[0-9]{2}')), server(500.00))
+ }&bookingDate=${
+ value(client(regex('[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])')), server('2015-05-18'))
+ }""")
+ }
+ response {
+ status 204
+ body(
+ paymentId: value(client('4'), server(regex('[1-9][0-9]*'))),
+ foundExistingPayment: false
+ )
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual('''
+{
+ "request": {
+ "method": "POST",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/x-www-form-urlencoded"
+ }
+ },
+ "url": "/ws/payments",
+ "bodyPatterns": [
+ {
+ "matches": "paymentType=INCOMING&transferType=BANK&amount=[0-9]{3}\\\\.[0-9]{2}&bookingDate=[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])"
+ }
+ ]
+ },
+ "response": {
+ "status": 204,
+ "body": "{\\"paymentId\\":\\"4\\",\\"foundExistingPayment\\":false}"
+ }
+}
+''', wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should convert groovy dsl stub with Body as String to wireMock stub for the client side'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(~/\/[0-9]{2}/), server('/12'))
+ }
+ response {
+ status 200
+ body("""\
+ {
+ "id": "${value(client('123'), server('321'))}",
+ "surname": "${value(client('Kowalsky'), server('Lewandowski'))}",
+ "name": "Jan",
+ "created" : "${$(client('2014-02-02 12:23:43'), server('2999-09-09 01:23:45'))}"
+ }
+ """
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+ }
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should convert groovy dsl stub with simple Body as String to wireMock stub for the client side'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(regex('/[0-9]{2}')), server('/12'))
+ body """
+ {
+ "name": "Jan"
+ }
+ """
+ }
+ response {
+ status 200
+ body("""\
+ {
+ "name": "Jan"
+ }
+ """
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+ }
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual('''
+{
+ "request" : {
+ "urlPattern" : "/[0-9]{2}",
+ "method" : "GET",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.name == 'Jan')]"
+ } ]
+ },
+ "response" : {
+ "status" : 200,
+ "body" : "{\\"name\\":\\"Jan\\"}",
+ "headers" : {
+ "Content-Type" : "text/plain"
+ }
+ }
+}
+''', wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should use equalToJson when body match is defined as map'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(~/\/[0-9]{2}/), server('/12'))
+ body(
+ id: value(
+ client('123'),
+ server({ regex('[0-9]+') })
+ ),
+ surname: $(
+ client('Kowalsky'),
+ server('Lewandowski')
+ ),
+ name: 'Jan',
+ created: $(client('2014-02-02 12:23:43'), server({ currentDate(it) }))
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should use equalToJson when content type ends with json'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ headers {
+ header "Content-Type", "customtype/json"
+ }
+ body """
+ {
+ "name": "Jan"
+ }
+ """
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "request" : {
+ "url" : "/users",
+ "method" : "GET",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.name == 'Jan')]"
+ } ],
+ "headers" : {
+ "Content-Type" : {
+ "equalTo" : "customtype/json"
+ }
+ }
+ },
+ "response" : {
+ "status" : 200
+ }
+}
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should use equalToXml when content type ends with xml'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ headers {
+ header "Content-Type", "customtype/xml"
+ }
+ body """${value(client('Jozo'), server('Denis'))}${
+ value(client(""), server('1234567890'))
+ }"""
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "url": "/users",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "customtype/xml"
+ }
+ },
+ "bodyPatterns": [
+ {
+ "equalToXml":"Jozo<test>"
+ }
+ ]
+ },
+ "response": {
+ "status": 200
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should use equalToXml when content type is parsable xml'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ body """${value(client('Jozo'), server('Denis'))}${
+ value(client(""), server('1234567890'))
+ }"""
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "url": "/users",
+ "bodyPatterns": [
+ {
+ "equalToXml":"Jozo<test>"
+ }
+ ]
+ },
+ "response": {
+ "status": 200
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should support xml as a response body'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ }
+ response {
+ status 200
+ body """${value(client('Jozo'), server('Denis'))}${
+ value(client(""), server('1234567890'))
+ }"""
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "url": "/users"
+ },
+ "response": {
+ "status": 200,
+ "body":"Jozo<test>"
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should use equalToJson'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ body equalToJson('''{"name":"Jan"}''')
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "url": "/users",
+ "bodyPatterns": [
+ {
+ "equalToJson":"{\\"name\\":\\"Jan\\"}"
+ }
+ ]
+ },
+ "response": {
+ "status": 200
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should use equalToXml'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url "/users"
+ body equalToXml("""${value(client('Jozo'), server('Denis'))}${
+ value(client(""), server('1234567890'))
+ }""")
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "url": "/users",
+ "bodyPatterns": [
+ {
+ "equalToXml":"Jozo<test>"
+ }
+ ]
+ },
+ "response": {
+ "status": 200
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should convert groovy dsl stub with regexp Body as String to wireMock stub for the client side'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(regex('/[0-9]{2}')), server('/12'))
+ body """
+ {
+ "personalId": "${value(client(regex('^[0-9]{11}$')), server('57593728525'))}"
+ }
+ """
+ }
+ response {
+ status 200
+ body("""\
+ {
+ "name": "Jan"
+ }
+ """
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+ }
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should convert groovy dsl stub with a regexp and an integer in request body'() {
+ given:
+ GroovyDsl groovyDsl = 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: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
+ )
+ headers {
+ header('Content-Type': 'application/vnd.fraud.v1+json')
+ }
+ }
+
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def "should generate request with urlPath and queryParameters for client side"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath($(client("users"), server("items"))) {
+ queryParameters {
+ parameter 'limit': $(client(equalTo("20")), server("10"))
+ parameter 'offset': $(client(containing("10")), server("10"))
+ parameter 'filter': "email"
+ parameter 'sort': $(client(~/^[0-9]{10}$/), server("1234567890"))
+ parameter 'search': $(client(notMatching(~/^\/[0-9]{2}$/)), server("10"))
+ parameter 'age': $(client(notMatching("^\\w*\$")), server(10))
+ parameter 'name': $(client(matching("Denis.*")), server("Denis"))
+ parameter 'credit': absent()
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "urlPath": "users",
+ "queryParameters": {
+ "offset": {
+ "contains": "10"
+ },
+ "limit": {
+ "equalTo": "20"
+ },
+ "filter": {
+ "equalTo": "email"
+ },
+ "sort": {
+ "matches": "^[0-9]{10}$"
+ },
+ "search": {
+ "doesNotMatch": "^/[0-9]{2}$"
+ },
+ "age": {
+ "doesNotMatch": "^\\\\w*$"
+ },
+ "name": {
+ "matches": "Denis.*"
+ },
+ "credit": {
+ "absent": true
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def "should generate request with urlPath for client side"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath $(client("boxes"), server("items"))
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "urlPath": "boxes"
+ },
+ "response": {
+ "status": 200,
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def "should generate simple request with urlPath for client side"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath "boxes"
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "urlPath": "boxes"
+ },
+ "response": {
+ "status": 200,
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def "should not allow regexp in url for server value"() {
+ when:
+ GroovyDsl.make {
+ request {
+ method 'GET'
+ url(regex(/users\/[0-9]*/)) {
+ queryParameters {
+ parameter 'age': notMatching("^\\w*\$")
+ parameter 'name': matching("Denis.*")
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ then:
+ def e = thrown(IllegalStateException)
+ e.message.contains "Url can't be a pattern for the server side"
+ }
+
+ def "should not allow regexp in query parameter for server value"() {
+ when:
+ GroovyDsl.make {
+ request {
+ method 'GET'
+ url("abc") {
+ queryParameters {
+ parameter 'age': $(client(notMatching("^\\w*\$")), server(regex(".*")))
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ then:
+ def e = thrown(IllegalStateException)
+ e.message.contains "Query parameter 'age' can't be a pattern for the server side"
+ }
+
+ def "should not allow query parameter unresolvable for a server value"() {
+ when:
+ GroovyDsl.make {
+ request {
+ method 'GET'
+ urlPath("users") {
+ queryParameters {
+ parameter 'age': notMatching("^\\w*\$")
+ parameter 'name': matching("Denis.*")
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ then:
+ def e = thrown(IllegalStateException)
+ e.message.contains "Query parameter 'age' can't be of a matching type: NOT_MATCHING for the server side"
+ }
+
+ def "should not allow query parameter with a different absent variation for server/client"() {
+ when:
+ GroovyDsl.make dsl
+ then:
+ def e = thrown(IllegalStateException)
+ e.message.contains "Absent cannot only be used only on one side"
+ where:
+ dsl << [
+ {
+ request {
+ method 'GET'
+ urlPath("users") {
+ queryParameters {
+ parameter 'name': $(client(absent()), server(""))
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ },
+ {
+ request {
+ method 'GET'
+ urlPath("users") {
+ queryParameters {
+ parameter 'name': $(client(""), server(absent()))
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ },
+ {
+ request {
+ method 'GET'
+ urlPath("users") {
+ queryParameters {
+ parameter 'name': $(client(absent()), server(matching("abc")))
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ ]
+ }
+
+ def "should generate request with url and queryParameters for client side"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'GET'
+ url($(client(regex(/users\/[0-9]*/)), server("users/123"))) {
+ queryParameters {
+ parameter 'age': $(client(notMatching("^\\w*\$")), server(10))
+ parameter 'name': $(client(matching("Denis.*")), server("Denis"))
+ }
+ }
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "GET",
+ "urlPattern": "users/[0-9]*",
+ "queryParameters": {
+ "age": {
+ "doesNotMatch": "^\\\\w*$"
+ },
+ "name": {
+ "matches": "Denis.*"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ }
+ }
+ '''), json)
+ and:
+ stubMappingIsValidWireMockStub(json)
+ }
+
+ def 'should convert groovy dsl stub with rich tree Body as String to wireMock stub for the client side'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('GET')
+ url $(client(~/\/[0-9]{2}/), server('/12'))
+ body """\
+ {
+ "personalId": "${value(client(regex('[0-9]{11}')), server('57593728525'))}",
+ "firstName": "${value(client(regex('.*')), server('Bruce'))}",
+ "lastName": "${value(client(regex('.*')), server('Lee'))}",
+ "birthDate": "${value(client(regex('[0-9]{4}-[0-9]{2}-[0-9]{2}')), server('1985-12-12'))}",
+ "errors": [
+ {
+ "propertyName": "${value(client(regex('[0-9]{2}')), server('04'))}",
+ "providerValue": "Test"
+ },
+ {
+ "propertyName": "${value(client(regex('[0-9]{2}')), server('08'))}",
+ "providerValue": "Test"
+ }
+ ]
+ }
+ """
+ }
+ response {
+ status 200
+ body("""\
+ {
+ "name": "Jan"
+ }
+ """
+ )
+ headers {
+ header 'Content-Type': 'text/plain'
+ }
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ }
+
+ def 'should use regexp matches when request body match is defined using a map with a pattern'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method 'POST'
+ url '/reissue-payment-order'
+ body(
+ loanNumber: "999997001",
+ amount: value(client(regex('[0-9.]+')), server('100.00')),
+ currency: "DKK",
+ applicationName: value(client(regex('.*')), server("Auto-Repayments")),
+ username: value(client(regex('.*')), server("scheduler")),
+ cardId: 1
+ )
+ }
+ response {
+ status 200
+ body '''
+ {
+ "status": "OK"
+ }
+ '''
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "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)
+ }
+
+ def "should generate stub for empty body"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ url("test")
+ body("")
+ }
+ response {
+ status 406
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "POST",
+ "url": "test",
+ "bodyPatterns": [
+ {
+ "equalTo": ""
+ }
+ ]
+ },
+ "response": {
+ "status": 406
+ }
+ }
+'''), json)
+ }
+
+ def "should generate stub with priority"() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ priority 9
+ request {
+ method('POST')
+ url("test")
+ }
+ response {
+ status 406
+ }
+ }
+ when:
+ def json = toWireMockClientJsonStub(groovyDsl)
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "priority": 9,
+ "request": {
+ "method": "POST",
+ "url": "test"
+ },
+ "response": {
+ "status": 406
+ }
+ }
+ '''), json)
+ }
+
+ @Issue("#127")
+ def 'should use "test" as an alias for "server"'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ body(
+ property: value(stub("value"), test("value"))
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+{
+ "request" : {
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.property == 'value')]"
+ } ]
+ },
+ "response" : {
+ "status" : 200
+ }
+}
+ '''), wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ @Issue("#121")
+ def 'should generate stub with empty list as a value of a field'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+ request {
+ method('POST')
+ body(
+ values: []
+ )
+ }
+ response {
+ status 200
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request": {
+ "method": "POST",
+ "bodyPatterns": [
+ {
+ "equalToJson": "{\\"values\\":[]}"
+ }
+ ]
+ },
+ "response": {
+ "status": 200
+ }
+ }
+ '''), wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should generate stub properly resolving GString with regular expression'() {
+ given:
+ GroovyDsl groovyDsl = 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'))}]"
+ )
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request" : {
+ "url" : "/users/password",
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.callback_url =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]"
+ }, {
+ "matchesJsonPath" : "$[?(@.email =~ /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}/)]"
+ } ],
+ "headers" : {
+ "Content-Type" : {
+ "equalTo" : "application/json"
+ }
+ }
+ },
+ "response" : {
+ "status" : 404,
+ "body" : "{\\"code\\":4,\\"message\\":\\"User not found by email = [not.existing@user.com]\\"}",
+ "headers" : {
+ "Content-Type" : "application/json"
+ }
+ },
+ "priority" : 1
+ }
+ '''), wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ def 'should generate stub properly resolving GString with regular expression in url'() {
+ given:
+ GroovyDsl groovyDsl = GroovyDsl.make {
+
+ request {
+ method 'PUT'
+ url "/partners/${value(client(regex('^[0-9]*$')), server('11'))}/agents/11/customers/09665703Z"
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ first_name: 'Josef',
+ )
+ }
+ response {
+ status 422
+ }
+ }
+ when:
+ String wireMockStub = new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request" : {
+ "urlPattern" : "/partners/^[0-9]*$/agents/11/customers/09665703Z",
+ "method" : "PUT",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.first_name == 'Josef')]"
+ } ],
+ "headers" : {
+ "Content-Type" : {
+ "equalTo" : "application/json"
+ }
+ }
+ },
+ "response" : {
+ "status" : 422
+ }
+ }
+ '''), wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ }
+
+ @Issue('42')
+ @Unroll
+ def 'should generate stub without optional parameters'() {
+ when:
+ String wireMockStub = new WireMockStubStrategy(contractDsl).toWireMockClientStub()
+ then:
+ AssertionUtil.assertThatJsonsAreEqual(('''
+ {
+ "request" : {
+ "url" : "/users/password",
+ "method" : "POST",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "$[?(@.callback_url =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]"
+ }, {
+ "matchesJsonPath" : "$[?(@.email =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})?/)]"
+ } ],
+ "headers" : {
+ "Content-Type" : {
+ "equalTo" : "application/json"
+ }
+ }
+ },
+ "response" : {
+ "status" : 404,
+ "body" : "{\\"code\\":\\"123123\\",\\"message\\":\\"User not found by email = [not.existing@user.com]\\"}",
+ "headers" : {
+ "Content-Type" : "application/json"
+ }
+ },
+ "priority" : 1
+ }
+ '''), wireMockStub)
+ and:
+ stubMappingIsValidWireMockStub(wireMockStub)
+ where:
+ contractDsl << [
+ GroovyDsl.make {
+ priority 1
+ request {
+ method 'POST'
+ url '/users/password'
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ email: $(stub(optional(regex(email()))), test('abc@abc.com')),
+ callback_url: $(stub(regex(hostname())), test('http://partners.com'))
+ )
+ }
+ response {
+ status 404
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ code: $(stub("123123"), test(optional("123123"))),
+ message: "User not found by email = [${value(test(regex(email())), stub('not.existing@user.com'))}]"
+ )
+ }
+ },
+ GroovyDsl.make {
+ priority 1
+ request {
+ method 'POST'
+ url '/users/password'
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ """ {
+ "email" : "${value(stub(optional(regex(email()))), test('abc@abc.com'))}",
+ "callback_url" : "${value(client(regex(hostname())), server('http://partners.com'))}"
+ }
+ """
+ )
+ }
+ response {
+ status 404
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body(
+ """ {
+ "code" : "${value(stub(123123), test(optional(123123)))}",
+ "message" : "User not found by email = [${value(server(regex(email())), client('not.existing@user.com'))}]"
+ }
+ """
+ )
+ }
+ }
+ ]
+ }
+
+ String toJsonString(value) {
+ new JsonBuilder(value).toPrettyString()
+ }
+
+ Object parseJson(json) {
+ new JsonSlurper().parseText(json)
+ }
+
+ String toWireMockClientJsonStub(groovyDsl) {
+ new WireMockStubStrategy(groovyDsl).toWireMockClientStub()
+ }
+}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockStubVerifier.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockStubVerifier.groovy
new file mode 100644
index 0000000000..537fb78ea2
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WireMockStubVerifier.groovy
@@ -0,0 +1,16 @@
+package io.codearte.accurest.dsl
+import com.github.tomakehurst.wiremock.stubbing.StubMapping
+
+import java.util.regex.Pattern
+
+trait WireMockStubVerifier {
+
+ void stubMappingIsValidWireMockStub(String mappingDefinition) {
+ StubMapping stubMapping = StubMapping.buildFrom(mappingDefinition)
+ stubMapping.request.bodyPatterns.findAll { it.matches }.every {
+ Pattern.compile(it.matches)
+ }
+ assert !mappingDefinition.contains('io.codearte.accurest.dsl.internal')
+ }
+
+}
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 13299ceebe..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
deleted file mode 100755
index 4ff7fa09f5..0000000000
--- a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockGroovyDslSpec.groovy
+++ /dev/null
@@ -1,289 +0,0 @@
-package io.codearte.accurest.dsl
-import groovy.json.JsonSlurper
-
-class WiremockGroovyDslSpec extends WiremockSpec {
-
- def 'should convert groovy dsl stub to wiremock stub for the client side'() {
- given:
- GroovyDsl groovyDsl = GroovyDsl.make {
- request {
- method('GET')
- url $(client(~/\/[0-9]{2}/), server('/12'))
- }
- response {
- status 200
- body(
- id: value(
- client('123'),
- server({ regex('[0-9]+') })
- ),
- surname: $(
- client('Kowalsky'),
- server('Lewandowski')
- ),
- name: 'Jan',
- created: $(client('2014-02-02 12:23:43'), server({ currentDate(it) }))
- )
- headers {
- header 'Content-Type': 'text/plain'
- }
- }
- }
- 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"
- }
- }
-}
-''')
- and:
- stubMappingIsValidWiremockStub(wiremockStub)
- }
-
- def 'should convert groovy dsl stub with Body as String to wiremock stub for the client side'() {
- given:
- GroovyDsl groovyDsl = GroovyDsl.make {
- request {
- method('GET')
- url $(client(~/\/[0-9]{2}/), server('/12'))
- }
- response {
- status 200
- body("""\
- {
- "id": "${value(client('123'), server('321'))}",
- "surname": "${value(client('Kowalsky'), server('Lewandowski'))}",
- "name": "Jan",
- "created" : "${$(client('2014-02-02 12:23:43'), server('2999-09-09 01:23:45'))}"
- }
- """
- )
- headers {
- header 'Content-Type': 'text/plain'
- }
- }
- }
- 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": "{\\"created\\":\\"2014-02-02 12:23:43\\",\\"id\\":\\"123\\",\\"name\\":\\"Jan\\",\\"surname\\":\\"Kowalsky\\"}",
- "headers": {
- "Content-Type": "text/plain"
- }
- }
-}
-''')
- and:
- stubMappingIsValidWiremockStub(wiremockStub)
- }
-
- def 'should convert groovy dsl stub with simple Body as String to wiremock stub for the client side'() {
- given:
- GroovyDsl groovyDsl = GroovyDsl.make {
- request {
- method('GET')
- url $(client(regex('/[0-9]{2}')), server('/12'))
- body """
- {
- "name": "Jan"
- }
- """
- }
- response {
- status 200
- body("""\
- {
- "name": "Jan"
- }
- """
- )
- headers {
- header 'Content-Type': 'text/plain'
- }
- }
- }
- when:
- String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
- then:
- new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
-{
- "request": {
- "method": "GET",
- "urlPattern": "/[0-9]{2}",
- "bodyPatterns": [
- {
- "equalTo":"{\\"name\\":\\"Jan\\"}"
- }
- ]
- },
- "response": {
- "status": 200,
- "body": "{\\"name\\":\\"Jan\\"}",
- "headers": {
- "Content-Type": "text/plain"
- }
- }
-}
-''')
- and:
- stubMappingIsValidWiremockStub(wiremockStub)
- }
-
-
- def 'should convert groovy dsl stub with regexp Body as String to wiremock stub for the client side'() {
- given:
- GroovyDsl groovyDsl = GroovyDsl.make {
- request {
- method('GET')
- url $(client(regex('/[0-9]{2}')), server('/12'))
- body """
- {
- "personalId": "${value(client(regex('^[0-9]{11}$')), server('57593728525'))}"
- }
- """
- }
- response {
- status 200
- body("""\
- {
- "name": "Jan"
- }
- """
- )
- headers {
- header 'Content-Type': 'text/plain'
- }
- }
- }
- when:
- String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
- then:
- new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
-{
- "request": {
- "method": "GET",
- "urlPattern": "/[0-9]{2}",
- "bodyPatterns": [
- {
- "matches":"{\\"personalId\\":\\"^[0-9]{11}$\\"}"
- }
- ]
- },
- "response": {
- "status": 200,
- "body": "{\\"name\\":\\"Jan\\"}",
- "headers": {
- "Content-Type": "text/plain"
- }
- }
-}
-''')
- 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 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.*$"
- }
- }
- }
- ''')
- }
-}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockSpec.groovy
deleted file mode 100644
index 2a6237d89d..0000000000
--- a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/WiremockSpec.groovy
+++ /dev/null
@@ -1,12 +0,0 @@
-package io.codearte.accurest.dsl
-
-import com.github.tomakehurst.wiremock.stubbing.StubMapping
-import spock.lang.Specification
-
-class WiremockSpec extends Specification {
-
- void stubMappingIsValidWiremockStub(String mappingDefinition) {
- StubMapping.buildFrom(mappingDefinition)
- }
-
-}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/ExecutionPropertySpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/ExecutionPropertySpec.groovy
index d8660a8433..35e0fbe83a 100644
--- a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/ExecutionPropertySpec.groovy
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/ExecutionPropertySpec.groovy
@@ -4,16 +4,16 @@ import spock.lang.Specification
class ExecutionPropertySpec extends Specification {
- def 'should insert passed value in place of $it placeholder'() {
- given:
- String commandToExecute = 'commandToExecute($it)'
- ExecutionProperty executionProperty = new ExecutionProperty(commandToExecute)
- and:
- String valueToInsert = 'someObject.itsValue'
- when:
- String commandWithInsertedValue = executionProperty.insertValue(valueToInsert)
- then:
- 'commandToExecute(someObject.itsValue)' == commandWithInsertedValue
- }
+ def 'should insert passed value in place of $it placeholder'() {
+ given:
+ String commandToExecute = 'commandToExecute($it)'
+ ExecutionProperty executionProperty = new ExecutionProperty(commandToExecute)
+ and:
+ String valueToInsert = 'someObject.itsValue'
+ when:
+ String commandWithInsertedValue = executionProperty.insertValue(valueToInsert)
+ then:
+ 'commandToExecute(someObject.itsValue)' == commandWithInsertedValue
+ }
}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/RegexPatternsSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/RegexPatternsSpec.groovy
new file mode 100644
index 0000000000..bc217f336e
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/dsl/internal/RegexPatternsSpec.groovy
@@ -0,0 +1,68 @@
+package io.codearte.accurest.dsl.internal
+
+import spock.lang.Specification
+import spock.lang.Unroll
+
+import java.util.regex.Pattern
+
+class RegexPatternsSpec extends Specification {
+
+ RegexPatterns regexPatterns = new RegexPatterns()
+
+ @Unroll
+ def "should generate a regex for ip address [#textToMatch] that is a match [#shouldMatch]"() {
+ expect:
+ shouldMatch == Pattern.compile(regexPatterns.ipAddress()).matcher(textToMatch).matches()
+ where:
+ textToMatch || shouldMatch
+ '123.123.123.123' || true
+ 'a.b.' || false
+ }
+
+ @Unroll
+ def "should generate a regex for hostname [#textToMatch] that is a match [#shouldMatch]"() {
+ expect:
+ shouldMatch == Pattern.compile(regexPatterns.hostname()).matcher(textToMatch).matches()
+ where:
+ textToMatch || shouldMatch
+ 'https://asd.com' || true
+ 'https://asd.com:8080' || true
+ 'https://localhost' || true
+ 'https://localhost:8080' || true
+ 'https://asd.com/asd' || false
+ 'asd.com' || false
+ }
+
+ @Unroll
+ def "should generate a regex for email [#textToMatch] that is a match [#shouldMatch]"() {
+ expect:
+ shouldMatch == Pattern.compile(regexPatterns.email()).matcher(textToMatch).matches()
+ where:
+ textToMatch || shouldMatch
+ 'asd@asd.com' || true
+ 'a.b.' || false
+ }
+
+ @Unroll
+ def "should generate a regex for url [#textToMatch] that is a match [#shouldMatch]"() {
+ expect:
+ shouldMatch == Pattern.compile(regexPatterns.url()).matcher(textToMatch).matches()
+ where:
+ textToMatch || shouldMatch
+ 'ftp://asd.com:9090/asd/a?a=b' || true
+ 'a.b.' || false
+ }
+
+ @Unroll
+ def "should generate a regex for a number [#textToMatch] that is a match [#shouldMatch]"() {
+ expect:
+ shouldMatch == Pattern.compile(regexPatterns.number()).matcher(textToMatch).matches()
+ where:
+ textToMatch || shouldMatch
+ '1' || true
+ '1.0' || true
+ '0.1' || true
+ '.1' || true
+ '1.' || false
+ }
+}
diff --git a/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonToJsonPathsConverterSpec.groovy b/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonToJsonPathsConverterSpec.groovy
new file mode 100644
index 0000000000..5348c77fd5
--- /dev/null
+++ b/accurest-core/src/test/groovy/io/codearte/accurest/util/JsonToJsonPathsConverterSpec.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 JsonToJsonPathsConverterSpec extends Specification {
+
+ @Unroll
+ def 'should convert a json with list as root to a map of path to value'() {
+ when:
+ JsonPaths pathAndValues = JsonToJsonPathsConverter.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 = JsonToJsonPathsConverter.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 = JsonToJsonPathsConverter.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 = JsonToJsonPathsConverter.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 = JsonToJsonPathsConverter.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-core/src/test/resources/dsl/basic/sampleDsl.groovy b/accurest-core/src/test/resources/dsl/basic/sampleDsl.groovy
index 95d19e6b87..4405a9920e 100644
--- a/accurest-core/src/test/resources/dsl/basic/sampleDsl.groovy
+++ b/accurest-core/src/test/resources/dsl/basic/sampleDsl.groovy
@@ -5,23 +5,23 @@ io.codearte.accurest.dsl.GroovyDsl.make {
header 'Content-Type': 'application/json'
}
body("""\
- {
- "name": "Jan",
- "id": "${value(client('abc'), server('def'))}",
- }
- """
+ {
+ "name": "Jan",
+ "id": "${value(client('abc'), server('def'))}",
+ }
+ """
)
url $(client('/[0-9]{2}'), server('/12'))
}
response {
status 200
body("""\
- {
- "name": "Jan",
- "id": "${value(client('123'), server('321'))}",
+ {
+ "name": "Jan",
+ "id": "${value(client('123'), server('321'))}",
"surname": "${value(client('Kowalsky'), server('$checkIfSurnameValid($value)'))}"
- }
- """
+ }
+ """
)
headers {
header 'Content-Type': 'text/plain'
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 cee3f48357..11a86d33c9 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
@@ -11,7 +12,7 @@ import org.gradle.api.Task
class AccurestGradlePlugin implements Plugin {
private static final String GENERATE_SERVER_TESTS_TASK_NAME = 'generateAccurest'
- private static final String DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWiremockClientStubs'
+ private static final String DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWireMockClientStubs'
private static final Class IDEA_PLUGIN_CLASS = org.gradle.plugins.ide.idea.IdeaPlugin
private static final String GROUP_NAME = "Verification"
@@ -27,7 +28,9 @@ class AccurestGradlePlugin implements Plugin {
setConfigurationDefaults(extension)
createGenerateTestsTask(extension)
- createAndConfigureGenerateWiremockClientStubsFromDslTask(extension)
+ createAndConfigureGenerateWireMockClientStubsFromDslTask(extension)
+ deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask()
+ project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.0.5-beta")
project.afterEvaluate {
def hasIdea = project.plugins.findPlugin(IDEA_PLUGIN_CLASS)
@@ -60,13 +63,21 @@ class AccurestGradlePlugin implements Plugin {
}
}
- private void createAndConfigureGenerateWiremockClientStubsFromDslTask(AccurestConfigProperties extension) {
- Task task = project.tasks.create(DSL_TO_WIREMOCK_CLIENT_TASK_NAME, GenerateWiremockClientStubsFromDslTask)
- task.description = "Generate Wiremock client stubs from GroovyDSL"
+ private void createAndConfigureGenerateWireMockClientStubsFromDslTask(AccurestConfigProperties extension) {
+ Task task = project.tasks.create(DSL_TO_WIREMOCK_CLIENT_TASK_NAME, GenerateWireMockClientStubsFromDslTask)
+ task.description = "Generate WireMock client stubs from GroovyDSL"
task.group = GROUP_NAME
task.conventionMapping.with {
contractsDslDir = { extension.contractsDslDir }
stubsOutputDir = { extension.stubsOutputDir }
}
}
+
+ private void deprecatedCreateAndConfigureGenerateWiremockClientStubsFromDslTask() {
+ Task task = project.tasks.create('generateWiremockClientStubs')
+ task.dependsOn('generateWireMockClientStubs')
+ task.description = "DEPRECATED - Generates WireMock client stubs. - DEPRECATED - use 'generateWireMockClientStubs' task"
+ task.group = GROUP_NAME
+ task.doFirst {logger.warn("DEPRECATION WARNING. Task 'generateWiremockClientStubs' is deprecated. Use 'generateWireMockClientStubs' task instead.")}
+ }
}
diff --git a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWiremockClientStubsFromDslTask.groovy b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWireMockClientStubsFromDslTask.groovy
similarity index 63%
rename from accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWiremockClientStubsFromDslTask.groovy
rename to accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWireMockClientStubsFromDslTask.groovy
index 6a6f08f692..be22c44def 100644
--- a/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWiremockClientStubsFromDslTask.groovy
+++ b/accurest-gradle-plugin/src/main/groovy/io/codearte/accurest/plugin/GenerateWireMockClientStubsFromDslTask.groovy
@@ -1,6 +1,6 @@
package io.codearte.accurest.plugin
-import io.codearte.accurest.wiremock.DslToWiremockClientConverter
+import io.codearte.accurest.wiremock.DslToWireMockClientConverter
import io.codearte.accurest.wiremock.RecursiveFilesConverter
import org.gradle.api.internal.ConventionTask
import org.gradle.api.tasks.InputDirectory
@@ -8,7 +8,7 @@ import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
//TODO: Implement as an incremental task: https://gradle.org/docs/current/userguide/custom_tasks.html#incremental_tasks ?
-class GenerateWiremockClientStubsFromDslTask extends ConventionTask {
+class GenerateWireMockClientStubsFromDslTask extends ConventionTask {
@InputDirectory
File contractsDslDir
@@ -17,10 +17,10 @@ class GenerateWiremockClientStubsFromDslTask extends ConventionTask {
@TaskAction
void generate() {
- project.logger.info("Accurest Plugin: Invoking GroovyDSL to Wiremock client stubs conversion")
- project.logger.debug("From '${getContractsDslDir()}' to '${getStubsOutputDir()}'")
+ logger.info("Accurest Plugin: Invoking GroovyDSL to WireMock client stubs conversion")
+ logger.debug("From '${getContractsDslDir()}' to '${getStubsOutputDir()}'")
- RecursiveFilesConverter converter = new RecursiveFilesConverter(new DslToWiremockClientConverter(), getContractsDslDir(),
+ RecursiveFilesConverter converter = new RecursiveFilesConverter(new DslToWireMockClientConverter(), getContractsDslDir(),
getStubsOutputDir())
converter.processFiles()
}
diff --git a/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/BasicFunctionalSpec.groovy b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/BasicFunctionalSpec.groovy
index e2ee36959d..a54d20308e 100755
--- a/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/BasicFunctionalSpec.groovy
+++ b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/BasicFunctionalSpec.groovy
@@ -1,6 +1,6 @@
package io.codearte.accurest.plugin
-import groovy.json.JsonSlurper
+import io.codearte.accurest.util.AssertionUtil
import nebula.test.IntegrationSpec
import spock.lang.Stepwise
@@ -23,7 +23,7 @@ class BasicFunctionalSpec extends IntegrationSpec {
when:
def result = runTasksSuccessfully('check')
then:
- result.wasExecuted(":generateWiremockClientStubs")
+ result.wasExecuted(":generateWireMockClientStubs")
result.wasExecuted(":generateAccurest")
and: "tests generated"
@@ -38,28 +38,29 @@ class BasicFunctionalSpec extends IntegrationSpec {
def "should generate valid client json stubs for simple input"() {
when:
- runTasksSuccessfully('generateWiremockClientStubs')
+ runTasksSuccessfully('generateWireMockClientStubs')
then:
def generatedClientJsonStub = file(GENERATED_CLIENT_JSON_STUB).text
- new JsonSlurper().parseText(generatedClientJsonStub) == new JsonSlurper().parseText("""
-{
- "request": {
- "method": "PUT",
- "headers": {
- "Content-Type": {
- "equalTo": "application/json"
- }
- },
- "url": "/api/12",
- "bodyPatterns": [
- { "equalTo": "[{\\"text\\":\\"Gonna see you at Warsaw\\"}]" }
- ]
- },
- "response": {
- "status": 200
- }
-}
-""")
+ AssertionUtil.assertThatJsonsAreEqual("""
+ {
+ "request" : {
+ "url" : "/api/12",
+ "method" : "PUT",
+ "bodyPatterns" : [ {
+ "matchesJsonPath" : "\$[*][?(@.text == 'Gonna see you at Warsaw')]"
+ } ],
+ "headers" : {
+ "Content-Type" : {
+ "equalTo" : "application/json"
+ }
+ }
+ },
+ "response" : {
+ "status" : 200
+ },
+ "priority" : 2
+ }
+ """, generatedClientJsonStub)
}
def "tasks should be up-to-date when appropriate"() {
@@ -67,16 +68,16 @@ class BasicFunctionalSpec extends IntegrationSpec {
assert !fileExists(GENERATED_CLIENT_JSON_STUB)
assert !fileExists(TEST_EXECUTION_XML_REPORT)
when:
- runTasksSuccessfully('generateWiremockClientStubs', 'generateAccurest')
+ runTasksSuccessfully('generateWireMockClientStubs', 'generateAccurest')
then:
fileExists(GENERATED_CLIENT_JSON_STUB)
fileExists(GENERATED_TEST)
when: "running generation without change inputs"
- def secondExecutionResult = runTasksSuccessfully('generateWiremockClientStubs', 'generateAccurest')
+ def secondExecutionResult = runTasksSuccessfully('generateWireMockClientStubs', 'generateAccurest')
then: "tasks should be up-to-date"
- secondExecutionResult.wasUpToDate(":generateWiremockClientStubs")
+ secondExecutionResult.wasUpToDate(":generateWireMockClientStubs")
secondExecutionResult.wasUpToDate(":generateAccurest")
when: "inputs changed"
@@ -84,10 +85,10 @@ class BasicFunctionalSpec extends IntegrationSpec {
groovyDslFile.text = groovyDslFile.text.replace("200", "599")
and: "tasks run"
- def thirdExecutionResult = runTasksSuccessfully('generateWiremockClientStubs', 'generateAccurest')
+ def thirdExecutionResult = runTasksSuccessfully('generateWireMockClientStubs', 'generateAccurest')
then: "tasks should be reexecuted"
- thirdExecutionResult.wasExecuted(":generateWiremockClientStubs")
+ thirdExecutionResult.wasExecuted(":generateWireMockClientStubs")
thirdExecutionResult.wasExecuted(":generateAccurest")
and: "changes visible in generate files"
diff --git a/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleJerseyProjectSpec.groovy b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleJerseyProjectSpec.groovy
new file mode 100755
index 0000000000..789d897199
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleJerseyProjectSpec.groovy
@@ -0,0 +1,21 @@
+package io.codearte.accurest.plugin
+
+import nebula.test.IntegrationSpec
+import spock.lang.Stepwise
+
+@Stepwise
+class SampleJerseyProjectSpec extends IntegrationSpec {
+
+ void setup() {
+ copyResources("functionalTest/sampleJerseyProject", "")
+ runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
+ }
+
+ def "should pass basic flow"() {
+ given:
+ assert fileExists('build.gradle')
+ expect:
+ runTasksSuccessfully('check')
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleProjectSpec.groovy b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleProjectSpec.groovy
new file mode 100755
index 0000000000..e32b8810f4
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/groovy/io/codearte/accurest/plugin/SampleProjectSpec.groovy
@@ -0,0 +1,21 @@
+package io.codearte.accurest.plugin
+
+import nebula.test.IntegrationSpec
+import spock.lang.Stepwise
+
+@Stepwise
+class SampleProjectSpec extends IntegrationSpec {
+
+ void setup() {
+ copyResources("functionalTest/sampleProject", "")
+ runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
+ }
+
+ def "should pass basic flow"() {
+ given:
+ assert fileExists('build.gradle')
+ expect:
+ runTasksSuccessfully('check')
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle
index 1241194253..e7565e3efe 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle
@@ -1,75 +1,66 @@
buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath "io.codearte.accurest:accurest-gradle-plugin:$accurestVersion"
- }
+ repositories {
+ mavenCentral()
+ }
}
apply plugin: 'groovy'
apply plugin: 'accurest'
ext {
- contractsDir = file("${project.rootDir}/repository/mappings/com/ofg/twitter-places-analyzer")
- wiremockStubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
- wiremockStubsOutputDir = new File(wiremockStubsOutputDirRoot, 'repository/mappings/')
+ contractsDir = file("${project.rootDir}/repository/mappings/com/ofg/twitter-places-analyzer")
+ wireMockStubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
+ wireMockStubsOutputDir = new File(wireMockStubsOutputDirRoot, 'repository/mappings/')
}
configurations {
- all {
- resolutionStrategy {
- eachDependency { DependencyResolveDetails details ->
- // To prevent an accidental usage of groovy-all.jar and groovy.jar in different versions
- // all modularized Groovy jars are replaced with groovy-all.jar by default.
- if (details.requested.group == 'org.codehaus.groovy' && details.requested.name != "groovy-all") {
- details.useTarget("org.codehaus.groovy:groovy-all:${details.requested.version}")
- }
- }
- }
- }
+ all {
+ resolutionStrategy {
+ eachDependency { DependencyResolveDetails details ->
+ // To prevent an accidental usage of groovy-all.jar and groovy.jar in different versions
+ // all modularized Groovy jars are replaced with groovy-all.jar by default.
+ if (details.requested.group == 'org.codehaus.groovy' && details.requested.name != "groovy-all") {
+ details.useTarget("org.codehaus.groovy:groovy-all:${details.requested.version}")
+ }
+ }
+ }
+ }
}
repositories {
- mavenCentral()
+ mavenCentral()
}
dependencies {
- compile "org.springframework:spring-web:$springVersion"
- compile "org.springframework:spring-context-support:$springVersion"
- compile "org.codehaus.groovy:groovy-all:2.4.1"
- compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4'
- compile "org.codehaus.jackson:jackson-mapper-asl:$jacksonMapper"
- compile "org.codehaus.jackson:jackson-core-asl:$jacksonMapper"
- compile 'com.jayway.jsonpath:json-path-assert:1.2.0'
+ compile "org.springframework:spring-web:$springVersion"
+ compile "org.springframework:spring-context-support:$springVersion"
+ compile "org.codehaus.groovy:groovy-all:2.4.5"
+ compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4'
+ compile 'com.jayway.jsonpath:json-path-assert:2.0.0'
- testCompile('com.github.tomakehurst:wiremock:1.53') {
- exclude group: 'org.mortbay.jetty', module: 'servlet-api'
- }
- testCompile "org.spockframework:spock-spring:0.7-groovy-2.0"
- testCompile "com.jayway.restassured:rest-assured:$restAssuredVersion"
- testCompile "com.jayway.restassured:spring-mock-mvc:$restAssuredVersion"
- testCompile "io.codearte.accurest:accurest-core:$accurestVersion"
- testCompile "javax.servlet:javax.servlet-api:3.0.1" //provided
- testCompile "ch.qos.logback:logback-classic:1.1.2"
+ testCompile "com.github.tomakehurst:wiremock:2.0.5-beta"
+ testCompile "org.spockframework:spock-spring:1.0-groovy-2.4"
+ testCompile "com.jayway.restassured:rest-assured:$restAssuredVersion"
+ testCompile "com.jayway.restassured:spring-mock-mvc:$restAssuredVersion"
+ testCompile "ch.qos.logback:logback-classic:1.1.2"
}
accurest {
- baseClassForTests = 'com.ofg.twitter.places.BaseMockMvcSpec'
- basePackageForTests = 'accurest'
- contractsDslDir = contractsDir
-// generatedTestSourcesDir = file("${project.rootDir}/src/test/groovy/")
- stubsOutputDir = wiremockStubsOutputDir
+ baseClassForTests = 'com.ofg.twitter.places.BaseMockMvcSpec'
+ basePackageForTests = 'accurest'
+ contractsDslDir = contractsDir
+// generatedTestSourcesDir = file("${project.rootDir}/src/test/groovy/")
+ stubsOutputDir = wireMockStubsOutputDir
}
//TODO: Put it into the plugin
-task createWiremockStubsOutputDir << {
- wiremockStubsOutputDir.mkdirs()
+task createWireMockStubsOutputDir << {
+ wireMockStubsOutputDir.mkdirs()
}
-generateWiremockClientStubs.dependsOn { createWiremockStubsOutputDir }
-generateAccurest.dependsOn generateWiremockClientStubs
+generateWireMockClientStubs.dependsOn { createWireMockStubsOutputDir }
+generateAccurest.dependsOn generateWireMockClientStubs
wrapper {
- gradleVersion '2.2.1'
+ gradleVersion '2.2.1'
}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
index 6e02ac3599..c484dce638 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/gradle.properties
@@ -1,5 +1,4 @@
groupId=com.ofg
jacksonMapper=1.9.13
restAssuredVersion=2.4.0
-accurestVersion=0.4.1
-springVersion=4.1.4.RELEASE
\ No newline at end of file
+springVersion=4.1.7.RELEASE
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/colleratePlacesFromTweet.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/colleratePlacesFromTweet.groovy
index 08b137a054..826f71b791 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/colleratePlacesFromTweet.groovy
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/colleratePlacesFromTweet.groovy
@@ -1,17 +1,18 @@
io.codearte.accurest.dsl.GroovyDsl.make {
- request {
- method 'PUT'
- url '/api/12'
- headers {
- header 'Content-Type': 'application/json'
- }
- body '''\
- [{
- "text": "Gonna see you at Warsaw"
- }]
+ priority 2
+ request {
+ method 'PUT'
+ url '/api/12'
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body '''\
+ [{
+ "text": "Gonna see you at Warsaw"
+ }]
'''
- }
- response {
- status 200
- }
+ }
+ response {
+ status 200
+ }
}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/moreComplexVersion.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/moreComplexVersion.groovy
index fdeb658215..943fbc23b9 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/moreComplexVersion.groovy
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/repository/mappings/com/ofg/twitter-places-analyzer/pairId/moreComplexVersion.groovy
@@ -1,21 +1,21 @@
io.codearte.accurest.dsl.GroovyDsl.make {
- request {
- method 'PUT'
- url $(client(regex('^/api/[0-9]{2}$')), server('/api/12'))
- headers {
- header 'Content-Type': 'application/json'
- }
- body '''\
- [{
- "text": "Gonna see you at Warsaw"
- }]
+ request {
+ method 'PUT'
+ url $(client(regex('^/api/[0-9]{2}$')), server('/api/12'))
+ headers {
+ header 'Content-Type': 'application/json'
+ }
+ body '''\
+ [{
+ "text": "Gonna see you at Warsaw"
+ }]
'''
- }
- response {
- body (
- path: $(client('/api/12'), server(regex('^/api/[0-9]{2}$'))),
- correlationId: $(client('1223456'), server(execute('isProperCorrelationId($it)')))
- )
- status 200
- }
+ }
+ response {
+ body (
+ path: $(client('/api/12'), server(regex('^/api/[0-9]{2}$'))),
+ correlationId: $(client('1223456'), server(execute('isProperCorrelationId($it)')))
+ )
+ status 200
+ }
}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/PairIdController.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/PairIdController.groovy
index 4f49f1ed3b..3a7671793c 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/PairIdController.groovy
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/PairIdController.groovy
@@ -16,21 +16,21 @@ import static org.springframework.web.bind.annotation.RequestMethod.PUT
@TypeChecked
class PairIdController {
- @RequestMapping(
- value = '{pairId}',
- method = PUT,
- consumes = MediaType.APPLICATION_JSON_VALUE,
- produces = MediaType.APPLICATION_JSON_VALUE)
- String getPlacesFromTweets(@PathVariable long pairId, @RequestBody List tweets) {
- log.info("Inside PairIdController, doing very important logic")
- if (tweets?.text != ["Gonna see you at Warsaw"]) {
- throw new IllegalArgumentException("Wrong text in tweet: ${tweets?.text}")
- }
- return """
- {
- "path" : "/api/$pairId",
- "correlationId" : 123456
- }
- """
- }
+ @RequestMapping(
+ value = '{pairId}',
+ method = PUT,
+ consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE)
+ String getPlacesFromTweets(@PathVariable long pairId, @RequestBody List tweets) {
+ log.info("Inside PairIdController, doing very important logic")
+ if (tweets?.text != ["Gonna see you at Warsaw"]) {
+ throw new IllegalArgumentException("Wrong text in tweet: ${tweets?.text}")
+ }
+ return """
+ {
+ "path" : "/api/$pairId",
+ "correlationId" : 123456
+ }
+ """
+ }
}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/Tweet.java b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/Tweet.java
index 96fdd52262..5d1e9c2835 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/Tweet.java
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/main/groovy/com/ofg/twitter/place/Tweet.java
@@ -1,13 +1,13 @@
package com.ofg.twitter.place;
public class Tweet {
- private String text;
+ private String text;
- public String getText() {
- return text;
- }
+ public String getText() {
+ return text;
+ }
- public void setText(String text) {
- this.text = text;
- }
+ public void setText(String text) {
+ this.text = text;
+ }
}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/AcceptanceSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/AcceptanceSpec.groovy
index 6a3bef53d7..458e275daf 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/AcceptanceSpec.groovy
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/AcceptanceSpec.groovy
@@ -11,13 +11,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
class AcceptanceSpec extends Specification {
- def "should have controller up and running"() {
- given:
- MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PairIdController()).build()
- expect:
- mockMvc.perform(put("/api/${1}").
- contentType(MediaType.APPLICATION_JSON).
- content("""[{"text":"Gonna see you at Warsaw"}]""")).
- andExpect(status().isOk())
- }
+ def "should have controller up and running"() {
+ given:
+ MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PairIdController()).build()
+ expect:
+ mockMvc.perform(put("/api/${1}").
+ contentType(MediaType.APPLICATION_JSON).
+ content("""[{"text":"Gonna see you at Warsaw"}]""")).
+ andExpect(status().isOk())
+ }
}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/BaseMockMvcSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/BaseMockMvcSpec.groovy
index cade991eaa..6b8e7e630e 100644
--- a/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/BaseMockMvcSpec.groovy
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/com/ofg/twitter/places/BaseMockMvcSpec.groovy
@@ -6,11 +6,11 @@ import spock.lang.Specification
abstract class BaseMockMvcSpec extends Specification {
- def setup() {
- RestAssuredMockMvc.standaloneSetup(new PairIdController())
- }
+ def setup() {
+ RestAssuredMockMvc.standaloneSetup(new PairIdController())
+ }
- void isProperCorrelationId(Integer correlationId) {
- assert correlationId == 123456
- }
+ void isProperCorrelationId(Integer correlationId) {
+ assert correlationId == 123456
+ }
}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle
new file mode 100644
index 0000000000..f33b17b5a6
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle
@@ -0,0 +1,94 @@
+buildscript {
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ }
+ dependencies {
+ classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.6.RELEASE"
+ }
+}
+
+ext {
+ restAssuredVersion = '2.5.0'
+ spockVersion = '1.0-groovy-2.4'
+ wiremockVersion = '2.0.5-beta'
+
+ accurestStubsBaseDirectory = 'src/test/resources/stubs'
+}
+
+subprojects {
+ apply plugin: 'groovy'
+
+ repositories {
+ mavenCentral()
+ mavenLocal()
+ }
+
+ dependencies {
+ testCompile 'org.codehaus.groovy:groovy-all:2.4.5'
+ testCompile "org.spockframework:spock-core:$spockVersion"
+ testCompile 'junit:junit:4.12'
+ testCompile "com.github.tomakehurst:wiremock:$wiremockVersion"
+ }
+}
+
+configure([project(':fraudDetectionService'), project(':loanApplicationService')]) {
+ apply plugin: 'spring-boot'
+ apply plugin: 'accurest'
+
+ ext {
+ wireMockStubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
+ wireMockStubsOutputDir = new File(wireMockStubsOutputDirRoot, 'mappings/')
+ }
+
+ accurest {
+ targetFramework = 'Spock'
+ testMode = 'JaxRsClient'
+ baseClassForTests = 'com.blogspot.toomuchcoding.MvcSpec'
+ contractsDslDir = file("${project.projectDir.absolutePath}/mappings/")
+ generatedTestSourcesDir = file("${project.buildDir}/generated-sources/")
+ stubsOutputDir = wireMockStubsOutputDir
+ }
+
+ jar {
+ version = '0.0.1'
+ }
+
+ configurations {
+ compile.exclude module: "spring-boot-starter-tomcat"
+ }
+
+ dependencies {
+ compile 'org.glassfish.jersey.containers:jersey-container-jetty-http:2.15'
+ compile 'org.springframework.boot:spring-boot-starter-jersey'
+ compile 'org.springframework.boot:spring-boot-starter-jetty'
+
+ testRuntime "org.spockframework:spock-spring:$spockVersion"
+
+ compile 'org.glassfish.jersey.connectors:jersey-apache-connector:2.15'
+ testCompile 'org.springframework:spring-test'
+ }
+
+ task cleanup(type: Delete) {
+ delete 'src/test/resources/mappings', 'src/test/resources/stubs'
+ }
+
+ clean.dependsOn('cleanup')
+
+}
+
+configure(project(':fraudDetectionService')) {
+ test.dependsOn('generateWireMockClientStubs')
+}
+
+configure(project(':loanApplicationService')) {
+
+ task copyCollaboratorStubs(type: Copy) {
+ File fraudBuildDir = project(':fraudDetectionService').buildDir
+ from(new File(fraudBuildDir, "/production/${project(':fraudDetectionService').name}-stubs/"))
+ into "src/test/resources/"
+ }
+
+ generateAccurest.dependsOn('copyCollaboratorStubs')
+}
+
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy
new file mode 100644
index 0000000000..44b1c08604
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy
@@ -0,0 +1,27 @@
+io.codearte.accurest.dsl.GroovyDsl.make {
+ request {
+ method """PUT"""
+ url """/fraudcheck"""
+ body("""
+ {
+ "clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
+ "loanAmount":99999}
+ """
+ )
+ headers {
+ header("""Content-Type""", """application/vnd.fraud.v1+json""")
+ }
+
+ }
+ response {
+ status 200
+ body( """{
+ "fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
+ "rejectionReason": "Amount too high"
+}""")
+ headers {
+ header('Content-Type': 'application/vnd.fraud.v1+json')
+ }
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy
new file mode 100644
index 0000000000..7bc64d0dac
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy
@@ -0,0 +1,28 @@
+io.codearte.accurest.dsl.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: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
+ )
+ headers {
+ header('Content-Type': 'application/vnd.fraud.v1+json')
+ }
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
new file mode 100644
index 0000000000..2089bda142
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
@@ -0,0 +1,25 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @Bean
+ ResourceConfig resourceConfig() {
+ return ResourceConfig.forApplication(new FraudRestApplication());
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java
new file mode 100644
index 0000000000..bb015f08a4
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java
@@ -0,0 +1,38 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheck;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheckResult;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.ws.rs.*;
+import java.math.BigDecimal;
+
+import static com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus.FRAUD;
+import static com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus.OK;
+
+@Controller
+@Path("/")
+public class FraudDetectionController {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+ private static final String NO_REASON = null;
+ private static final String AMOUNT_TOO_HIGH = "Amount too high";
+ private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
+
+ @PUT
+ @Path("/fraudcheck")
+ @Produces(FRAUD_SERVICE_JSON_VERSION_1)
+ @Consumes(FRAUD_SERVICE_JSON_VERSION_1)
+ public FraudCheckResult fraudCheck(@RequestBody(required = false) FraudCheck fraudCheck) {
+ if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FRAUD, AMOUNT_TOO_HIGH);
+ }
+ return new FraudCheckResult(OK, NO_REASON);
+ }
+
+ private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
+ return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudRestApplication.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudRestApplication.java
new file mode 100644
index 0000000000..83e15edc59
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudRestApplication.java
@@ -0,0 +1,13 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class FraudRestApplication extends javax.ws.rs.core.Application {
+
+ @Override
+ public Set> getClasses() {
+ return Collections.>singleton(FraudDetectionController.class);
+ }
+
+}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java
new file mode 100644
index 0000000000..77471aee19
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java
@@ -0,0 +1,29 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class FraudCheck {
+
+ private String clientPesel;
+
+ private BigDecimal loanAmount;
+
+ public FraudCheck() {
+ }
+
+ public String getClientPesel() {
+ return clientPesel;
+ }
+
+ public void setClientPesel(String clientPesel) {
+ this.clientPesel = clientPesel;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java
new file mode 100644
index 0000000000..28efc573f5
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java
@@ -0,0 +1,32 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class FraudCheckResult {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudCheckResult() {
+ }
+
+ public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
new file mode 100644
index 0000000000..b87c365d51
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum FraudCheckStatus {
+ OK, FRAUD
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/resources/application.yml b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/resources/application.yml
new file mode 100644
index 0000000000..a30a91f034
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/main/resources/application.yml
@@ -0,0 +1 @@
+server.port=8085
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy
new file mode 100644
index 0000000000..621d20ded4
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy
@@ -0,0 +1,57 @@
+package com.blogspot.toomuchcoding
+import com.blogspot.toomuchcoding.frauddetection.Application
+import com.blogspot.toomuchcoding.frauddetection.FraudRestApplication
+import org.eclipse.jetty.server.Server
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider
+import org.glassfish.jersey.client.ClientConfig
+import org.glassfish.jersey.jetty.JettyHttpContainerFactory
+import org.glassfish.jersey.server.ResourceConfig
+import org.springframework.context.annotation.AnnotationConfigApplicationContext
+import spock.lang.Shared
+import spock.lang.Specification
+
+import javax.ws.rs.client.Client
+import javax.ws.rs.client.ClientBuilder
+import javax.ws.rs.client.WebTarget
+import javax.ws.rs.core.UriBuilder
+
+import static org.springframework.util.SocketUtils.findAvailableTcpPort
+
+abstract class MvcSpec extends Specification {
+
+ @Shared
+ WebTarget webTarget
+
+ @Shared
+ private Server server
+
+ @Shared
+ private Client client
+
+ def setupSpec() {
+
+ URI baseUri = UriBuilder.fromUri("http://localhost").port(findAvailableTcpPort(8000)).build()
+
+
+ ResourceConfig resourceConfig = ResourceConfig.forApplication(new FraudRestApplication())
+ resourceConfig.property("contextConfig", new AnnotationConfigApplicationContext(Application))
+ server = JettyHttpContainerFactory.createServer(baseUri, resourceConfig, true)
+
+ ClientConfig clientConfig = new ClientConfig()
+ clientConfig.connectorProvider(new ApacheConnectorProvider())
+ client = ClientBuilder.newClient(clientConfig)
+
+ webTarget = client.target(baseUri)
+
+ server.start()
+ }
+
+ def cleanupSpec() {
+ client?.close()
+ server?.stop()
+ }
+
+ void assertThatRejectionReasonIsNull(def rejectionReason) {
+ assert !rejectionReason
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.jar b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..667288ad6c
Binary files /dev/null and b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.properties b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..b4603dcb69
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Jan 28 00:32:44 CET 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew.bat b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/mappings/.gitkeep b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/mappings/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
new file mode 100644
index 0000000000..5a1a60244e
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
@@ -0,0 +1,17 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java
new file mode 100644
index 0000000000..82476a3a46
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java
@@ -0,0 +1,62 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudServiceRequest;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudServiceResponse;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplication;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationResult;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationStatus;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class LoanApplicationService {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 =
+ "application/vnd.fraud.v1+json";
+
+ private final RestTemplate restTemplate;
+
+ public LoanApplicationService() {
+ this.restTemplate = new RestTemplate();
+ }
+
+ public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
+ FraudServiceRequest request =
+ new FraudServiceRequest(loanApplication);
+
+ FraudServiceResponse response =
+ sendRequestToFraudDetectionService(request);
+
+ return buildResponseFromFraudResult(response);
+ }
+
+ private FraudServiceResponse sendRequestToFraudDetectionService(
+ FraudServiceRequest request) {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+
+ ResponseEntity response =
+ restTemplate.exchange("http://localhost:8080/fraudcheck", HttpMethod.PUT,
+ new HttpEntity<>(request, httpHeaders),
+ FraudServiceResponse.class);
+
+ return response.getBody();
+ }
+
+ private LoanApplicationResult buildResponseFromFraudResult(FraudServiceResponse response) {
+ LoanApplicationStatus applicationStatus = null;
+ if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
+ } else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
+ }
+
+ return new LoanApplicationResult(applicationStatus, response.getRejectionReason());
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java
new file mode 100644
index 0000000000..5e91273eda
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java
@@ -0,0 +1,14 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class Client {
+
+ private String pesel;
+
+ public String getPesel() {
+ return pesel;
+ }
+
+ public void setPesel(String pesel) {
+ this.pesel = pesel;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
new file mode 100644
index 0000000000..b87c365d51
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum FraudCheckStatus {
+ OK, FRAUD
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java
new file mode 100644
index 0000000000..ac595998bc
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java
@@ -0,0 +1,34 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class FraudServiceRequest {
+
+ private String clientPesel;
+
+ private BigDecimal loanAmount;
+
+ public FraudServiceRequest() {
+ }
+
+ public FraudServiceRequest(LoanApplication loanApplication) {
+ this.clientPesel = loanApplication.getClient().getPesel();
+ this.loanAmount = loanApplication.getAmount();
+ }
+
+ public String getClientPesel() {
+ return clientPesel;
+ }
+
+ public void setClientPesel(String clientPesel) {
+ this.clientPesel = clientPesel;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java
new file mode 100644
index 0000000000..9f3353ecbf
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java
@@ -0,0 +1,27 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class FraudServiceResponse {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudServiceResponse() {
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java
new file mode 100644
index 0000000000..816087988b
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java
@@ -0,0 +1,36 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class LoanApplication {
+
+ private Client client;
+
+ private BigDecimal amount;
+
+ private String loanApplicationId;
+
+ public Client getClient() {
+ return client;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getLoanApplicationId() {
+ return loanApplicationId;
+ }
+
+ public void setLoanApplicationId(String loanApplicationId) {
+ this.loanApplicationId = loanApplicationId;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java
new file mode 100644
index 0000000000..523f4f2ea3
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java
@@ -0,0 +1,32 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class LoanApplicationResult {
+
+ private LoanApplicationStatus loanApplicationStatus;
+
+ private String rejectionReason;
+
+ public LoanApplicationResult() {
+ }
+
+ public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus, String rejectionReason) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public LoanApplicationStatus getLoanApplicationStatus() {
+ return loanApplicationStatus;
+ }
+
+ public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java
new file mode 100644
index 0000000000..7f7f86e0ea
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum LoanApplicationStatus {
+ LOAN_APPLIED, LOAN_APPLICATION_REJECTED
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/resources/application.yml b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/resources/application.yml
new file mode 100644
index 0000000000..e86bbd0e0f
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/main/resources/application.yml
@@ -0,0 +1 @@
+server.port=8090
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy
new file mode 100644
index 0000000000..58d17673ce
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy
@@ -0,0 +1,50 @@
+package com.blogspot.toomuchcoding
+
+import com.blogspot.toomuchcoding.frauddetection.Application
+import com.blogspot.toomuchcoding.frauddetection.LoanApplicationService
+import com.blogspot.toomuchcoding.frauddetection.model.Client
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplication
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationResult
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationStatus
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule
+import org.junit.ClassRule
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.SpringApplicationContextLoader
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Shared
+import spock.lang.Specification
+
+@ContextConfiguration(loader = SpringApplicationContextLoader, classes = Application)
+class LoanApplicationServiceSpec extends Specification {
+
+ @ClassRule
+ @Shared
+ WireMockClassRule wireMockRule = new WireMockClassRule()
+
+ @Autowired
+ LoanApplicationService sut
+
+ def 'should successfully apply for loan'() {
+ given:
+ LoanApplication application =
+ new LoanApplication(client: new Client(pesel: '1234567890'), amount: 123.123)
+ when:
+ LoanApplicationResult loanApplication = sut.loanApplication(application)
+ then:
+ loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
+ loanApplication.rejectionReason == null
+ }
+
+ def 'should be rejected due to abnormal loan amount'() {
+ given:
+ LoanApplication application =
+ new LoanApplication(client: new Client(pesel: '1234567890'), amount: 99_999)
+ when:
+ LoanApplicationResult loanApplication = sut.loanApplication(application)
+ then:
+ loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLICATION_REJECTED
+ loanApplication.rejectionReason == 'Amount too high'
+ }
+
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json
new file mode 100644
index 0000000000..7229872299
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json
@@ -0,0 +1,23 @@
+{
+ "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*\"?99999\"?\\s*\\}\\s*"
+ }
+ ]
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/vnd.fraud.v1+json"
+ },
+ "body": "{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}"
+ }
+}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json
new file mode 100644
index 0000000000..5a251171c7
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json
@@ -0,0 +1,23 @@
+{
+ "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}"
+ }
+}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/settings.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/settings.gradle
new file mode 100644
index 0000000000..6a42a6c7ce
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/settings.gradle
@@ -0,0 +1,2 @@
+include ':fraudDetectionService'
+include ':loanApplicationService'
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle
new file mode 100644
index 0000000000..25ca064fc4
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle
@@ -0,0 +1,92 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ mavenLocal()
+ }
+ dependencies {
+ classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.6.RELEASE")
+ }
+}
+
+ext {
+ restAssuredVersion = '2.5.0'
+ spockVersion = '1.0-groovy-2.4'
+ wiremockVersion = '2.0.5-beta'
+
+ accurestStubsBaseDirectory = 'src/test/resources/stubs'
+}
+
+subprojects {
+ apply plugin: 'groovy'
+
+ repositories {
+ mavenCentral()
+ mavenLocal()
+ }
+
+ dependencies {
+ testCompile "org.codehaus.groovy:groovy-all:2.4.5"
+ testCompile "org.spockframework:spock-core:$spockVersion"
+ testCompile("junit:junit:4.12")
+ testCompile "com.github.tomakehurst:wiremock:$wiremockVersion"
+ }
+}
+
+configure([project(':fraudDetectionService'), project(':loanApplicationService')]) {
+ apply plugin: 'spring-boot'
+ apply plugin: 'accurest'
+
+ ext {
+ wireMockStubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
+ wireMockStubsOutputDir = new File(wireMockStubsOutputDirRoot, 'mappings/')
+ }
+
+ accurest {
+ targetFramework = 'Spock'
+ testMode = 'MockMvc'
+ baseClassForTests = 'com.blogspot.toomuchcoding.MvcSpec'
+ contractsDslDir = file("${project.projectDir.absolutePath}/mappings/")
+ generatedTestSourcesDir = file("${project.buildDir}/generated-sources/")
+ stubsOutputDir = wireMockStubsOutputDir
+ }
+
+ jar {
+ version = '0.0.1'
+ }
+
+ dependencies {
+ compile("org.springframework.boot:spring-boot-starter-web") {
+ exclude module: "spring-boot-starter-tomcat"
+ }
+ compile("org.springframework.boot:spring-boot-starter-jetty")
+ compile("org.springframework.boot:spring-boot-starter-actuator")
+
+ testRuntime "org.spockframework:spock-spring:$spockVersion"
+ testCompile "org.springframework:spring-test"
+ testCompile "com.jayway.restassured:rest-assured:$restAssuredVersion"
+ testCompile "com.jayway.restassured:spring-mock-mvc:$restAssuredVersion"
+ }
+
+ task cleanup(type: Delete) {
+ delete 'src/test/resources/mappings', 'src/test/resources/stubs'
+ }
+
+ clean.dependsOn('cleanup')
+
+}
+
+configure(project(':fraudDetectionService')) {
+ test.dependsOn('generateWireMockClientStubs')
+}
+
+configure(project(':loanApplicationService')) {
+
+ task copyCollaboratorStubs(type: Copy) {
+ File fraudBuildDir = project(':fraudDetectionService').buildDir
+ from(new File(fraudBuildDir, "/production/${project(':fraudDetectionService').name}-stubs/"))
+ into "src/test/resources/"
+ }
+
+ generateAccurest.dependsOn('copyCollaboratorStubs')
+}
+
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy
new file mode 100644
index 0000000000..44b1c08604
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsFraud.groovy
@@ -0,0 +1,27 @@
+io.codearte.accurest.dsl.GroovyDsl.make {
+ request {
+ method """PUT"""
+ url """/fraudcheck"""
+ body("""
+ {
+ "clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
+ "loanAmount":99999}
+ """
+ )
+ headers {
+ header("""Content-Type""", """application/vnd.fraud.v1+json""")
+ }
+
+ }
+ response {
+ status 200
+ body( """{
+ "fraudCheckStatus": "${value(client('FRAUD'), server(regex('[A-Z]{5}')))}",
+ "rejectionReason": "Amount too high"
+}""")
+ headers {
+ header('Content-Type': 'application/vnd.fraud.v1+json')
+ }
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy
new file mode 100644
index 0000000000..7bc64d0dac
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.groovy
@@ -0,0 +1,28 @@
+io.codearte.accurest.dsl.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: $(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))
+ )
+ headers {
+ header('Content-Type': 'application/vnd.fraud.v1+json')
+ }
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
new file mode 100644
index 0000000000..5a1a60244e
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
@@ -0,0 +1,17 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java
new file mode 100644
index 0000000000..e264462cce
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/FraudDetectionController.java
@@ -0,0 +1,39 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheck;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheckResult;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+
+import static com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus.FRAUD;
+import static com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus.OK;
+import static org.springframework.web.bind.annotation.RequestMethod.PUT;
+
+@RestController
+public class FraudDetectionController {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
+ private static final String NO_REASON = null;
+ private static final String AMOUNT_TOO_HIGH = "Amount too high";
+ private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
+
+ @RequestMapping(
+ value = "/fraudcheck",
+ method = PUT,
+ consumes = FRAUD_SERVICE_JSON_VERSION_1,
+ produces = FRAUD_SERVICE_JSON_VERSION_1)
+ public FraudCheckResult fraudCheck(@RequestBody FraudCheck fraudCheck) {
+ if (amountGreaterThanThreshold(fraudCheck)) {
+ return new FraudCheckResult(FRAUD, AMOUNT_TOO_HIGH);
+ }
+ return new FraudCheckResult(OK, NO_REASON);
+ }
+
+ private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
+ return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java
new file mode 100644
index 0000000000..77471aee19
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheck.java
@@ -0,0 +1,29 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class FraudCheck {
+
+ private String clientPesel;
+
+ private BigDecimal loanAmount;
+
+ public FraudCheck() {
+ }
+
+ public String getClientPesel() {
+ return clientPesel;
+ }
+
+ public void setClientPesel(String clientPesel) {
+ this.clientPesel = clientPesel;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java
new file mode 100644
index 0000000000..28efc573f5
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckResult.java
@@ -0,0 +1,32 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class FraudCheckResult {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudCheckResult() {
+ }
+
+ public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
new file mode 100644
index 0000000000..b87c365d51
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum FraudCheckStatus {
+ OK, FRAUD
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/resources/application.yml b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/resources/application.yml
new file mode 100644
index 0000000000..a30a91f034
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/main/resources/application.yml
@@ -0,0 +1 @@
+server.port=8085
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy
new file mode 100644
index 0000000000..bcb6ef1579
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/fraudDetectionService/src/test/groovy/com/blogspot/toomuchcoding/MvcSpec.groovy
@@ -0,0 +1,15 @@
+package com.blogspot.toomuchcoding
+
+import com.blogspot.toomuchcoding.frauddetection.FraudDetectionController
+import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
+import spock.lang.Specification
+
+class MvcSpec extends Specification {
+ def setup() {
+ RestAssuredMockMvc.standaloneSetup(new FraudDetectionController())
+ }
+
+ void assertThatRejectionReasonIsNull(def rejectionReason) {
+ assert !rejectionReason
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.jar b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..667288ad6c
Binary files /dev/null and b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.properties b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..b4603dcb69
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Jan 28 00:32:44 CET 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew.bat b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/mappings/.gitkeep b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/mappings/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
new file mode 100644
index 0000000000..5a1a60244e
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/Application.java
@@ -0,0 +1,17 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java
new file mode 100644
index 0000000000..82476a3a46
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/LoanApplicationService.java
@@ -0,0 +1,62 @@
+package com.blogspot.toomuchcoding.frauddetection;
+
+import com.blogspot.toomuchcoding.frauddetection.model.FraudCheckStatus;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudServiceRequest;
+import com.blogspot.toomuchcoding.frauddetection.model.FraudServiceResponse;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplication;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationResult;
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationStatus;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class LoanApplicationService {
+
+ private static final String FRAUD_SERVICE_JSON_VERSION_1 =
+ "application/vnd.fraud.v1+json";
+
+ private final RestTemplate restTemplate;
+
+ public LoanApplicationService() {
+ this.restTemplate = new RestTemplate();
+ }
+
+ public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
+ FraudServiceRequest request =
+ new FraudServiceRequest(loanApplication);
+
+ FraudServiceResponse response =
+ sendRequestToFraudDetectionService(request);
+
+ return buildResponseFromFraudResult(response);
+ }
+
+ private FraudServiceResponse sendRequestToFraudDetectionService(
+ FraudServiceRequest request) {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
+
+ ResponseEntity response =
+ restTemplate.exchange("http://localhost:8080/fraudcheck", HttpMethod.PUT,
+ new HttpEntity<>(request, httpHeaders),
+ FraudServiceResponse.class);
+
+ return response.getBody();
+ }
+
+ private LoanApplicationResult buildResponseFromFraudResult(FraudServiceResponse response) {
+ LoanApplicationStatus applicationStatus = null;
+ if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
+ } else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
+ applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
+ }
+
+ return new LoanApplicationResult(applicationStatus, response.getRejectionReason());
+ }
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java
new file mode 100644
index 0000000000..5e91273eda
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/Client.java
@@ -0,0 +1,14 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class Client {
+
+ private String pesel;
+
+ public String getPesel() {
+ return pesel;
+ }
+
+ public void setPesel(String pesel) {
+ this.pesel = pesel;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
new file mode 100644
index 0000000000..b87c365d51
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudCheckStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum FraudCheckStatus {
+ OK, FRAUD
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java
new file mode 100644
index 0000000000..ac595998bc
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceRequest.java
@@ -0,0 +1,34 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class FraudServiceRequest {
+
+ private String clientPesel;
+
+ private BigDecimal loanAmount;
+
+ public FraudServiceRequest() {
+ }
+
+ public FraudServiceRequest(LoanApplication loanApplication) {
+ this.clientPesel = loanApplication.getClient().getPesel();
+ this.loanAmount = loanApplication.getAmount();
+ }
+
+ public String getClientPesel() {
+ return clientPesel;
+ }
+
+ public void setClientPesel(String clientPesel) {
+ this.clientPesel = clientPesel;
+ }
+
+ public BigDecimal getLoanAmount() {
+ return loanAmount;
+ }
+
+ public void setLoanAmount(BigDecimal loanAmount) {
+ this.loanAmount = loanAmount;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java
new file mode 100644
index 0000000000..9f3353ecbf
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/FraudServiceResponse.java
@@ -0,0 +1,27 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class FraudServiceResponse {
+
+ private FraudCheckStatus fraudCheckStatus;
+
+ private String rejectionReason;
+
+ public FraudServiceResponse() {
+ }
+
+ public FraudCheckStatus getFraudCheckStatus() {
+ return fraudCheckStatus;
+ }
+
+ public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
+ this.fraudCheckStatus = fraudCheckStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java
new file mode 100644
index 0000000000..816087988b
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplication.java
@@ -0,0 +1,36 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+import java.math.BigDecimal;
+
+public class LoanApplication {
+
+ private Client client;
+
+ private BigDecimal amount;
+
+ private String loanApplicationId;
+
+ public Client getClient() {
+ return client;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public String getLoanApplicationId() {
+ return loanApplicationId;
+ }
+
+ public void setLoanApplicationId(String loanApplicationId) {
+ this.loanApplicationId = loanApplicationId;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java
new file mode 100644
index 0000000000..523f4f2ea3
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationResult.java
@@ -0,0 +1,32 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public class LoanApplicationResult {
+
+ private LoanApplicationStatus loanApplicationStatus;
+
+ private String rejectionReason;
+
+ public LoanApplicationResult() {
+ }
+
+ public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus, String rejectionReason) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ this.rejectionReason = rejectionReason;
+ }
+
+ public LoanApplicationStatus getLoanApplicationStatus() {
+ return loanApplicationStatus;
+ }
+
+ public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
+ this.loanApplicationStatus = loanApplicationStatus;
+ }
+
+ public String getRejectionReason() {
+ return rejectionReason;
+ }
+
+ public void setRejectionReason(String rejectionReason) {
+ this.rejectionReason = rejectionReason;
+ }
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java
new file mode 100644
index 0000000000..7f7f86e0ea
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/java/com/blogspot/toomuchcoding/frauddetection/model/LoanApplicationStatus.java
@@ -0,0 +1,5 @@
+package com.blogspot.toomuchcoding.frauddetection.model;
+
+public enum LoanApplicationStatus {
+ LOAN_APPLIED, LOAN_APPLICATION_REJECTED
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/resources/application.yml b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/resources/application.yml
new file mode 100644
index 0000000000..e86bbd0e0f
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/main/resources/application.yml
@@ -0,0 +1 @@
+server.port=8090
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy
new file mode 100644
index 0000000000..58d17673ce
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/groovy/com/blogspot/toomuchcoding/LoanApplicationServiceSpec.groovy
@@ -0,0 +1,50 @@
+package com.blogspot.toomuchcoding
+
+import com.blogspot.toomuchcoding.frauddetection.Application
+import com.blogspot.toomuchcoding.frauddetection.LoanApplicationService
+import com.blogspot.toomuchcoding.frauddetection.model.Client
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplication
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationResult
+import com.blogspot.toomuchcoding.frauddetection.model.LoanApplicationStatus
+import com.github.tomakehurst.wiremock.junit.WireMockClassRule
+import org.junit.ClassRule
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.SpringApplicationContextLoader
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Shared
+import spock.lang.Specification
+
+@ContextConfiguration(loader = SpringApplicationContextLoader, classes = Application)
+class LoanApplicationServiceSpec extends Specification {
+
+ @ClassRule
+ @Shared
+ WireMockClassRule wireMockRule = new WireMockClassRule()
+
+ @Autowired
+ LoanApplicationService sut
+
+ def 'should successfully apply for loan'() {
+ given:
+ LoanApplication application =
+ new LoanApplication(client: new Client(pesel: '1234567890'), amount: 123.123)
+ when:
+ LoanApplicationResult loanApplication = sut.loanApplication(application)
+ then:
+ loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
+ loanApplication.rejectionReason == null
+ }
+
+ def 'should be rejected due to abnormal loan amount'() {
+ given:
+ LoanApplication application =
+ new LoanApplication(client: new Client(pesel: '1234567890'), amount: 99_999)
+ when:
+ LoanApplicationResult loanApplication = sut.loanApplication(application)
+ then:
+ loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLICATION_REJECTED
+ loanApplication.rejectionReason == 'Amount too high'
+ }
+
+
+}
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json
new file mode 100644
index 0000000000..157726ca2e
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsFraud.json
@@ -0,0 +1,23 @@
+{
+ "request": {
+ "method": "PUT",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.fraud.v1+json"
+ }
+ },
+ "url": "/fraudcheck",
+ "bodyPatterns": [
+ {
+ "matches": "{\"clientPesel\":\"[0-9]{10}\",\"loanAmount\":\"99999\"}"
+ }
+ ]
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/vnd.fraud.v1+json"
+ },
+ "body": "{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}"
+ }
+}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json
new file mode 100644
index 0000000000..afa27159d9
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/loanApplicationService/src/test/resources/mappings/fraudDetectionService/shouldMarkClientAsNotFraud.json
@@ -0,0 +1,23 @@
+{
+ "request": {
+ "method": "PUT",
+ "headers": {
+ "Content-Type": {
+ "equalTo": "application/vnd.fraud.v1+json"
+ }
+ },
+ "url": "/fraudcheck",
+ "bodyPatterns": [
+ {
+ "matches": "{\"clientPesel\":\"[0-9]{10}\",\"loanAmount\":\"123.123\"}"
+ }
+ ]
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/vnd.fraud.v1+json"
+ },
+ "body": "{\"fraudCheckStatus\":\"OK\",\"rejectionReason\":null}"
+ }
+}
\ No newline at end of file
diff --git a/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/settings.gradle b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/settings.gradle
new file mode 100644
index 0000000000..6a42a6c7ce
--- /dev/null
+++ b/accurest-gradle-plugin/src/test/resources/functionalTest/sampleProject/settings.gradle
@@ -0,0 +1,2 @@
+include ':fraudDetectionService'
+include ':loanApplicationService'
diff --git a/accurest-testing-utils/src/main/groovy/io/codearte/accurest/util/AssertionUtil.groovy b/accurest-testing-utils/src/main/groovy/io/codearte/accurest/util/AssertionUtil.groovy
new file mode 100644
index 0000000000..4c632a4de3
--- /dev/null
+++ b/accurest-testing-utils/src/main/groovy/io/codearte/accurest/util/AssertionUtil.groovy
@@ -0,0 +1,12 @@
+package io.codearte.accurest.util
+
+import org.skyscreamer.jsonassert.JSONAssert
+
+class AssertionUtil {
+
+ private static boolean NON_STRICT = false
+
+ public static void assertThatJsonsAreEqual(String expected, String actual) {
+ JSONAssert.assertEquals(expected, actual, NON_STRICT)
+ }
+}
diff --git a/build.gradle b/build.gradle
index c2d42cfdf1..42d265f044 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,20 +1,16 @@
buildscript {
repositories {
mavenCentral()
+ mavenLocal()
}
dependencies {
classpath "pl.allegro.tech.build:axion-release-plugin:1.2.2"
- classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.1"
+ classpath "com.bmuschko:gradle-nexus-plugin:2.3"
+ classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.3"
}
}
apply plugin: "pl.allegro.tech.build.axion-release"
-apply plugin: 'io.codearte.nexus-staging'
-
-nexusStaging {
- packageGroup = "io.codearte"
- stagingProfileId = '93c08fdebde1ff'
-}
scmVersion {
tag { prefix = "accurest" }
@@ -22,8 +18,8 @@ scmVersion {
releaseCommitMessage { version, position -> "Release version: ${version}\n\n[ci skip]" }
hooks {
pre "fileUpdate", [file : "README.md",
- pattern : { v, p -> /'io\.codearte\.accurest:accurest-gradle-plugin:.*'/ },
- replacement: { v, p -> "'io.codearte.accurest:accurest-gradle-plugin:$v'" }]
+ pattern : { v, p -> /'io\.codearte\.accurest:accurest-gradle-plugin:.*'/ },
+ replacement: { v, p -> "'io.codearte.accurest:accurest-gradle-plugin:$v'" }]
}
}
@@ -31,13 +27,16 @@ allprojects {
project.version = scmVersion.version
}
+apply plugin: 'io.codearte.nexus-staging'
+
+nexusStaging {
+ packageGroup = "io.codearte"
+ stagingProfileId = '93c08fdebde1ff'
+}
+
subprojects {
apply plugin: 'groovy'
- apply plugin: 'maven-publish'
-
- if (!version.contains('SNAPSHOT')) {
- apply from: "$rootDir/gradle/release.gradle"
- }
+ apply from: "$rootDir/gradle/release.gradle"
group = 'io.codearte.accurest'
@@ -47,6 +46,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/
@@ -55,49 +55,46 @@ subprojects {
dependencies {
compile localGroovy()
- testCompile('org.spockframework:spock-core:0.7-groovy-2.0') {
+ testCompile('org.spockframework:spock-core:1.0-groovy-2.3') {
exclude(group: 'org.codehaus.groovy')
}
}
-
- publishing {
- publications {
- maven(MavenPublication) {
- from components.java
- pom.withXml {
- //#89 - workaround to not to have only runtime dependencies in generated pom.xml
- //Known limitation in maven-publish - - http://forums.gradle.org/gradle/topics/maven_publish_plugin_generated_pom_making_dependency_scope_runtime#reply_14120711
- asNode().dependencies.'*'.findAll() {
- it.scope.text() == 'runtime' && project.configurations.compile.allDependencies.find { dep ->
- dep.name == it.artifactId.text()
- }
- }.each() {
- it.scope*.value = 'compile'
- }
- }
- }
- }
- }
-
- uploadArchives.dependsOn { check }
}
project(':accurest-core') {
+
dependencies {
compile 'org.slf4j:slf4j-api:[1.6.0,)'
- compile 'org.codehaus.plexus:plexus-utils:3.0.21'
- compile 'commons-io:commons-io:2.4'
+ 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.github.tomakehurst:wiremock:$wiremockVersion"
testCompile 'cglib:cglib-nodep:2.2'
testCompile 'org.objenesis:objenesis:2.1'
- testCompile 'com.github.tomakehurst:wiremock:1.53'
+ testCompile project(':accurest-testing-utils')
}
+
+}
+
+project(':accurest-testing-utils') {
+
+ dependencies {
+ compile 'org.skyscreamer:jsonassert:1.2.3'
+ }
+
}
project(':accurest-converters') {
dependencies {
compile project(':accurest-core')
- compile 'org.apache.commons:commons-lang3:3.3.2'
- compile 'commons-io:commons-io:[2.4,)'
+ 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:$wiremockVersion"
+ testCompile 'org.hamcrest:hamcrest-all:1.3'
}
}
@@ -106,10 +103,10 @@ project(':accurest-gradle-plugin') {
compile project(':accurest-core')
compile project(':accurest-converters')
compile gradleApi()
-
- testCompile('com.netflix.nebula:nebula-test:2.2.0') {
+ testCompile('com.netflix.nebula:nebula-test:2.2.1') {
exclude(group: 'org.spockframework')
}
+ testCompile project(':accurest-testing-utils')
}
test {
@@ -127,5 +124,5 @@ project(':accurest-gradle-plugin') {
}
task wrapper(type: Wrapper) {
- gradleVersion = '2.2.1'
+ gradleVersion = '2.4'
}
diff --git a/gradle.properties b/gradle.properties
index fe3cdf2fd8..27a71580f7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,4 @@
nexusUsername =
-nexusPassword =
\ No newline at end of file
+nexusPassword =
+
+wiremockVersion = 2.0.5-beta
diff --git a/gradle/release.gradle b/gradle/release.gradle
index 34e8ae08ef..e3f5159bb1 100644
--- a/gradle/release.gradle
+++ b/gradle/release.gradle
@@ -1,64 +1,40 @@
-apply plugin: 'maven'
-apply plugin: 'signing'
+apply plugin: 'com.bmuschko.nexus'
-task javadocJar(type: Jar) {
- classifier = 'javadoc'
- from javadoc
-}
+modifyPom {
+ project {
+ name "$project.name"
+ packaging 'jar'
+ description 'RESTful Contract Verifier'
+ url 'https://github.com/Codearte/accurest'
+ inceptionYear '2014'
-task sourcesJar(type: Jar) {
- classifier = 'sources'
- from sourceSets.main.allSource
-}
+ scm {
+ connection 'scm:git:git@github.com:Codearte/accurest.git'
+ developerConnection 'scm:git:git@github.com:Codearte/accurest.git'
+ url 'https://github.com/Codearte/accurest'
+ }
-artifacts {
- archives javadocJar, sourcesJar
-}
-
-signing {
- sign configurations.archives
-}
-
-uploadArchives {
- repositories {
- mavenDeployer {
- beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
-
- repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
- authentication(userName: nexusUsername, password: nexusPassword)
+ licenses {
+ license {
+ name 'The Apache License, Version 2.0'
+ url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
+ }
- snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
- authentication(userName: nexusUsername, password: nexusPassword)
+ developers {
+ developer {
+ id 'jkubrynski'
+ name 'Jakub Kubrynski'
+ email 'jk ATT codearte DOTT io'
}
-
- pom.project {
- name "$project.name"
- packaging 'jar'
- description 'RESTful Contract Verifier'
- url 'http://codearte.github.io/accurest'
-
- scm {
- connection 'scm:git:git@github.com:Codearte/accurest.git'
- developerConnection 'scm:git:git@github.com:Codearte/accurest.git'
- url 'https://github.com/Codearte/accurest'
- }
-
- licenses {
- license {
- name 'The Apache License, Version 2.0'
- url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
- }
- }
-
- developers {
- developer {
- id 'jkubrynski'
- name 'Jakub Kubrynski'
- email 'jk ATT codearte DOTT io'
- }
- }
+ developer {
+ id 'marcingrzejszczak'
+ name 'Marcin Grzejszczak'
+ email 'marcin ATT grzejszczak DOTT pl'
}
}
}
-}
\ No newline at end of file
+}
+
+uploadArchives.dependsOn { check }
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a0889f9ef7..8c1b9c3b9f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Jan 25 20:45:35 CET 2015
+#Sat May 16 12:50:16 CEST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip
diff --git a/settings.gradle b/settings.gradle
index 148580177b..7a36841ba8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,3 @@
-include "accurest-core", "accurest-gradle-plugin", 'accurest-converters'
+include "accurest-core", "accurest-gradle-plugin", 'accurest-converters', 'accurest-testing-utils'
rootProject.name = "accurest"