Converted to java
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingStrategy;
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
@@ -54,8 +58,19 @@ class MockMvcQueryParamsWhen implements When, MockMvcAcceptor, QueryParamsResolv
|
||||
}
|
||||
|
||||
private void addQueryParameters(Url buildUrl) {
|
||||
buildUrl.getQueryParameters().getParameters().stream()
|
||||
.filter(this::allowedQueryParameter).forEach(this::addQueryParameter);
|
||||
List<QueryParameter> queryParameters = buildUrl.getQueryParameters().getParameters().stream()
|
||||
.filter(this::allowedQueryParameter)
|
||||
.collect(Collectors.toList());
|
||||
Iterator<QueryParameter> iterator = queryParameters.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
QueryParameter parameter = iterator.next();
|
||||
String text = addQueryParameter(parameter);
|
||||
if (iterator.hasNext()) {
|
||||
this.blockBuilder.addLine(text);
|
||||
} else {
|
||||
this.blockBuilder.addIndented(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean allowedQueryParameter(Object o) {
|
||||
@@ -68,10 +83,10 @@ class MockMvcQueryParamsWhen implements When, MockMvcAcceptor, QueryParamsResolv
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addQueryParameter(QueryParameter queryParam) {
|
||||
this.blockBuilder.addLine("." + QUERY_PARAM_METHOD + "("
|
||||
private String addQueryParameter(QueryParameter queryParam) {
|
||||
return "." + QUERY_PARAM_METHOD + "("
|
||||
+ this.bodyParser.quotedLongText(queryParam.getName()) + ","
|
||||
+ this.bodyParser.quotedLongText(resolveParamValue(queryParam)) + ")");
|
||||
+ this.bodyParser.quotedLongText(resolveParamValue(queryParam)) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.contract.verifier.builder
|
||||
|
||||
import groovy.json.JsonOutput
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Request
|
||||
import org.springframework.cloud.contract.verifier.util.ContentUtils
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* Representation of the request side to be used for response templating in
|
||||
* the generated tests.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class TestSideRequestTemplateModel {
|
||||
/**
|
||||
* Request URL
|
||||
*/
|
||||
final String url
|
||||
|
||||
/**
|
||||
* Map containing query parameters
|
||||
*/
|
||||
final Map<String, List<String>> query
|
||||
|
||||
/**
|
||||
* List of path entries
|
||||
*/
|
||||
final Path path
|
||||
|
||||
/**
|
||||
* Map containing request headers
|
||||
*/
|
||||
final Map<String, List<String>> headers
|
||||
|
||||
/**
|
||||
* Request body as it would be sent to the controller
|
||||
*/
|
||||
final String body
|
||||
|
||||
/**
|
||||
* Escaped request body that can be put into test
|
||||
*/
|
||||
final String escapedBody
|
||||
|
||||
private TestSideRequestTemplateModel(String url, Map<String, List<String>> query, Path path, Map<String, List<String>> headers, String body, String escapedBody) {
|
||||
this.url = url
|
||||
this.query = query
|
||||
this.path = path
|
||||
this.headers = headers
|
||||
this.body = body
|
||||
this.escapedBody = escapedBody
|
||||
}
|
||||
|
||||
static TestSideRequestTemplateModel from(final Request request) {
|
||||
String url = MapConverter.getTestSideValues(request.url ?: request.urlPath)
|
||||
Path paths = new Path(buildPathsFromUrl(url))
|
||||
Map<String, List<String>> query = (Map<String, List<String>>) (request.url ?: request.urlPath)
|
||||
.queryParameters?.parameters?.groupBy { it.name }?.collectEntries {
|
||||
[(it.key): it.value.collect { MapConverter.getTestSideValues(it) }]
|
||||
}
|
||||
String fullUrl = (query == null || query.isEmpty()) ? url :
|
||||
url + "?" + query.collect { String name, List<String> values ->
|
||||
return values.collect { "${name}=${it}"}.join("&") }.join("&")
|
||||
Map<String, List<String>> headers = (Map<String, List<String>>) (request.headers?.entries?.groupBy {
|
||||
it.name
|
||||
}?.collectEntries {
|
||||
List<Object> headerValues = []
|
||||
for (Object value : it.value) {
|
||||
headerValues.add(MapConverter.getTestSideValues(value))
|
||||
}
|
||||
[(it.key): headerValues]
|
||||
})
|
||||
String escapedBody = trimmedAndEscapedBody(request.body)
|
||||
String body = getBodyAsRawJson(request.body)
|
||||
return new TestSideRequestTemplateModel(fullUrl, query, paths, headers, body, escapedBody)
|
||||
}
|
||||
|
||||
private static List<String> buildPathsFromUrl(String url) {
|
||||
String fakeUrl = "https://foo.bar" + (url.startsWith("/") ? url : "/" + url)
|
||||
List<String> paths = new URL(fakeUrl).path.split("/") as List<String>
|
||||
if (!paths.isEmpty()) {
|
||||
paths.remove(0)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
private static String trimmedAndEscapedBody(Object body) {
|
||||
String rawBody = getBodyAsRawJson(body)
|
||||
return StringEscapeUtils.escapeJava(rawBody)
|
||||
}
|
||||
|
||||
private static String getBodyAsRawJson(Object body) {
|
||||
Object bodyValue = extractServerValueFromBody(body)
|
||||
if (bodyValue instanceof GString || bodyValue instanceof String) {
|
||||
return bodyValue.toString()
|
||||
}
|
||||
else if (bodyValue instanceof FromFileProperty) {
|
||||
return null
|
||||
}
|
||||
return bodyValue != null ? new JsonOutput().toJson(bodyValue) : bodyValue
|
||||
}
|
||||
|
||||
protected static Object extractServerValueFromBody(bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
bodyValue = ContentUtils.
|
||||
extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue } as Closure)
|
||||
}
|
||||
else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue, {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
})
|
||||
}
|
||||
return bodyValue
|
||||
}
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
class Path extends ArrayList<String> {
|
||||
|
||||
Path(List<String> list) {
|
||||
this.addAll(list)
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
return "/" + this.join("/")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import groovy.json.JsonOutput;
|
||||
import groovy.lang.GString;
|
||||
import groovy.transform.CompileStatic;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.Header;
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter;
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.spec.internal.Url;
|
||||
import org.springframework.cloud.contract.verifier.util.ContentUtils;
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter;
|
||||
|
||||
/**
|
||||
* Representation of the request side to be used for response templating in the generated
|
||||
* tests.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class TestSideRequestTemplateModel {
|
||||
|
||||
/**
|
||||
* Request URL
|
||||
*/
|
||||
private final String url;
|
||||
|
||||
/**
|
||||
* Map containing query parameters
|
||||
*/
|
||||
private final Map<String, List<Object>> query;
|
||||
|
||||
/**
|
||||
* List of path entries
|
||||
*/
|
||||
private final Path path;
|
||||
|
||||
/**
|
||||
* Map containing request headers
|
||||
*/
|
||||
private final Map<String, List<String>> headers;
|
||||
|
||||
/**
|
||||
* Request body as it would be sent to the controller
|
||||
*/
|
||||
private final String body;
|
||||
|
||||
/**
|
||||
* Escaped request body that can be put into test
|
||||
*/
|
||||
private final String escapedBody;
|
||||
|
||||
private TestSideRequestTemplateModel(String url, Map<String, List<Object>> query,
|
||||
Path path, Map<String, List<String>> headers, String body,
|
||||
String escapedBody) {
|
||||
this.url = url;
|
||||
this.query = query;
|
||||
this.path = path;
|
||||
this.headers = headers;
|
||||
this.body = body;
|
||||
this.escapedBody = escapedBody;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public Map<String, List<Object>> getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public String getEscapedBody() {
|
||||
return this.escapedBody;
|
||||
}
|
||||
|
||||
public static TestSideRequestTemplateModel from(final Request request) {
|
||||
Url urlPath = request.getUrl() != null ? request.getUrl() : request.getUrlPath();
|
||||
String url = MapConverter.getTestSideValues(urlPath).toString();
|
||||
Path paths = new Path(buildPathsFromUrl(url));
|
||||
QueryParameters queryParameters = urlPath.getQueryParameters();
|
||||
Map<String, List<Object>> query = query(queryParameters);
|
||||
boolean queryParamsPresent = query == null || query.isEmpty();
|
||||
String fullUrl = fullUrl(url, query, queryParamsPresent);
|
||||
boolean headersEntriesPresent = request.getHeaders() != null
|
||||
&& !request.getHeaders().getEntries().isEmpty();
|
||||
Map<String, List<String>> headers = headers(request, headersEntriesPresent);
|
||||
String escapedBody = trimmedAndEscapedBody(request.getBody());
|
||||
String body = getBodyAsRawJson(request.getBody());
|
||||
return new TestSideRequestTemplateModel(fullUrl, query, paths, headers, body,
|
||||
escapedBody);
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> headers(Request request,
|
||||
boolean headersEntriesPresent) {
|
||||
if (!headersEntriesPresent) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return request.getHeaders().getEntries().stream()
|
||||
.collect(Collectors.groupingBy(Header::getName,
|
||||
Collectors.mapping(
|
||||
(Function<Object, String>) o -> MapConverter
|
||||
.getTestSideValues(o).toString(),
|
||||
Collectors.toList())));
|
||||
}
|
||||
|
||||
private static String fullUrl(String url, Map<String, List<Object>> query,
|
||||
boolean queryParamsPresent) {
|
||||
if (queryParamsPresent) {
|
||||
return url;
|
||||
}
|
||||
String joinedParams = query.entrySet().stream()
|
||||
.map(entry -> entry.getValue().stream().map(s -> entry.getKey() + "=" + s)
|
||||
.collect(Collectors.joining("&")))
|
||||
.collect(Collectors.joining("&"));
|
||||
return url + "?" + joinedParams;
|
||||
}
|
||||
|
||||
private static Map<String, List<Object>> query(QueryParameters queryParameters) {
|
||||
if (queryParameters == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return queryParameters.getParameters().stream()
|
||||
.collect(Collectors.groupingBy(QueryParameter::getName, Collectors
|
||||
.mapping(MapConverter::getTestSideValues, Collectors.toList())));
|
||||
}
|
||||
|
||||
private static List<String> buildPathsFromUrl(String url) {
|
||||
String fakeUrl = "https://foo.bar" + (url.startsWith("/") ? url : "/" + url);
|
||||
List<String> paths;
|
||||
try {
|
||||
paths = new LinkedList<>(
|
||||
Arrays.asList(new URL(fakeUrl).getPath().split("/")));
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
if (!paths.isEmpty()) {
|
||||
paths.remove(0);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
private static String trimmedAndEscapedBody(Object body) {
|
||||
String rawBody = getBodyAsRawJson(body);
|
||||
return StringEscapeUtils.escapeJava(rawBody);
|
||||
}
|
||||
|
||||
private static String getBodyAsRawJson(Object body) {
|
||||
Object bodyValue = extractServerValueFromBody(body);
|
||||
if (bodyValue instanceof GString || bodyValue instanceof String) {
|
||||
return bodyValue.toString();
|
||||
}
|
||||
else if (bodyValue instanceof FromFileProperty) {
|
||||
return null;
|
||||
}
|
||||
return bodyValue != null ? new JsonOutput().toJson(bodyValue) : null;
|
||||
}
|
||||
|
||||
private static Object extractServerValueFromBody(Object bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
bodyValue = ContentUtils.extractValue((GString) bodyValue,
|
||||
ContentUtils.GET_TEST_SIDE_FUNCTION);
|
||||
}
|
||||
else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue,
|
||||
ContentUtils.GET_TEST_SIDE);
|
||||
}
|
||||
return bodyValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@CompileStatic
|
||||
class Path extends ArrayList<String> {
|
||||
|
||||
Path(List<String> list) {
|
||||
this.addAll(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "/" + String.join("/", this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.verifier.builder.handlebars
|
||||
package org.springframework.cloud.contract.verifier.builder.handlebars;
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import groovy.transform.CompileStatic
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import wiremock.com.github.jknack.handlebars.Helper;
|
||||
import wiremock.com.github.jknack.handlebars.Options;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel;
|
||||
|
||||
/**
|
||||
* A Handlebars helper for the {@code escapejsonbody} helper function.
|
||||
@@ -30,30 +32,31 @@ import org.springframework.cloud.contract.verifier.builder.TestSideRequestTempla
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class HandlebarsEscapeHelper implements Helper<Map<String, Object>> {
|
||||
public class HandlebarsEscapeHelper implements Helper<Map<String, Object>> {
|
||||
|
||||
public static final String NAME = "escapejsonbody"
|
||||
public static final String REQUEST_MODEL_NAME = "request"
|
||||
public static final String NAME = "escapejsonbody";
|
||||
|
||||
public static final String REQUEST_MODEL_NAME = "request";
|
||||
|
||||
@Override
|
||||
Object apply(Map<String, Object> context, Options options) throws IOException {
|
||||
Object model = context.get(REQUEST_MODEL_NAME)
|
||||
public Object apply(Map<String, Object> context, Options options) throws IOException {
|
||||
Object model = context.get(REQUEST_MODEL_NAME);
|
||||
if (model instanceof TestSideRequestTemplateModel) {
|
||||
return StringEscapeUtils.escapeJson(returnObjectForTest(model).toString())
|
||||
return StringEscapeUtils.escapeJson(returnObjectForTest(model).toString());
|
||||
}
|
||||
else if (model instanceof RequestTemplateModel) {
|
||||
return StringEscapeUtils.escapeJson(returnObjectForStub(model).toString())
|
||||
return StringEscapeUtils.escapeJson(returnObjectForStub(model).toString());
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported model")
|
||||
|
||||
throw new IllegalArgumentException("Unsupported model");
|
||||
}
|
||||
|
||||
private Object returnObjectForStub(Object model) {
|
||||
return ((RequestTemplateModel) model).body
|
||||
return ((RequestTemplateModel) model).getBody();
|
||||
}
|
||||
|
||||
private Object returnObjectForTest(Object model) {
|
||||
return ((TestSideRequestTemplateModel) model).escapedBody
|
||||
return ((TestSideRequestTemplateModel) model).getEscapedBody();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.contract.verifier.builder.handlebars
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.WireMockHelpers
|
||||
import com.jayway.jsonpath.DocumentContext
|
||||
import com.jayway.jsonpath.JsonPath
|
||||
import groovy.transform.CompileStatic
|
||||
import wiremock.com.github.jknack.handlebars.Helper
|
||||
import wiremock.com.github.jknack.handlebars.Options
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel
|
||||
|
||||
/**
|
||||
* A Handlebars helper for the {@code jsonpath} helper function.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class HandlebarsJsonPathHelper implements Helper<Object> {
|
||||
|
||||
public static final String NAME = "jsonpath"
|
||||
public static final String REQUEST_MODEL_NAME = "request"
|
||||
|
||||
@Override
|
||||
Object apply(Object context, Options options) throws IOException {
|
||||
if (context instanceof Map<String, Object>) {
|
||||
// legacy
|
||||
Map<String, Object> oldContext = (Map<String, Object>) context
|
||||
String jsonPath = options.param(0)
|
||||
Object model = oldContext.get(REQUEST_MODEL_NAME)
|
||||
if (model instanceof TestSideRequestTemplateModel) {
|
||||
return returnObjectForTest(model, jsonPath)
|
||||
}
|
||||
else if (model instanceof RequestTemplateModel) {
|
||||
return returnObjectForStub(model, jsonPath)
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported model")
|
||||
}
|
||||
else if (context instanceof String) {
|
||||
Object value = WireMockHelpers.jsonPath.apply(context, options)
|
||||
if (testSideModel(options)) {
|
||||
return processTestResponseValue(value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported context")
|
||||
}
|
||||
|
||||
private boolean testSideModel(Options options) {
|
||||
Object model = options.context.model()
|
||||
if (!(model instanceof Map)) {
|
||||
return false
|
||||
}
|
||||
Map map = (Map) model
|
||||
return map.values().any { it instanceof TestSideRequestTemplateModel }
|
||||
}
|
||||
|
||||
private Object returnObjectForStub(Object model, String jsonPath) {
|
||||
DocumentContext documentContext = JsonPath.
|
||||
parse(((RequestTemplateModel) model).body)
|
||||
return documentContext.read(jsonPath)
|
||||
}
|
||||
|
||||
private Object returnObjectForTest(TestSideRequestTemplateModel model, String jsonPath) {
|
||||
String body = removeSurroundingQuotes(model.escapedBody).replace('\\"', '"')
|
||||
DocumentContext documentContext = JsonPath.parse(body)
|
||||
Object value = documentContext.read(jsonPath)
|
||||
return processTestResponseValue(value)
|
||||
}
|
||||
|
||||
private Object processTestResponseValue(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return String.valueOf(value) + "L"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private String removeSurroundingQuotes(String body) {
|
||||
if (body.startsWith('"') && body.endsWith('"')) {
|
||||
return body.substring(1, body.length() - 1)
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.contract.verifier.builder.handlebars;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel;
|
||||
import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.WireMockHelpers;
|
||||
import com.jayway.jsonpath.DocumentContext;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
import wiremock.com.github.jknack.handlebars.Helper;
|
||||
import wiremock.com.github.jknack.handlebars.Options;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel;
|
||||
|
||||
/**
|
||||
* A Handlebars helper for the {@code jsonpath} helper function.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class HandlebarsJsonPathHelper implements Helper<Object> {
|
||||
|
||||
public static final String NAME = "jsonpath";
|
||||
|
||||
public static final String REQUEST_MODEL_NAME = "request";
|
||||
|
||||
@Override
|
||||
public Object apply(Object context, Options options) throws IOException {
|
||||
if (context instanceof Map) {
|
||||
// legacy
|
||||
Map<String, Object> oldContext = (Map<String, Object>) context;
|
||||
String jsonPath = options.param(0);
|
||||
Object model = oldContext.get(REQUEST_MODEL_NAME);
|
||||
if (model instanceof TestSideRequestTemplateModel) {
|
||||
return returnObjectForTest((TestSideRequestTemplateModel) model,
|
||||
jsonPath);
|
||||
}
|
||||
else if (model instanceof RequestTemplateModel) {
|
||||
return returnObjectForStub(model, jsonPath);
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported model");
|
||||
}
|
||||
else if (context instanceof String) {
|
||||
Object value = WireMockHelpers.jsonPath.apply(context, options);
|
||||
if (testSideModel(options)) {
|
||||
return processTestResponseValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported context");
|
||||
}
|
||||
|
||||
private boolean testSideModel(Options options) {
|
||||
Object model = options.context.model();
|
||||
if (!(model instanceof Map)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map map = (Map) model;
|
||||
return map.values().stream()
|
||||
.anyMatch(o -> o instanceof TestSideRequestTemplateModel);
|
||||
}
|
||||
|
||||
private Object returnObjectForStub(Object model, String jsonPath) {
|
||||
DocumentContext documentContext = JsonPath
|
||||
.parse(((RequestTemplateModel) model).getBody());
|
||||
return documentContext.read(jsonPath);
|
||||
}
|
||||
|
||||
private Object returnObjectForTest(TestSideRequestTemplateModel model,
|
||||
String jsonPath) {
|
||||
String body = removeSurroundingQuotes(model.getEscapedBody()).replace("\\\"",
|
||||
"\"");
|
||||
DocumentContext documentContext = JsonPath.parse(body);
|
||||
Object value = documentContext.read(jsonPath);
|
||||
return processTestResponseValue(value);
|
||||
}
|
||||
|
||||
private Object processTestResponseValue(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return (long) value + "L";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String removeSurroundingQuotes(String body) {
|
||||
if (body.startsWith("\"") && body.endsWith("\"")) {
|
||||
return body.substring(1, body.length() - 1);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,6 +71,20 @@ class ContentUtils {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
}
|
||||
|
||||
public static final Function GET_STUB_SIDE_FUNCTION = new Function() {
|
||||
@Override
|
||||
Object apply(Object it) {
|
||||
return it instanceof DslProperty ? it.clientValue : it
|
||||
}
|
||||
}
|
||||
|
||||
public static final Function GET_TEST_SIDE_FUNCTION = new Function() {
|
||||
@Override
|
||||
Object apply(Object it) {
|
||||
return it instanceof DslProperty ? it.serverValue : it
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern TEMPORARY_PATTERN_HOLDER = Pattern.
|
||||
compile('.*REGEXP>>(.*)<<.*')
|
||||
private static final Pattern TEMPORARY_EXECUTION_PATTERN_HOLDER = Pattern.
|
||||
@@ -238,6 +252,10 @@ class ContentUtils {
|
||||
)
|
||||
}
|
||||
|
||||
static Object extractValue(GString bodyAsValue, Function valueProvider) {
|
||||
return extractValue(bodyAsValue, UNKNOWN, { valueProvider.apply(it) })
|
||||
}
|
||||
|
||||
static Object extractValue(GString bodyAsValue, Closure valueProvider) {
|
||||
return extractValue(bodyAsValue, UNKNOWN, valueProvider)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user