Merge pull request #12 from 4finance/groovyDsl

[#5] Groovy DSL and Wiremock conversion
This commit is contained in:
Marcin Grzejszczak
2015-02-13 00:21:02 +01:00
23 changed files with 951 additions and 376 deletions

2
.gitignore vendored
View File

@@ -2,6 +2,8 @@
*.iml
.idea/
.gradle/
target/
build/
hs_err_pid*

View File

@@ -0,0 +1,37 @@
package io.codearte.accurest.wiremock
import groovy.json.JsonSlurper
import io.coderate.accurest.dsl.GroovyDsl
class WiremockToDslConverter {
static GroovyDsl fromWiremockStub(String wiremockStringStub) {
Object wiremockStub = new JsonSlurper().parseText(wiremockStringStub)
def wiremockRequest = wiremockStub.request
def wiremockResponse = wiremockStub.response
return GroovyDsl.make {
request {
wiremockRequest.method ? method(wiremockRequest.method as String) : null
wiremockRequest.url ? url(wiremockRequest.url as String) : null
wiremockRequest.urlPattern ? urlPattern(wiremockRequest.urlPattern as String) : null
wiremockRequest.urlPath ? urlPath(wiremockRequest.urlPath as String) : null
wiremockRequest.headers ? headers {
wiremockRequest.headers.each {
def assertion = it.value
String headerName = it.key as String
header(headerName)."$assertion.key"(assertion.value)
}
} : null
}
response {
status wiremockResponse.status ? wiremockResponse.status as Integer : null
wiremockResponse.body ? body (
wiremockResponse.body as Map
) : null
wiremockResponse.headers ? headers {
wiremockResponse.headers.each {
header([(it.key) : it.value])
}
} : null
}
}
}
}

View File

@@ -0,0 +1,54 @@
package io.codearte.accurest.wiremock
import io.coderate.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",
"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:
GroovyDsl expectedGroovyDsl = GroovyDsl.make {
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 {
header 'Content-Type': 'text/plain'
}
}
}
when:
GroovyDsl groovyDsl = WiremockToDslConverter.fromWiremockStub(wiremockStub)
then:
groovyDsl == expectedGroovyDsl
}
}

View File

@@ -0,0 +1,55 @@
package io.coderate.accurest.dsl
import groovy.transform.CompileStatic
import io.coderate.accurest.dsl.internal.DslProperty
import io.coderate.accurest.dsl.internal.Headers
import io.coderate.accurest.dsl.internal.WithValuePattern
@CompileStatic
abstract class BaseWiremockStubStrategy {
protected Map buildClientHeadersSection(Headers headers) {
if (!headers) {
return null
}
return withAssertionHeaders(headers) {
Map.Entry<String, WithValuePattern> entry -> [(entry.key): buildClientHeaderFromValuePattern(entry.value)]
} << headers?.valueHeaders()
}
protected Map buildServerHeadersSection(Headers headers) {
if (!headers) {
return null
}
return withAssertionHeaders(headers) {
Map.Entry<String, WithValuePattern> entry -> [(entry.key): buildServerHeaderFromValuePattern(entry.value)]
} << headers.valueHeaders()
}
private Map withAssertionHeaders(Headers headers, Closure closure) {
return headers?.assertionEntries()?.collectEntries(closure)
}
private Map buildClientHeaderFromValuePattern(WithValuePattern valuePattern) {
return getValuePatternSection(valuePattern)
.findAll { it.value }
.collectEntries { [(it.key): it.value.clientValue] }
}
private Map buildServerHeaderFromValuePattern(WithValuePattern valuePattern) {
return getValuePatternSection(valuePattern)
.findAll { it.value }
.collectEntries { [(it.key): it.value.serverValue] }
}
private Map<String, DslProperty> getValuePatternSection(WithValuePattern valuePattern) {
return [equalToJson : valuePattern.equalToJson,
equalToXml : valuePattern.equalToXml,
matchesXPath : valuePattern.matchesXPath,
jsonCompareMode: valuePattern.jsonCompareMode,
equalTo : valuePattern.equalTo,
contains : valuePattern.contains,
matches : valuePattern.matches,
doesNotMatch : valuePattern.doesNotMatch,
absent : valuePattern.absent,
matchesJsonPath: valuePattern.matchesJsonPath]
}
}

View File

@@ -1,11 +1,18 @@
package io.coderate.accurest.dsl
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import io.coderate.accurest.dsl.internal.Request
import io.coderate.accurest.dsl.internal.Response
@TypeChecked
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class GroovyDsl {
Request request
Response response
static GroovyDsl make(Closure closure) {
GroovyDsl dsl = new GroovyDsl()
@@ -15,9 +22,14 @@ class GroovyDsl {
}
void request(@DelegatesTo(Request) Closure closure) {
Request request = new Request()
this.request = request
this.request = new Request()
closure.delegate = request
closure()
}
void response(@DelegatesTo(Response) Closure closure) {
this.response = new Response()
closure.delegate = response
closure()
}
}

View File

@@ -1,172 +0,0 @@
package io.coderate.accurest.dsl
import groovy.transform.TypeChecked
@TypeChecked
class Request {
String method
String url
StringCustomizableProperty urlPattern
String urlPath
Headers headers
void method(String method) {
this.method = method
}
void url(String url) {
this.url = url
}
void urlPattern(@DelegatesTo(StringCustomizableProperty) Closure closure) {
StringCustomizableProperty urlPattern = new StringCustomizableProperty()
this.urlPattern = urlPattern
delegateToClosure(closure, urlPattern)
}
void headers(@DelegatesTo(Headers) Closure closure) {
Headers headers = new Headers()
this.headers = headers
delegateToClosure(closure, headers)
}
void urlPath(String urlPath) {
this.urlPath = urlPath
}
//TODO: Can we have different types for Client/Server (client: pattern(String), server: value(Boolean/Int)) ?
class CustomizableProperty<T, V> {
private T client
private V server
void client(T client) {
this.client = client
}
void server(V server) {
this.server = server
}
T toClientSide() {
return client
}
V toServerSide() {
return server
}
}
private class StringCustomizableProperty extends CustomizableProperty<String, String> {
@Override
String toClientSide() {
return super.toClientSide() as String
}
@Override
String toServerSide() {
return super.toServerSide() as String
}
}
private class NoOpCustomizableProperty<T> extends CustomizableProperty<T, T> {
NoOpCustomizableProperty(T value) {
client(value)
server(value)
}
@Override
public String toString() {
return toClientSide()
}
}
class Headers {
private Map<String, WithValuePattern> headers = [:]
WithValuePattern header(String headerName) {
WithValuePattern withValuePattern = new WithValuePattern()
headers[headerName] = withValuePattern
return withValuePattern
}
Set<Map.Entry<String, WithValuePattern>> entries() {
return headers.entrySet()
}
}
/**
*
* From Wiremock
private Map<String, ValuePattern> queryParamPatterns;
private List<ValuePattern> bodyPatterns;
private String equalToJson;
private String equalToXml;
private String matchesXPath;
private JSONCompareMode jsonCompareMode;
private String equalTo;
private String contains;
private String matches;
private String doesNotMatch;
private Boolean absent;
private String matchesJsonPath;
*/
class WithValuePattern {
NoOpCustomizableProperty<String> equalToJson
NoOpCustomizableProperty<String> equalToXml
StringCustomizableProperty matchesXPath
NoOpCustomizableProperty<JSONCompareMode> jsonCompareMode
NoOpCustomizableProperty<String> equalTo
StringCustomizableProperty contains
StringCustomizableProperty matches
StringCustomizableProperty doesNotMatch
CustomizableProperty<Boolean, Boolean> absent
StringCustomizableProperty matchesJsonPath
// void equalToJson(String equalToJson) {
// this.equalToJson = equalToJson
// }
//
void equalTo(String equalTo) {
this.equalTo = new NoOpCustomizableProperty(equalTo)
}
// void equalToXml(String equalToXml) {
// this.equalToXml = equalToXml
// }
void matches(@DelegatesTo(StringCustomizableProperty) Closure closure) {
StringCustomizableProperty placeholderHaving = new StringCustomizableProperty()
this.matches = placeholderHaving
delegateToClosure(closure, placeholderHaving)
}
void doesNotMatch(@DelegatesTo(StringCustomizableProperty) Closure closure) {
StringCustomizableProperty placeholderHaving = new StringCustomizableProperty()
this.doesNotMatch = placeholderHaving
delegateToClosure(closure, placeholderHaving)
}
void contains(@DelegatesTo(StringCustomizableProperty) Closure closure) {
StringCustomizableProperty placeholderHaving = new StringCustomizableProperty()
this.contains = placeholderHaving
delegateToClosure(closure, placeholderHaving)
}
// void jsonCompareMode(JSONCompareMode jsonCompareMode) {
// this.jsonCompareMode = jsonCompareMode
// }
}
enum JSONCompareMode {
STRICT, LENIENT, NON_EXTENSIBLE, STRICT_ORDER;
}
private static <T> void delegateToClosure(@DelegatesTo(T) Closure closure, T delegate) {
closure.delegate = delegate
closure()
}
}

View File

@@ -0,0 +1,42 @@
package io.coderate.accurest.dsl
import groovy.transform.CompileStatic
import groovy.transform.PackageScope
import io.coderate.accurest.dsl.internal.ClientRequest
import io.coderate.accurest.dsl.internal.Request
import io.coderate.accurest.dsl.internal.ServerRequest
@CompileStatic
@PackageScope
class WiremockRequestStubStrategy extends BaseWiremockStubStrategy {
private final Request request
WiremockRequestStubStrategy(GroovyDsl groovyDsl) {
this.request = groovyDsl.request
}
@PackageScope Map buildClientRequestContent() {
return buildRequestContent(new ClientRequest(request))
}
@PackageScope Map buildServerRequestContent() {
return buildRequestContent(new ServerRequest(request))
}
private Map<String, Object> buildRequestContent(ClientRequest request) {
return [method : request?.method?.clientValue,
url : request?.url?.clientValue,
urlPattern: request?.urlPattern?.clientValue,
urlPath : request?.urlPath?.clientValue,
headers : buildClientHeadersSection(request.headers)].findAll { it.value }
}
private Map<String, Object> buildRequestContent(ServerRequest request) {
return [method : request?.method?.serverValue,
url : request?.url?.serverValue,
urlPattern: request?.urlPattern?.serverValue,
urlPath : request?.urlPath?.serverValue,
headers : buildServerHeadersSection(request.headers)].findAll { it.value }
}
}

View File

@@ -0,0 +1,39 @@
package io.coderate.accurest.dsl
import groovy.transform.CompileStatic
import groovy.transform.PackageScope
import io.coderate.accurest.dsl.internal.ClientResponse
import io.coderate.accurest.dsl.internal.Response
import io.coderate.accurest.dsl.internal.ServerResponse
@CompileStatic
@PackageScope
class WiremockResponseStubStrategy extends BaseWiremockStubStrategy {
private final Response response
WiremockResponseStubStrategy(GroovyDsl groovyDsl) {
this.response = groovyDsl.response
}
@PackageScope Map buildClientResponseContent() {
return buildResponseContent(new ClientResponse(response))
}
@PackageScope Map buildServerResponseContent() {
return buildResponseContent(new ServerResponse(response))
}
private Map<String, Object> buildResponseContent(ClientResponse response) {
return [status : response?.status?.clientValue,
body : response?.body?.forClientSide(),
headers: buildClientHeadersSection(response.headers)].findAll { it.value }
}
private Map<String, Object> buildResponseContent(ServerResponse response) {
return [status : response?.status?.serverValue,
body : response?.body?.forServerSide(),
headers: buildServerHeadersSection(response.headers)].findAll { it.value }
}
}

View File

@@ -6,81 +6,21 @@ import groovy.transform.CompileStatic
@CompileStatic
class WiremockStubStrategy {
private final Request request
private final WiremockRequestStubStrategy wiremockRequestStubStrategy
private final WiremockResponseStubStrategy wiremockResponseStubStrategy
WiremockStubStrategy(GroovyDsl groovyDsl) {
this.request = groovyDsl.request
this.wiremockRequestStubStrategy = new WiremockRequestStubStrategy(groovyDsl)
this.wiremockResponseStubStrategy = new WiremockResponseStubStrategy(groovyDsl)
}
String toWiremockClientStub() {
return JsonOutput.toJson(buildClientRequest(request))
return JsonOutput.toJson([request: wiremockRequestStubStrategy.buildClientRequestContent(),
response: wiremockResponseStubStrategy.buildClientResponseContent()])
}
String toWiremockServerStub() {
return JsonOutput.toJson(buildServerRequest(request))
return JsonOutput.toJson([request: wiremockRequestStubStrategy.buildServerRequestContent(),
response: wiremockResponseStubStrategy.buildServerResponseContent()])
}
private Map buildClientRequest(Request request) {
return getRequestSection(request,
{ request.urlPattern?.toClientSide() },
{ buildClientHeadersSection(request.headers) })
}
private Map buildServerRequest(Request request) {
return getRequestSection(request,
{ request.urlPattern?.toServerSide() },
{ buildServerHeadersSection(request.headers) })
}
private Map<String, Map<String, Object>> getRequestSection(Request request, Closure<String> buildUrlPattern, Closure<Map> buildHeaders) {
return [request: [method : request.method,
url : request.url,
urlPattern: buildUrlPattern(),
urlPath : request.urlPath,
headers : buildHeaders()].findAll { it.value }]
}
private Map buildClientHeadersSection(Request.Headers headers) {
return createHeadersSection(headers) {
Map.Entry<String, Request.WithValuePattern> entry -> [(entry.key): buildClientHeaderFromValuePattern(entry.value)]
}
}
private Map buildServerHeadersSection(Request.Headers headers) {
return createHeadersSection(headers) {
Map.Entry<String, Request.WithValuePattern> entry -> [(entry.key): buildServerHeaderFromValuePattern(entry.value)]
}
}
private Map createHeadersSection(Request.Headers headers, Closure closure) {
return headers?.entries()?.collectEntries(closure)
}
private Map buildClientHeaderFromValuePattern(Request.WithValuePattern valuePattern) {
return getValuePatternSection(valuePattern)
.findAll { it.value }
.collectEntries { [(it.key): it.value.toClientSide()] }
}
private Map buildServerHeaderFromValuePattern(Request.WithValuePattern valuePattern) {
return getValuePatternSection(valuePattern)
.findAll { it.value }
.collectEntries { [(it.key): it.value.toServerSide()] }
}
private Map<String, Request.CustomizableProperty> getValuePatternSection(Request.WithValuePattern valuePattern) {
return [equalToJson : valuePattern.equalToJson,
equalToXml : valuePattern.equalToXml,
matchesXPath : valuePattern.matchesXPath,
jsonCompareMode: valuePattern.jsonCompareMode,
equalTo : valuePattern.equalTo,
contains : valuePattern.contains,
matches : valuePattern.matches,
doesNotMatch : valuePattern.doesNotMatch,
absent : valuePattern.absent,
matchesJsonPath: valuePattern.matchesJsonPath]
}
}

View File

@@ -0,0 +1,32 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@CompileStatic
@ToString(includePackage = false, includeFields = true)
@EqualsAndHashCode(includeFields = true)
class Body {
private final Map<String, DslProperty> body
Body() {
this.body = [:]
}
Body(Map<String, DslProperty> body) {
this.body = body
}
Map<String, Object> forClientSide() {
return body.collectEntries {
Map.Entry<String, DslProperty> entry -> [(entry.key) : entry.value.clientValue]
} as Map<String, Object>
}
Map<String, Object> forServerSide() {
return body.collectEntries {
Map.Entry<String, DslProperty> entry -> [(entry.key) : entry.value.serverValue]
} as Map<String, Object>
}
}

View File

@@ -0,0 +1,10 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
@CompileStatic
class ClientDslProperty extends DslProperty {
ClientDslProperty(Object singleValue) {
super(singleValue)
}
}

View File

@@ -0,0 +1,52 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
/**
* @TypeChecked instead of @CompileStatic due to usage of double dispatch.
* Double dispatch doesn't work if you're using @CompileStatic
*/
@TypeChecked
@PackageScope
class Common {
Map<String, DslProperty> convertObjectsToDslProperties(Map<String, Object> body) {
return body.collectEntries {
Map.Entry<String, Object> entry ->
[(entry.key): toDslProperty(entry.value)]
} as Map<String, DslProperty>
}
DslProperty toDslProperty(Object property) {
return new DslProperty(property)
}
DslProperty toDslProperty(DslProperty property) {
return property
}
DslProperty value(ClientDslProperty client, ServerDslProperty server) {
return new DslProperty(client.clientValue, server.serverValue)
}
DslProperty value(ServerDslProperty server, ClientDslProperty client) {
return new DslProperty(client.clientValue, server.serverValue)
}
DslProperty $(ClientDslProperty client, ServerDslProperty server) {
return value(client, server)
}
DslProperty $(ServerDslProperty server, ClientDslProperty client) {
return value(server, client)
}
ClientDslProperty client(Object clientValue) {
return new ClientDslProperty(clientValue)
}
ServerDslProperty server(Object serverValue) {
return new ServerDslProperty(serverValue)
}
}

View File

@@ -0,0 +1,24 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class DslProperty<T> {
final T clientValue
final T serverValue
DslProperty(T clientValue, T serverValue) {
this.clientValue = clientValue
this.serverValue = serverValue
}
DslProperty(T singleValue) {
this.clientValue = singleValue
this.serverValue = singleValue
}
}

View File

@@ -0,0 +1,31 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class Headers {
private Map<String, WithValuePattern> assertionHeaders = [:]
private Map<String, String> valueHeaders = [:]
WithValuePattern header(String headerName) {
WithValuePattern withValuePattern = new WithValuePattern()
assertionHeaders[headerName] = withValuePattern
return withValuePattern
}
void header(Map<String, String> singleHeader) {
Map.Entry<String, String> first = singleHeader.entrySet().first()
valueHeaders[first?.key] = first?.value
}
Map<String, String> valueHeaders() {
return Collections.unmodifiableMap(valueHeaders)
}
Set<Map.Entry<String, WithValuePattern>> assertionEntries() {
return Collections.unmodifiableSet(assertionHeaders.entrySet())
}
}

View File

@@ -0,0 +1,5 @@
package io.coderate.accurest.dsl.internal
enum JSONCompareMode {
STRICT, LENIENT, NON_EXTENSIBLE, STRICT_ORDER
}

View File

@@ -0,0 +1,84 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@TypeChecked
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class Request extends Common {
DslProperty method
DslProperty url
DslProperty urlPattern
DslProperty urlPath
Headers headers
Request() {
}
Request(Request request) {
this.method = request.method
this.url = request.url
this.urlPattern = request.urlPattern
this.urlPath = request.urlPath
this.headers = request.headers
}
void method(String method) {
this.method = toDslProperty(method)
}
void method(DslProperty method) {
this.method = toDslProperty(method)
}
void url(String url) {
this.url = toDslProperty(url)
}
void url(DslProperty url) {
this.url = toDslProperty(url)
}
void urlPattern(String urlPattern) {
this.urlPattern = toDslProperty(urlPattern)
}
void urlPattern(DslProperty urlPattern) {
this.urlPattern = toDslProperty(urlPattern)
}
void headers(@DelegatesTo(Headers) Closure closure) {
this.headers = new Headers()
closure.delegate = headers
closure()
}
void urlPath(String urlPath) {
this.urlPath = toDslProperty(urlPath)
}
void urlPath(DslProperty urlPath) {
this.urlPath = toDslProperty(urlPath)
}
}
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ServerRequest extends Request {
ServerRequest(Request request) {
super(request)
}
}
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ClientRequest extends Request {
ClientRequest(Request request) {
super(request)
}
}

View File

@@ -0,0 +1,73 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@TypeChecked
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false, includeFields = true)
class Response extends Common {
private DslProperty status
private Headers headers
private Body body = new Body()
Response() {
}
Response(Response response) {
this.status = response.status
this.headers = response.headers
this.body = response.body
}
void status(int status) {
this.status = toDslProperty(status)
}
void status(DslProperty status) {
this.status = toDslProperty(status)
}
void headers(@DelegatesTo(Headers) Closure closure) {
this.headers = new Headers()
closure.delegate = headers
closure()
}
void body(Map<String, Object> body) {
this.body = new Body(convertObjectsToDslProperties(body))
}
Body getBody() {
return body
}
DslProperty getStatus() {
return status
}
Headers getHeaders() {
return headers
}
}
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ServerResponse extends Response {
ServerResponse(Response request) {
super(request)
}
}
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ClientResponse extends Response {
ClientResponse(Response request) {
super(request)
}
}

View File

@@ -0,0 +1,15 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@CompileStatic
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class ServerDslProperty extends DslProperty {
ServerDslProperty(Object singleValue) {
super(singleValue)
}
}

View File

@@ -0,0 +1,102 @@
package io.coderate.accurest.dsl.internal
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@TypeChecked
@EqualsAndHashCode(includeFields = true)
@ToString(includePackage = false)
class WithValuePattern {
DslProperty<String> equalTo
DslProperty<String> equalToJson
DslProperty<String> equalToXml
DslProperty<String> matchesXPath
DslProperty<JSONCompareMode> jsonCompareMode
DslProperty<String> contains
DslProperty<String> matches
DslProperty<String> doesNotMatch
DslProperty<String> absent
DslProperty<String> matchesJsonPath
void equalTo(String equalTo) {
this.equalTo = new DslProperty<String>(equalTo)
}
void equalTo(DslProperty equalTo) {
this.equalTo = equalTo
}
void equalToJson(String equalToJson) {
this.equalToJson = new DslProperty<String>(equalToJson)
}
void equalToJson(DslProperty equalToJson) {
this.equalToJson = equalToJson
}
void equalToXml(String equalToXml) {
this.equalToXml = new DslProperty<String>(equalToXml)
}
void equalToXml(DslProperty equalToXml) {
this.equalToXml = equalToXml
}
void matchesXPath(String matchesXPath) {
this.matchesXPath = new DslProperty<String>(matchesXPath)
}
void matchesXPath(DslProperty matchesXPath) {
this.matchesXPath = matchesXPath
}
void jsonCompareMode(JSONCompareMode jsonCompareMode) {
this.jsonCompareMode = new DslProperty<JSONCompareMode>(jsonCompareMode)
}
void jsonCompareMode(DslProperty jsonCompareMode) {
this.jsonCompareMode = jsonCompareMode
}
void contains(String contains) {
this.contains = new DslProperty<String>(contains)
}
void contains(DslProperty contains) {
this.contains = contains
}
void matches(String matches) {
this.matches = new DslProperty<String>(matches)
}
void matches(DslProperty matches) {
this.matches = matches
}
void doesNotMatch(String doesNotMatch) {
this.doesNotMatch = new DslProperty<String>(doesNotMatch)
}
void doesNotMatch(DslProperty doesNotMatch) {
this.doesNotMatch = doesNotMatch
}
void absent(String absent) {
this.absent = new DslProperty<String>(absent)
}
void absent(DslProperty absent) {
this.absent = absent
}
void matchesJsonPath(String matchesJsonPath) {
this.matchesJsonPath = new DslProperty<String>(matchesJsonPath)
}
void matchesJsonPath(DslProperty matchesJsonPath) {
this.matchesJsonPath = matchesJsonPath
}
}

View File

@@ -0,0 +1,100 @@
package io.codearte.accurest.dsl
import groovy.json.JsonSlurper
import io.coderate.accurest.dsl.GroovyDsl
import io.coderate.accurest.dsl.WiremockResponseStubStrategy
import spock.lang.Specification
class WiremockGroovyDslResponseSpec extends Specification {
def 'should generate response without body for #side side'() {
given:
GroovyDsl dsl = GroovyDsl.make {
response {
status 200
}
}
expect:
new WiremockResponseStubStrategy(dsl)."build${side}ResponseContent"() == new JsonSlurper().parseText(expectedStub)
where:
side << ['Client', 'Server']
expectedStub << ['''
{
"status": 200
}
''',
'''
{
"status": 200
}
''']
}
def 'should generate headers for response for client side'() {
given:
GroovyDsl dsl = GroovyDsl.make {
response {
headers {
header('Content-Type').matches $(client('text/xml'), server('text/*'))
}
status 200
}
}
expect:
new WiremockResponseStubStrategy(dsl).buildClientResponseContent() == new JsonSlurper().parseText('''
{
"headers": {
"Content-Type": {
"matches": "text/xml"
},
},
"status": 200
}
''')
}
def 'should generate headers for response for server side'() {
given:
GroovyDsl dsl = GroovyDsl.make {
response {
status 200
headers {
header('Content-Type').matches $(client('text/xml'), server('text/*'))
}
}
}
expect:
new WiremockResponseStubStrategy(dsl).buildServerResponseContent() == new JsonSlurper().parseText('''
{
"status": 200,
"headers": {
"Content-Type": {
"matches": "text/*"
}
}
}
''')
}
def 'should generate an exact header for response for both sides '() {
given:
GroovyDsl dsl = GroovyDsl.make {
response {
status 200
headers {
header 'Content-Type': 'text/xml'
}
}
}
expect:
new WiremockResponseStubStrategy(dsl).buildServerResponseContent() == new JsonSlurper().parseText('''
{
"status": 200,
"headers": {
"Content-Type": "text/xml"
}
}
''')
}
}

View File

@@ -2,41 +2,43 @@ package io.codearte.accurest.dsl
import groovy.json.JsonSlurper
import io.coderate.accurest.dsl.GroovyDsl
import io.coderate.accurest.dsl.WiremockRequestStubStrategy
import io.coderate.accurest.dsl.WiremockStubStrategy
import spock.lang.Ignore
import spock.lang.Specification
class WiremockGroovyDslSpec extends Specification {
// TODO: add alias instead of placeholder
@Ignore
def 'should convert groovy dsl stub to wiremock stub'() {
def 'should convert groovy dsl stub to wiremock stub for the client side'() {
given:
GroovyDsl dsl = GroovyDsl.make {
request {
method('GET')
urlPattern {
client('/[0-9]{2}')
server('/12')
GroovyDsl groovyDsl = GroovyDsl.make {
request {
method('GET')
urlPattern $(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'
}
}
}
response {
status(200)
body {
withPlaceholder(client: '2015-01-14', server: '$anyInt($it)')
withTemplate('''
{
"date" : "$placeholder0"
}
''')
}
headers {
Content-Type('text/plain')
}
}
}
expect:
dsl.toWiremockClientStub() == '''
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
{
"request": {
"method": "GET",
@@ -44,13 +46,69 @@ class WiremockGroovyDslSpec extends Specification {
},
"response": {
"status": 200,
"body": "2015-01-14",
"body": {
"id": "123",
"surname": "Kowalsky",
"name": "Jan",
"created" : "2014-02-02 12:23:43"
},
"headers": {
"Content-Type": "text/plain"
}
}
}
'''
''')
}
def 'should convert groovy dsl stub to wiremock stub for the server side'() {
given:
GroovyDsl groovyDsl = GroovyDsl.make {
request {
method('GET')
urlPattern $(client('/[0-9]{2}'), server('/12'))
}
response {
status(200)
body (
id : value(
client('123'),
server('321')
),
surname : $(
client('Kowalsky'),
server('Lewandowski')
),
name: 'Jan',
created : $(client('2014-02-02 12:23:43'), server('1999-01-01 01:23:45'))
)
headers {
header('Content-Type': 'text/plain')
}
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockServerStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
{
"request": {
"method": "GET",
"urlPattern": "/12"
},
"response": {
"status": 200,
"body": {
"id": "321",
"surname": "Lewandowski",
"name": "Jan",
"created" : "1999-01-01 01:23:45"
},
"headers": {
"Content-Type": "text/plain"
}
}
}
''')
}
def "should generate stub with GET"() {
@@ -60,14 +118,10 @@ class WiremockGroovyDslSpec extends Specification {
method("GET")
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"method":"GET"
}
"method":"GET"
}
''')
}
@@ -80,15 +134,11 @@ class WiremockGroovyDslSpec extends Specification {
url("/sth")
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"method":"GET",
"url":"/sth"
}
"method":"GET",
"url":"/sth"
}
''')
}
@@ -97,19 +147,16 @@ class WiremockGroovyDslSpec extends Specification {
given:
GroovyDsl groovyDsl = GroovyDsl.make {
request {
urlPattern {
client('/^[0-9]{2}$')
}
urlPattern $(
client('/^[0-9]{2}$'),
server('/12')
)
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"urlPattern":"/^[0-9]{2}$"
}
"urlPattern":"/^[0-9]{2}$"
}
''')
}
@@ -118,20 +165,16 @@ class WiremockGroovyDslSpec extends Specification {
given:
GroovyDsl groovyDsl = GroovyDsl.make {
request {
urlPattern {
client('/^[0-9]{2}$')
server('/12')
}
urlPattern $(
client('/[0-9]{2}'),
server('/12')
)
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockServerStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildServerRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"urlPattern":"/12"
}
"urlPattern":"/12"
}
''')
}
@@ -143,14 +186,10 @@ class WiremockGroovyDslSpec extends Specification {
urlPath ('/12')
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"urlPath":"/12"
}
"urlPath":"/12"
}
''')
}
@@ -162,14 +201,10 @@ class WiremockGroovyDslSpec extends Specification {
urlPath ('/12')
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockServerStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"urlPath":"/12"
}
"urlPath":"/12"
}
''')
}
@@ -180,40 +215,36 @@ class WiremockGroovyDslSpec extends Specification {
request {
headers {
header('Content-Type').equalTo('text/xml')
header('Accept').matches {
client('text/.*')
header('Accept').matches $(
client('text/.*'),
server('text/plain')
}
header('etag').doesNotMatch {
client('abcd.*')
)
header('etag').doesNotMatch $(
client('abcd.*'),
server('abcdef')
}
header('X-Custom-Header').contains {
client('2134')
)
header('X-Custom-Header').contains $(
client('2134'),
server('121345')
}
)
}
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockClientStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildClientRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"headers": {
"Content-Type": {
"equalTo": "text/xml"
},
"Accept": {
"matches": "text/.*"
},
"etag": {
"doesNotMatch": "abcd.*"
},
"X-Custom-Header": {
"contains": "2134"
}
"headers": {
"Content-Type": {
"equalTo": "text/xml"
},
"Accept": {
"matches": "text/.*"
},
"etag": {
"doesNotMatch": "abcd.*"
},
"X-Custom-Header": {
"contains": "2134"
}
}
}
@@ -226,45 +257,45 @@ class WiremockGroovyDslSpec extends Specification {
request {
headers {
header('Content-Type').equalTo('text/xml')
header('Accept').matches {
client('text/.*')
header('Accept').matches $(
client('text/.*'),
server('text/plain')
}
header('etag').doesNotMatch {
client('abcd.*')
)
header('etag').doesNotMatch $(
client('abcd.*'),
server('abcdef')
}
header('X-Custom-Header').contains {
client('2134')
)
header('X-Custom-Header').contains $(
client('2134'),
server('121345')
}
)
}
}
}
when:
String wiremockStub = new WiremockStubStrategy(groovyDsl).toWiremockServerStub()
then:
new JsonSlurper().parseText(wiremockStub) == new JsonSlurper().parseText('''
expect:
new WiremockRequestStubStrategy(groovyDsl).buildServerRequestContent() == new JsonSlurper().parseText('''
{
"request":{
"headers": {
"Content-Type": {
"equalTo": "text/xml"
},
"Accept": {
"matches": "text/plain"
},
"etag": {
"doesNotMatch": "abcdef"
},
"X-Custom-Header": {
"contains": "121345"
}
"headers": {
"Content-Type": {
"equalTo": "text/xml"
},
"Accept": {
"matches": "text/plain"
},
"etag": {
"doesNotMatch": "abcdef"
},
"X-Custom-Header": {
"contains": "121345"
}
}
}
''')
}
@Ignore("Not implemented yet")
def "should generate stub with request body matching for server side"() {}
@Ignore("Not implemented yet")
def "should generate stub with request query parameter matching for server side"() {}
}

View File

@@ -44,6 +44,12 @@ subprojects {
project(':accurest-core') {
}
project(':accurest-converters') {
dependencies {
compile project(':accurest-core')
}
}
project(':accurest-gradle-plugin') {
dependencies {
compile project(':accurest-core')

View File

@@ -1,2 +1,3 @@
include "accurest-core", "accurest-gradle-plugin"
rootProject.name = "accurest"
include "accurest-core", "accurest-gradle-plugin", 'accurest-converters'
rootProject.name = "accurest"