From 9178668f847ea102d579d432a76bf91acf9c6175 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 11 Oct 2018 19:18:18 +0200 Subject: [PATCH] Support for web test client (#1078) * Set up module. Start adding factory classes and methods for creating WebTestClient instances. * Add test setup. Add specification interfaces. Add `standaloneSetup()`, `given()`, `when()`, `and()` methods implementation. Start moving code that can be reused to a commons module. Start implementing `WebTesClientRequestSpecificationImpl`. * Implement handling body, cookies, multipart, config and merging specs. Fix serializing. * Finish implementing `WebTestClientRequestSenderImpl`. Start implementing logging for WebTestClient. * Start implementing WebtTestClientSenderImpl. Add tests and fixes. * Test fixes and javadocs for attributes and cookies. * Fix passing response headers. Implement `ValidatableWebTestClientResponseImpl`. * Handle null response content type. Implement content type tests. Switch to standard test formatting. * Implement logging.Start working on `WebTestClientRequestSpecBuilder`. * Fix assigning config to WebTestClientRequestSpecification. Adjust logging tests to WebTestClient returned headers. Implement setup for logging if validation fails. * Handle form params. Add non-static request and response spec test. * Implement param update methods in WebtTestClientParamConfig. Add param config tests. * Add methods in `WebTestClientRequestLogSpecification` and implement them in `WebTestClientRequestLogSpecificationImpl`, add fixes to `WebTestClientRequestSpecification` and `WebTestClientRequestSenderImpl`. Add more tests for params, requests and request specification. * Switch `WebTestClientRequestSenderImpl` to deserialize response to String in order to enable custom content types. Add more tests. * Fix outputting status line for error responses. Add setting blank content type for URL-encoded. Add `PutTest`. * Implement methods in `WebTestClientRequestLogSpecificationImpl`. Add `RequestLoggingTest`. Add `QueryParamTest`. * Add `ResponseLoggingTest`. Refactor `RequestLoggingTest`. * Fix passing params for restdocs. Fix consumeWith. Removed the possibility of returning responseSpec as trying to do body assertions on it would cause issues, cause the stream has already been blocked to get the byte array response. * Add SecuredRequestTest. Remove unnecessary comments and code. * Remove unnecessary code and refactor. * Implement sending requests with uriFunctions, refactor and reformat code. Add license comments. Javadoc fixes. * Refactor and reformat code. Add license comments. Javadoc fixes. * Clean up dependencies. * Fix method call. Throw IllegalArgumentException when WebTestClientFactory not assigned. * Fixes after code review. --- modules/pom.xml | 4 +- modules/spring-commons/pom.xml | 41 + .../module/spring/commons/BodyHelper.java | 84 ++ .../module/spring/commons/CookieHelper.java | 88 ++ .../module/spring/commons/HeaderHelper.java | 175 ++++ .../module/spring/commons/ParamApplier.java | 50 + .../module/spring/commons/ParamLogger.java | 48 + .../module/spring/commons/RequestLogger.java | 129 +++ .../module/spring/commons/Serializer.java | 48 + .../spring/commons}/config/AsyncConfig.java | 30 +- .../spring/commons/config/ClientConfig.java | 23 + .../commons/config}/ConfigConverter.java | 26 +- .../commons/config/ConfigMergeUtils.java | 80 ++ .../commons/config/SpecificationConfig.java | 81 ++ modules/spring-mock-mvc/pom.xml | 5 + .../module/mockmvc/config/MockMvcConfig.java | 4 +- .../mockmvc/config/MockMvcParamConfig.java | 22 +- .../config/RestAssuredMockMvcConfig.java | 40 +- .../mockmvc/internal/MockMvcFactory.java | 1 + .../internal/MockMvcRequestSenderImpl.java | 264 +---- .../MockMvcRequestSpecificationImpl.java | 295 ++---- .../restassured/module/mockmvc/AsyncTest.java | 6 +- .../mockmvc/MockMvcParamConfigTest.java | 2 +- modules/spring-web-test-client/pom.xml | 137 +++ .../RestAssuredWebTestClient.java | 829 +++++++++++++++ .../RestAssuredWebTestClientConfig.java | 420 ++++++++ .../config/WebTestClientConfig.java | 53 + .../config/WebTestClientParamConfig.java | 180 ++++ .../BuilderBasedWebTestClientFactory.java | 43 + .../internal/ExchangeResultConverter.java | 101 ++ .../internal/ResponseConverter.java | 52 + .../StandaloneWebTestClientFactory.java | 80 ++ .../ValidatableWebTestClientResponseImpl.java | 50 + .../internal/WebTestClientFactory.java | 37 + ...TestClientRequestLogSpecificationImpl.java | 129 +++ .../WebTestClientRequestSenderImpl.java | 644 ++++++++++++ ...WebTestClientRequestSpecificationImpl.java | 970 ++++++++++++++++++ .../WebTestClientRestAssuredResponseImpl.java | 46 + .../internal/WrapperWebTestClientFactory.java | 42 + .../RestAssuredWebTestClientMatchers.java | 229 +++++ .../ValidatableWebTestClientResponse.java | 30 + .../response/WebTestClientResponse.java | 26 + .../WebTestClientRequestLogSpecification.java | 35 + .../WebTestClientRequestSender.java | 147 +++ .../WebTestClientRequestSpecBuilder.java | 663 ++++++++++++ .../WebTestClientRequestSpecification.java | 929 +++++++++++++++++ .../module/webtestclient/BasePathTest.java | 108 ++ .../module/webtestclient/ContentTypeTest.java | 99 ++ .../module/webtestclient/ExtractTest.java | 44 + .../module/webtestclient/GetCookiesTest.java | 107 ++ .../module/webtestclient/GetTest.java | 47 + .../GreetingControllerRestAssuredTest.java | 96 ++ .../module/webtestclient/HeaderTest.java | 152 +++ .../LoggingIfValidationFailsTest.java | 213 ++++ .../module/webtestclient/ParserTest.java | 71 ++ .../module/webtestclient/PostTest.java | 81 ++ .../module/webtestclient/PutTest.java | 106 ++ .../module/webtestclient/QueryParamTest.java | 61 ++ .../webtestclient/RequestLoggingTest.java | 200 ++++ .../webtestclient/ResponseLoggingTest.java | 92 ++ .../module/webtestclient/RestDocsTest.java | 78 ++ .../webtestclient/ResultMatcherTest.java | 54 + .../webtestclient/SecuredRequestTest.java | 53 + .../module/webtestclient/SetCookiesTest.java | 59 ++ ...ntNonStaticRequestAndResponseSpecTest.java | 50 + .../WebTestClientParamConfigTest.java | 174 ++++ .../WebTestClientPathParamTest.java | 37 + .../WebTestClientRequestMethodTest.java | 122 +++ ...WebTestClientResponseAwareMatcherTest.java | 39 + .../WebTestClientResponseTimeTest.java | 56 + ...WebTestClientSpecificationMergingTest.java | 450 ++++++++ ...lientStaticRequestAndResponseSpecTest.java | 105 ++ .../setup/BasePathController.java | 41 + .../setup/ContentTypeProcessor.java | 41 + .../webtestclient/setup/CookieController.java | 33 + .../webtestclient/setup/CookieProcessor.java | 45 + .../module/webtestclient/setup/Greeting.java | 39 + .../setup/GreetingController.java | 54 + .../webtestclient/setup/HeaderController.java | 34 + .../setup/MultiValueController.java | 46 + .../webtestclient/setup/ParserController.java | 31 + .../webtestclient/setup/PostController.java | 49 + .../webtestclient/setup/PutController.java | 50 + .../setup/QueryParamsProcessor.java | 35 + .../setup/RedirectController.java | 36 + .../setup/ResponseAwareMatcherController.java | 48 + .../webtestclient/setup/SecuredProcessor.java | 37 + .../webtestclient/setup/support/Greeting.java | 62 ++ .../multipart/MultiPartInternal.groovy | 9 +- .../filter/log/RequestLoggingFilter.java | 44 +- .../io/restassured/filter/log/UrlDecoder.java | 67 ++ 91 files changed, 10419 insertions(+), 554 deletions(-) create mode 100644 modules/spring-commons/pom.xml create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/BodyHelper.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/CookieHelper.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/HeaderHelper.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamApplier.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamLogger.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/RequestLogger.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/Serializer.java rename modules/{spring-mock-mvc/src/main/java/io/restassured/module/mockmvc => spring-commons/src/main/java/io/restassured/module/spring/commons}/config/AsyncConfig.java (96%) create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ClientConfig.java rename modules/{spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal => spring-commons/src/main/java/io/restassured/module/spring/commons/config}/ConfigConverter.java (52%) create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigMergeUtils.java create mode 100644 modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/SpecificationConfig.java create mode 100644 modules/spring-web-test-client/pom.xml create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/RestAssuredWebTestClient.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/RestAssuredWebTestClientConfig.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientConfig.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientParamConfig.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/BuilderBasedWebTestClientFactory.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ExchangeResultConverter.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ResponseConverter.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/StandaloneWebTestClientFactory.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ValidatableWebTestClientResponseImpl.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientFactory.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestLogSpecificationImpl.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSenderImpl.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSpecificationImpl.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRestAssuredResponseImpl.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WrapperWebTestClientFactory.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/matcher/RestAssuredWebTestClientMatchers.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/ValidatableWebTestClientResponse.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/WebTestClientResponse.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestLogSpecification.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSender.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecBuilder.java create mode 100644 modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecification.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/BasePathTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ContentTypeTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ExtractTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetCookiesTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GreetingControllerRestAssuredTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/HeaderTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/LoggingIfValidationFailsTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ParserTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PostTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PutTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/QueryParamTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RequestLoggingTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResponseLoggingTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RestDocsTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResultMatcherTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SecuredRequestTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SetCookiesTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientNonStaticRequestAndResponseSpecTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientParamConfigTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientPathParamTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientRequestMethodTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseAwareMatcherTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseTimeTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientSpecificationMergingTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientStaticRequestAndResponseSpecTest.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/BasePathController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ContentTypeProcessor.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieProcessor.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/Greeting.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/GreetingController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/HeaderController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/MultiValueController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ParserController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PostController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PutController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/QueryParamsProcessor.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/RedirectController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ResponseAwareMatcherController.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/SecuredProcessor.java create mode 100644 modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/support/Greeting.java create mode 100644 rest-assured/src/main/java/io/restassured/filter/log/UrlDecoder.java diff --git a/modules/pom.xml b/modules/pom.xml index b21d530bc..98f75eb0f 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -1,6 +1,6 @@ + + + 4.0.0 + + io.rest-assured + modules + 3.1.2-SNAPSHOT + + spring-commons + 3.1.2-SNAPSHOT + spring-commons + http://maven.apache.org + + UTF-8 + 5.0.9.RELEASE + + + + + io.rest-assured + rest-assured + 3.1.2-SNAPSHOT + + + \ No newline at end of file diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/BodyHelper.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/BodyHelper.java new file mode 100644 index 000000000..7ea59ed6f --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/BodyHelper.java @@ -0,0 +1,84 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import io.restassured.http.Headers; +import io.restassured.internal.mapping.ObjectMapperSerializationContextImpl; +import io.restassured.internal.mapping.ObjectMapping; +import io.restassured.mapper.ObjectMapper; +import io.restassured.module.spring.commons.config.SpecificationConfig; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import static io.restassured.internal.serialization.SerializationSupport.isSerializableCandidate; + +public class BodyHelper { + + private BodyHelper() { + } + + public static String toStringBody(Object object, SpecificationConfig config, Headers headers) { + if (!isSerializableCandidate(object)) { + return object.toString(); + } + String requestContentType = HeaderHelper.getRequestContentType(headers); + return ObjectMapping.serialize(object, requestContentType, + Serializer.findEncoderCharsetOrReturnDefault(requestContentType, config), null, + config.getObjectMapperConfig(), config.getEncoderConfig()); + } + + public static Object toSerializedBody(Object object, ObjectMapper objectMapper, SpecificationConfig config, + Headers headers) { + String requestContentType = HeaderHelper.getRequestContentType(headers); + ObjectMapperSerializationContextImpl ctx = new ObjectMapperSerializationContextImpl(); + ctx.setObject(object); + ctx.setCharset(Serializer.findEncoderCharsetOrReturnDefault(requestContentType, config)); + ctx.setContentType(requestContentType); + return objectMapper.serialize(ctx); + } + + public static byte[] toByteArray(File file) { + ByteArrayOutputStream ous = null; + InputStream ios = null; + try { + byte[] buffer = new byte[4096]; + ous = new ByteArrayOutputStream(); + ios = new FileInputStream(file); + int read = 0; + while ((read = ios.read(buffer)) != -1) { + ous.write(buffer, 0, read); + } + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + if (ous != null) { + ous.close(); + } + if (ios != null) { + ios.close(); + } + } catch (IOException ignored) { + } + } + + return ous.toByteArray(); + } +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/CookieHelper.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/CookieHelper.java new file mode 100644 index 000000000..cf6812c68 --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/CookieHelper.java @@ -0,0 +1,88 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Headers; +import io.restassured.module.spring.commons.config.SpecificationConfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class CookieHelper { + + private CookieHelper() { + } + + public static Cookies cookies(Cookies requestCookies, Map cookies, Headers requestHeaders, + SpecificationConfig config) { + List cookieList = new ArrayList(); + if (requestCookies.exist()) { + for (Cookie requestCookie : requestCookies) { + cookieList.add(requestCookie); + } + } + for (Map.Entry stringEntry : cookies.entrySet()) { + cookieList.add(new Cookie.Builder(stringEntry.getKey(), Serializer.serializeIfNeeded(stringEntry.getValue(), + HeaderHelper.getRequestContentType(requestHeaders), config)).build()); + } + return new Cookies(cookieList); + } + + public static Cookies cookies(Cookies requestCookies, Cookies cookies) { + if (cookies.exist()) { + List cookieList = new ArrayList(); + if (requestCookies.exist()) { + for (Cookie cookie : requestCookies) { + cookieList.add(cookie); + } + } + for (Cookie cookie : cookies) { + cookieList.add(cookie); + } + return new Cookies(cookieList); + } + return requestCookies; + } + + public static Cookies cookie(final String cookieName, final Object cookieValue, Headers requestHeaders, + final SpecificationConfig config, Object... additionalValues) { + final String contentType = HeaderHelper.getRequestContentType(requestHeaders); + List cookieList = new ArrayList() {{ + add(new Cookie.Builder(cookieName, Serializer.serializeIfNeeded(cookieValue, contentType, config)).build()); + }}; + if (additionalValues != null) { + for (Object additionalCookieValue : additionalValues) { + cookieList.add(new Cookie.Builder(cookieName, + Serializer.serializeIfNeeded(additionalCookieValue, contentType, config)).build()); + } + } + return new Cookies(cookieList); + } + + public static Cookies sessionId(Cookies cookies, String sessionIdName, String sessionIdValue) { + List allOtherCookies = new ArrayList(); + for (Cookie cookie : cookies) { + if (!cookie.getName().equalsIgnoreCase(sessionIdName)) { + allOtherCookies.add(cookie); + } + } + allOtherCookies.add(new Cookie.Builder(sessionIdName, sessionIdValue).build()); + return new Cookies(allOtherCookies); + } +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/HeaderHelper.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/HeaderHelper.java new file mode 100644 index 000000000..518e631ef --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/HeaderHelper.java @@ -0,0 +1,175 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import io.restassured.config.EncoderConfig; +import io.restassured.config.HeaderConfig; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.module.spring.commons.config.SpecificationConfig; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static io.restassured.internal.assertion.AssertParameter.notNull; + +public class HeaderHelper { + + private static final String CONTENT_TYPE = "Content-Type"; + private static final String CHARSET = "charset"; + + private HeaderHelper() { + } + + public static Headers headers(Headers requestHeaders, Map headers, SpecificationConfig config) { + notNull(headers, "headers"); + List
headerList = new ArrayList
(); + if (requestHeaders.exist()) { + for (Header requestHeader : requestHeaders) { + headerList.add(requestHeader); + } + } + + for (Map.Entry stringEntry : headers.entrySet()) { + Object value = stringEntry.getValue(); + if (value instanceof List) { + List values = (List) value; + for (Object headerValue : values) { + headerList.add(new Header(stringEntry.getKey(), Serializer.serializeIfNeeded(headerValue, + getRequestContentType(requestHeaders), config))); + } + } else { + headerList.add(new Header(stringEntry.getKey(), Serializer.serializeIfNeeded(value, + getRequestContentType(requestHeaders), config))); + } + } + return new Headers(headerList); + } + + public static String getRequestContentType(Headers requestHeaders) { + Header header = requestHeaders.get(CONTENT_TYPE); + if (header != null) { + return header.getValue(); + } + return null; + } + + public static Headers headers(Headers requestHeaders, Headers headersToAdd, HeaderConfig headerConfig) { + notNull(headersToAdd, "Headers"); + if (headersToAdd.exist()) { + List
headerList = new ArrayList
(); + if (requestHeaders.exist()) { + for (Header requestHeader : requestHeaders) { + headerList.add(requestHeader); + } + } + + for (Header requestHeader : headersToAdd) { + headerList.add(requestHeader); + } + return new Headers(removeMergedHeadersIfNeeded(headerList, headerConfig)); + } + return requestHeaders; + } + + // TODO Extract content-type from headers and apply charset if needed! + public static String findContentType(Headers headers, List multiParts, SpecificationConfig config) { + String requestContentType = headers.getValue(CONTENT_TYPE); + if (StringUtils.isBlank(requestContentType) && !multiParts.isEmpty()) { + requestContentType = "multipart/" + config.getMultiPartConfig().defaultSubtype(); + } + + EncoderConfig encoderConfig = config.getEncoderConfig(); + if (requestContentType != null && encoderConfig.shouldAppendDefaultContentCharsetToContentTypeIfUndefined() && !StringUtils.containsIgnoreCase(requestContentType, CHARSET)) { + // Append default charset to request content type + requestContentType += "; charset="; + if (encoderConfig.hasDefaultCharsetForContentType(requestContentType)) { + requestContentType += encoderConfig.defaultCharsetForContentType(requestContentType); + } else { + requestContentType += encoderConfig.defaultContentCharset(); + } + } + return requestContentType; + } + + public static String buildApplicationFormEncodedContentType(SpecificationConfig config, String baseContentType) { + String contentType = baseContentType; + EncoderConfig encoderConfig = config.getEncoderConfig(); + if (encoderConfig.shouldAppendDefaultContentCharsetToContentTypeIfUndefined()) { + contentType += "; charset="; + if (encoderConfig.hasDefaultCharsetForContentType(contentType)) { + contentType += encoderConfig.defaultCharsetForContentType(contentType); + } else { + contentType += encoderConfig.defaultContentCharset(); + + } + } + return contentType; + } + + public static Object[] mapToArray(Map map) { + if (map == null) { + return new Object[0]; + } + return map.values().toArray(new Object[map.values().size()]); + } + + private static List
removeMergedHeadersIfNeeded(List
headerList, HeaderConfig headerConfig) { + List
filteredList = new ArrayList
(); + for (Header header : headerList) { + String headerName = header.getName(); + if (headerConfig.shouldOverwriteHeaderWithName(headerName)) { + int index = -1; + for (int i = 0; i < filteredList.size(); i++) { + Header filteredHeader = filteredList.get(i); + if (filteredHeader.hasSameNameAs(header)) { + index = i; + break; + } + } + + if (index != -1) { + filteredList.remove(index); + } + } + + filteredList.add(header); + } + return filteredList; + } + + public static Headers headers(final Headers requestHeaders, final String headerName, final Object headerValue, + final SpecificationConfig config, + Object... additionalHeaderValues) { + notNull(headerName, "Header name"); + notNull(headerValue, "Header value"); + + List
headerList = new ArrayList
() {{ + add(new Header(headerName, Serializer.serializeIfNeeded(headerValue, + getRequestContentType(requestHeaders), config))); + }}; + + if (additionalHeaderValues != null) { + for (Object additionalHeaderValue : additionalHeaderValues) { + headerList.add(new Header(headerName, Serializer.serializeIfNeeded(additionalHeaderValue, + getRequestContentType(requestHeaders), config))); + } + } + return new Headers(headerList); + } +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamApplier.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamApplier.java new file mode 100644 index 000000000..fd38e1af0 --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamApplier.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import java.util.Collection; +import java.util.Map; + +public abstract class ParamApplier { + + private Map map; + + protected ParamApplier(Map parameters) { + this.map = parameters; + } + + public void applyParams() { + for (Map.Entry listEntry : map.entrySet()) { + Object value = listEntry.getValue(); + String[] stringValues; + if (value instanceof Collection) { + Collection col = (Collection) value; + stringValues = new String[col.size()]; + int index = 0; + for (Object val : col) { + stringValues[index] = val == null ? null : val.toString(); + index++; + } + } else { + stringValues = new String[1]; + stringValues[0] = value == null ? null : value.toString(); + } + applyParam(listEntry.getKey(), stringValues); + } + } + + protected abstract void applyParam(String paramName, String[] paramValues); +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamLogger.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamLogger.java new file mode 100644 index 000000000..24e4b813a --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/ParamLogger.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +public abstract class ParamLogger { + + private Map map; + + protected ParamLogger(Map parameters) { + this.map = parameters; + } + + public void logParams() { + for (Map.Entry stringListEntry : map.entrySet()) { + Object value = stringListEntry.getValue(); + Collection values; + if (value instanceof Collection) { + values = (Collection) value; + } else { + values = new ArrayList(); + values.add(value); + } + + for (Object theValue : values) { + logParam(stringListEntry.getKey(), theValue); + } + } + } + + protected abstract void logParam(String paramName, Object paramValue); +} \ No newline at end of file diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/RequestLogger.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/RequestLogger.java new file mode 100644 index 000000000..2734a5647 --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/RequestLogger.java @@ -0,0 +1,129 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.internal.RequestSpecificationImpl; +import io.restassured.internal.http.CharsetExtractor; +import io.restassured.module.spring.commons.config.SpecificationConfig; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import static org.apache.commons.lang3.SystemUtils.LINE_SEPARATOR; + +public class RequestLogger { + + public static void logParamsAndHeaders(final RequestSpecificationImpl reqSpec, String method, String uri, + Object[] unnamedPathParams, Map params, Map queryParams, Map formParams, + Headers headers, Cookies cookies) { + reqSpec.setMethod(method); + reqSpec.path(uri); + reqSpec.buildUnnamedPathParameterTuples(unnamedPathParams); + if (params != null) { + new ParamLogger(params) { + protected void logParam(String paramName, Object paramValue) { + reqSpec.param(paramName, paramValue); + } + }.logParams(); + } + + if (queryParams != null) { + new ParamLogger(queryParams) { + protected void logParam(String paramName, Object paramValue) { + reqSpec.queryParam(paramName, paramValue); + } + }.logParams(); + } + + if (formParams != null) { + new ParamLogger(formParams) { + protected void logParam(String paramName, Object paramValue) { + reqSpec.formParam(paramName, paramValue); + } + }.logParams(); + } + + if (headers != null) { + for (Header header : headers) { + reqSpec.header(header); + } + } + + if (cookies != null) { + for (Cookie cookie : cookies) { + reqSpec.cookie(cookie); + } + } + } + + public static void logRequestBody(RequestSpecificationImpl reqSpec, Object requestBody, Headers headers, + List multiParts, SpecificationConfig config) { + if (requestBody != null) { + if (requestBody instanceof byte[]) { + reqSpec.body((byte[]) requestBody); + } else if (requestBody instanceof File) { + String contentType = HeaderHelper.findContentType(headers, multiParts, config); + RequestLogger.logFileRequestBody(reqSpec, requestBody, contentType); + } else { + reqSpec.body(requestBody); + } + } + } + + public static void logFileRequestBody(RequestSpecificationImpl reqSpec, Object requestBody, String contentType) { + String charset = null; + if (StringUtils.isNotBlank(contentType)) { + charset = CharsetExtractor.getCharsetFromContentType(contentType); + } + + if (charset == null) { + charset = Charset.defaultCharset().toString(); + } + + String string = fileToString((File) requestBody, charset); + reqSpec.body(string); + } + + private static String fileToString(File file, String charset) { + StringBuilder fileContents = new StringBuilder((int) file.length()); + Scanner scanner; + try { + scanner = new Scanner(file, charset); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + String lineSeparator = System.getProperty(LINE_SEPARATOR); + + try { + while (scanner.hasNextLine()) { + fileContents.append(scanner.nextLine()).append(lineSeparator); + } + return fileContents.toString(); + } finally { + scanner.close(); + } + } +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/Serializer.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/Serializer.java new file mode 100644 index 000000000..36f3d32c4 --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/Serializer.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons; + +import io.restassured.config.EncoderConfig; +import io.restassured.internal.http.CharsetExtractor; +import io.restassured.internal.mapping.ObjectMapping; +import io.restassured.module.spring.commons.config.SpecificationConfig; + +import static io.restassured.internal.serialization.SerializationSupport.isSerializableCandidate; + +public class Serializer { + + private Serializer() { + } + + public static String serializeIfNeeded(Object object, String contentType, SpecificationConfig config) { + return isSerializableCandidate(object) ? ObjectMapping.serialize(object, contentType, + findEncoderCharsetOrReturnDefault(contentType, config), null, config.getObjectMapperConfig(), + config.getEncoderConfig()) : object.toString(); + } + + public static String findEncoderCharsetOrReturnDefault(String contentType, SpecificationConfig config) { + String charset = CharsetExtractor.getCharsetFromContentType(contentType); + if (charset == null) { + EncoderConfig encoderConfig = config.getEncoderConfig(); + if (encoderConfig.hasDefaultCharsetForContentType(contentType)) { + charset = encoderConfig.defaultCharsetForContentType(contentType); + } else { + charset = encoderConfig.defaultContentCharset(); + } + } + return charset; + } +} diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/AsyncConfig.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/AsyncConfig.java similarity index 96% rename from modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/AsyncConfig.java rename to modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/AsyncConfig.java index 7dce6b348..bc2c1d96a 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/AsyncConfig.java +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/AsyncConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2018 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.restassured.module.mockmvc.config; +package io.restassured.module.spring.commons.config; import io.restassured.config.Config; @@ -66,6 +66,19 @@ private AsyncConfig(long duration, TimeUnit timeUnit, boolean isUserConfigured) this.userConfigured = isUserConfigured; } + public static AsyncConfig withTimeout(long duration, TimeUnit timeUnit) { + return new AsyncConfig(timeUnit.toMillis(duration)); + } + + /** + * Just syntactic sugar. + * + * @return A new instance of {@link AsyncConfig}. + */ + public static AsyncConfig asyncConfig() { + return new AsyncConfig(); + } + /** * Specify the timeout for the async request in milliseconds. * @@ -98,23 +111,10 @@ public boolean isUserConfigured() { return userConfigured; } - public static AsyncConfig withTimeout(long duration, TimeUnit timeUnit) { - return new AsyncConfig(timeUnit.toMillis(duration)); - } - /** * Just syntactic sugar to make the DSL more english like. */ public AsyncConfig with() { return this; } - - /** - * Just syntactic sugar. - * - * @return A new instance of {@link AsyncConfig}. - */ - public static AsyncConfig asyncConfig() { - return new AsyncConfig(); - } } diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ClientConfig.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ClientConfig.java new file mode 100644 index 000000000..2747a6faa --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ClientConfig.java @@ -0,0 +1,23 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons.config; + +public interface ClientConfig { + + boolean isUserConfigured(); + +} diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/ConfigConverter.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigConverter.java similarity index 52% rename from modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/ConfigConverter.java rename to modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigConverter.java index 32832c14a..8c242ba8a 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/ConfigConverter.java +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2018 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. @@ -14,30 +14,26 @@ * limitations under the License. */ -package io.restassured.module.mockmvc.internal; +package io.restassured.module.spring.commons.config; import io.restassured.config.ParamConfig; import io.restassured.config.RestAssuredConfig; -import io.restassured.module.mockmvc.config.MockMvcParamConfig; -import io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig; import java.lang.reflect.Field; -import static io.restassured.module.mockmvc.internal.UpdateStrategyConverter.convert; +public class ConfigConverter { -class ConfigConverter { - - public static RestAssuredConfig convertToRestAssuredConfig(RestAssuredMockMvcConfig mvcConfig) { - return new RestAssuredConfig().jsonConfig(mvcConfig.getJsonConfig()).xmlConfig(mvcConfig.getXmlConfig()).sessionConfig(mvcConfig.getSessionConfig()). - objectMapperConfig(mvcConfig.getObjectMapperConfig()).logConfig(mvcConfig.getLogConfig()).encoderConfig(mvcConfig.getEncoderConfig()). - decoderConfig(mvcConfig.getDecoderConfig()).multiPartConfig(mvcConfig.getMultiPartConfig()).paramConfig(toParamConfig(mvcConfig.getParamConfig())); + public static RestAssuredConfig convertToRestAssuredConfig(SpecificationConfig specificationConfig) { + return new RestAssuredConfig().jsonConfig(specificationConfig.getJsonConfig()).xmlConfig(specificationConfig.getXmlConfig()).sessionConfig(specificationConfig.getSessionConfig()). + objectMapperConfig(specificationConfig.getObjectMapperConfig()).logConfig(specificationConfig.getLogConfig()).encoderConfig(specificationConfig.getEncoderConfig()). + decoderConfig(specificationConfig.getDecoderConfig()).multiPartConfig(specificationConfig.getMultiPartConfig()).paramConfig(toParamConfig(specificationConfig.getParamConfig())); } - private static ParamConfig toParamConfig(MockMvcParamConfig cfg) { - ParamConfig config = new ParamConfig(convert(cfg.queryParamsUpdateStrategy()), - convert(cfg.formParamsUpdateStrategy()), convert(cfg.requestParamsUpdateStrategy())); + private static ParamConfig toParamConfig(ParamConfig baseConfig) { + ParamConfig config = new ParamConfig(baseConfig.queryParamsUpdateStrategy(), + baseConfig.formParamsUpdateStrategy(), baseConfig.requestParamsUpdateStrategy()); // We need to set the user configured flag to false if needed - if (!cfg.isUserConfigured()) { + if (!baseConfig.isUserConfigured()) { Field userConfigured = null; try { userConfigured = config.getClass().getDeclaredField("userConfigured"); diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigMergeUtils.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigMergeUtils.java new file mode 100644 index 000000000..1897e620f --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/ConfigMergeUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons.config; + +public class ConfigMergeUtils { + + public static SpecificationConfig mergeConfig(SpecificationConfig base, SpecificationConfig toMerge) { + boolean thisIsUserConfigured = base.isUserConfigured(); + boolean otherIsUserConfigured = toMerge.isUserConfigured(); + if (!otherIsUserConfigured) { + return base; + } + if (thisIsUserConfigured) { + if (toMerge.getDecoderConfig().isUserConfigured()) { + base = base.decoderConfig(toMerge.getDecoderConfig()); + } + + if (toMerge.getEncoderConfig().isUserConfigured()) { + base = base.encoderConfig(toMerge.getEncoderConfig()); + } + + if (toMerge.getHeaderConfig().isUserConfigured()) { + base = base.headerConfig(toMerge.getHeaderConfig()); + } + + if (toMerge.getJsonConfig().isUserConfigured()) { + base = base.jsonConfig(toMerge.getJsonConfig()); + } + + if (toMerge.getLogConfig().isUserConfigured()) { + base = base.logConfig(toMerge.getLogConfig()); + } + + if (toMerge.getObjectMapperConfig().isUserConfigured()) { + base = base.objectMapperConfig(toMerge.getObjectMapperConfig()); + } + + if (toMerge.getSessionConfig().isUserConfigured()) { + base = base.sessionConfig(toMerge.getSessionConfig()); + } + + if (toMerge.getXmlConfig().isUserConfigured()) { + base = base.xmlConfig(toMerge.getXmlConfig()); + } + + if (toMerge.getAsyncConfig().isUserConfigured()) { + base = base.asyncConfig(toMerge.getAsyncConfig()); + } + + if (toMerge.getMultiPartConfig().isUserConfigured()) { + base = base.multiPartConfig(toMerge.getMultiPartConfig()); + } + + if (toMerge.getClientConfig().isUserConfigured()) { + base = base.clientConfig(toMerge.getClientConfig()); + } + + if (toMerge.getParamConfig().isUserConfigured()) { + base = base.paramConfig(toMerge.getParamConfig()); + } + + return base; + } else { + return toMerge; + } + } +} diff --git a/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/SpecificationConfig.java b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/SpecificationConfig.java new file mode 100644 index 000000000..25d942f18 --- /dev/null +++ b/modules/spring-commons/src/main/java/io/restassured/module/spring/commons/config/SpecificationConfig.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.spring.commons.config; + +import io.restassured.config.DecoderConfig; +import io.restassured.config.EncoderConfig; +import io.restassured.config.HeaderConfig; +import io.restassured.config.JsonConfig; +import io.restassured.config.LogConfig; +import io.restassured.config.MultiPartConfig; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.config.ParamConfig; +import io.restassured.config.SessionConfig; +import io.restassured.config.XmlConfig; + +public interface SpecificationConfig { + + boolean isUserConfigured(); + + DecoderConfig getDecoderConfig(); + + SpecificationConfig decoderConfig(DecoderConfig decoderConfig); + + EncoderConfig getEncoderConfig(); + + SpecificationConfig encoderConfig(EncoderConfig encoderConfig); + + HeaderConfig getHeaderConfig(); + + SpecificationConfig headerConfig(HeaderConfig headerConfig); + + JsonConfig getJsonConfig(); + + SpecificationConfig jsonConfig(JsonConfig jsonConfig); + + LogConfig getLogConfig(); + + SpecificationConfig logConfig(LogConfig logConfig); + + ObjectMapperConfig getObjectMapperConfig(); + + SpecificationConfig objectMapperConfig(ObjectMapperConfig objectMapperConfig); + + SessionConfig getSessionConfig(); + + SpecificationConfig sessionConfig(SessionConfig sessionConfig); + + XmlConfig getXmlConfig(); + + SpecificationConfig xmlConfig(XmlConfig xmlConfig); + + AsyncConfig getAsyncConfig(); + + SpecificationConfig asyncConfig(AsyncConfig asyncConfig); + + MultiPartConfig getMultiPartConfig(); + + SpecificationConfig multiPartConfig(MultiPartConfig multiPartConfig); + + ClientConfig getClientConfig(); + + SpecificationConfig clientConfig(ClientConfig clientConfig); + + ParamConfig getParamConfig(); + + SpecificationConfig paramConfig(ParamConfig paramConfig); + +} diff --git a/modules/spring-mock-mvc/pom.xml b/modules/spring-mock-mvc/pom.xml index 08392fd36..474d708c3 100644 --- a/modules/spring-mock-mvc/pom.xml +++ b/modules/spring-mock-mvc/pom.xml @@ -38,6 +38,11 @@ rest-assured 3.1.2-SNAPSHOT + + io.rest-assured + spring-commons + 3.1.2-SNAPSHOT + org.springframework spring-test diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcConfig.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcConfig.java index 65091e0e9..d6dd2874c 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcConfig.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcConfig.java @@ -18,6 +18,8 @@ import io.restassured.config.Config; import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification; +import io.restassured.module.spring.commons.config.ClientConfig; + import org.springframework.test.web.servlet.MockMvcBuilder; import org.springframework.test.web.servlet.setup.MockMvcConfigurer; import org.springframework.web.context.WebApplicationContext; @@ -25,7 +27,7 @@ /** * General configuration of the Spring Mock MVC module */ -public class MockMvcConfig implements Config { +public class MockMvcConfig implements ClientConfig, Config { private final boolean userConfigured; private final boolean automaticallyApplySpringSecurityMockMvcConfigurer; diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcParamConfig.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcParamConfig.java index d3dea6124..5d64c83c2 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcParamConfig.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/MockMvcParamConfig.java @@ -17,16 +17,17 @@ package io.restassured.module.mockmvc.config; import io.restassured.config.Config; +import io.restassured.config.ParamConfig; +import static io.restassured.config.ParamConfig.UpdateStrategy.MERGE; +import static io.restassured.config.ParamConfig.UpdateStrategy.REPLACE; import static io.restassured.internal.assertion.AssertParameter.notNull; -import static io.restassured.module.mockmvc.config.MockMvcParamConfig.UpdateStrategy.MERGE; -import static io.restassured.module.mockmvc.config.MockMvcParamConfig.UpdateStrategy.REPLACE; /** * Determines how different parameter types in REST Assured MockMvc should be updated when adding multiple parameters * of the same type with the same name. */ -public class MockMvcParamConfig implements Config { +public class MockMvcParamConfig extends ParamConfig implements Config { private final boolean userConfigured; private final UpdateStrategy queryParamsUpdateStrategy; @@ -188,21 +189,6 @@ public boolean isUserConfigured() { return userConfigured; } - /** - * The update strategy to use for a parameter type - */ - public enum UpdateStrategy { - /** - * Parameters with the same name is merged. - */ - MERGE, - /** - * Parameters with the same name is replaced with the latest applied value. - */ - REPLACE - } - - /** * @return A static way to create a new MockMvcParamConfig instance without calling "new" explicitly. Mainly for syntactic sugar. */ diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/RestAssuredMockMvcConfig.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/RestAssuredMockMvcConfig.java index 094c842ad..b6a59960e 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/RestAssuredMockMvcConfig.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/config/RestAssuredMockMvcConfig.java @@ -16,7 +16,19 @@ package io.restassured.module.mockmvc.config; -import io.restassured.config.*; +import io.restassured.config.DecoderConfig; +import io.restassured.config.EncoderConfig; +import io.restassured.config.HeaderConfig; +import io.restassured.config.JsonConfig; +import io.restassured.config.LogConfig; +import io.restassured.config.MultiPartConfig; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.config.ParamConfig; +import io.restassured.config.SessionConfig; +import io.restassured.config.XmlConfig; +import io.restassured.module.spring.commons.config.AsyncConfig; +import io.restassured.module.spring.commons.config.ClientConfig; +import io.restassured.module.spring.commons.config.SpecificationConfig; import static io.restassured.internal.assertion.AssertParameter.notNull; @@ -29,7 +41,7 @@ * *

*/ -public class RestAssuredMockMvcConfig implements Config { +public class RestAssuredMockMvcConfig implements SpecificationConfig { // When adding a config here don't forget to update isUserConfigured method private final LogConfig logConfig; @@ -223,6 +235,17 @@ public RestAssuredMockMvcConfig multiPartConfig(MultiPartConfig multiPartConfig) objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, mockMvcConfig, paramConfig); } + public ClientConfig getClientConfig() { + return getMockMvcConfig(); + } + + public SpecificationConfig clientConfig(ClientConfig clientConfig) { + if (!(clientConfig instanceof MockMvcConfig)) { + throw new IllegalArgumentException("Wrong ClientConfig type supplied"); + } + return mockMvcConfig((MockMvcConfig) clientConfig); + } + /** * Set the parameter config * @@ -335,7 +358,18 @@ public MultiPartConfig getMultiPartConfig() { /** * @return The Param Config */ - public MockMvcParamConfig getParamConfig() { + public ParamConfig getParamConfig() { + return paramConfig; + } + + public SpecificationConfig paramConfig(ParamConfig paramConfig) { + if (!(paramConfig instanceof MockMvcParamConfig)) { + throw new IllegalArgumentException("Wrong ClientConfig type supplied"); + } + return paramConfig((MockMvcParamConfig) paramConfig); + } + + public MockMvcParamConfig getMockMvcParamConfig() { return paramConfig; } diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcFactory.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcFactory.java index 404f57a54..fcdc86475 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcFactory.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcFactory.java @@ -17,6 +17,7 @@ package io.restassured.module.mockmvc.internal; import io.restassured.module.mockmvc.config.MockMvcConfig; + import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvcBuilder; import org.springframework.test.web.servlet.request.RequestPostProcessor; diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSenderImpl.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSenderImpl.java index 3eedb8e86..a319b3d7d 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSenderImpl.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSenderImpl.java @@ -16,31 +16,54 @@ package io.restassured.module.mockmvc.internal; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + import io.restassured.RestAssured; import io.restassured.authentication.NoAuthScheme; import io.restassured.builder.MultiPartSpecBuilder; -import io.restassured.config.EncoderConfig; import io.restassured.filter.Filter; import io.restassured.filter.log.RequestLoggingFilter; import io.restassured.filter.time.TimingFilter; -import io.restassured.http.*; +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.http.Method; import io.restassured.internal.RequestSpecificationImpl; import io.restassured.internal.ResponseParserRegistrar; import io.restassured.internal.ResponseSpecificationImpl; import io.restassured.internal.filter.FilterContextImpl; -import io.restassured.internal.http.CharsetExtractor; import io.restassured.internal.log.LogRepository; import io.restassured.internal.support.PathSupport; import io.restassured.internal.util.SafeExceptionRethrower; -import io.restassured.module.mockmvc.config.AsyncConfig; import io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig; import io.restassured.module.mockmvc.intercept.MockHttpServletRequestBuilderInterceptor; import io.restassured.module.mockmvc.response.MockMvcResponse; import io.restassured.module.mockmvc.specification.MockMvcRequestAsyncConfigurer; import io.restassured.module.mockmvc.specification.MockMvcRequestAsyncSender; import io.restassured.module.mockmvc.specification.MockMvcRequestSender; +import io.restassured.module.spring.commons.BodyHelper; +import io.restassured.module.spring.commons.HeaderHelper; +import io.restassured.module.spring.commons.ParamApplier; +import io.restassured.module.spring.commons.config.AsyncConfig; +import io.restassured.module.spring.commons.config.ConfigConverter; import io.restassured.specification.ResponseSpecification; import org.apache.commons.lang3.StringUtils; + import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; @@ -56,27 +79,27 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.web.util.UriComponentsBuilder; -import java.io.*; -import java.net.URI; -import java.net.URL; -import java.nio.charset.Charset; -import java.security.Principal; -import java.util.*; -import java.util.concurrent.TimeUnit; - import static io.restassured.internal.assertion.AssertParameter.notNull; import static io.restassured.internal.support.PathSupport.mergeAndRemoveDoubleSlash; import static io.restassured.module.mockmvc.internal.SpringSecurityClassPathChecker.isSpringSecurityInClasspath; +import static io.restassured.module.spring.commons.HeaderHelper.mapToArray; +import static io.restassured.module.spring.commons.RequestLogger.logParamsAndHeaders; +import static io.restassured.module.spring.commons.RequestLogger.logRequestBody; import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.trimToNull; -import static org.springframework.http.HttpMethod.*; +import static org.springframework.http.HttpMethod.DELETE; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.HEAD; +import static org.springframework.http.HttpMethod.OPTIONS; +import static org.springframework.http.HttpMethod.PATCH; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.http.HttpMethod.PUT; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; class MockMvcRequestSenderImpl implements MockMvcRequestSender, MockMvcRequestAsyncConfigurer, MockMvcRequestAsyncSender { private static final String ATTRIBUTE_NAME_URL_TEMPLATE = "org.springframework.restdocs.urlTemplate"; private static final String CONTENT_TYPE = "Content-Type"; - private static final String CHARSET = "charset"; private static final String LINE_SEPARATOR = "line.separator"; private final MockMvc mockMvc; @@ -242,7 +265,7 @@ private MvcResult getMvcResult(ResultActions perform, boolean isAsyncRequest) th } private ResponseParserRegistrar getRpr() { - if (responseSpecification != null && responseSpecification instanceof ResponseSpecificationImpl) { + if (responseSpecification instanceof ResponseSpecificationImpl) { return ((ResponseSpecificationImpl) responseSpecification).getRpr(); } return new ResponseParserRegistrar(); @@ -259,13 +282,6 @@ private String assembleStatusLine(MockHttpServletResponse response, Exception re return builder.toString(); } - private Object[] mapToArray(Map map) { - if (map == null) { - return new Object[0]; - } - return map.values().toArray(new Object[map.values().size()]); - } - private MockMvcResponse sendRequest(HttpMethod method, String path, Object[] pathParams) { notNull(path, "Path"); if (requestBody != null && !multiParts.isEmpty()) { @@ -299,7 +315,7 @@ protected void applyParam(String paramName, String[] paramValues) { request = MockMvcRequestBuilders.fileUpload(uri, pathParams); } - String requestContentType = findContentType(); + String requestContentType = HeaderHelper.findContentType(headers, (List) (List) multiParts, config); if (!params.isEmpty()) { new ParamApplier(params) { @@ -419,7 +435,7 @@ protected void applyParam(String paramName, String[] paramValues) { if (requestBody instanceof byte[]) { request.content((byte[]) requestBody); } else if (requestBody instanceof File) { - byte[] bytes = toByteArray((File) requestBody); + byte[] bytes = BodyHelper.toByteArray((File) requestBody); request.content(bytes); } else { request.content(requestBody.toString()); @@ -431,68 +447,8 @@ protected void applyParam(String paramName, String[] paramValues) { return performRequest(request); } - // TODO Extract content-type from headers and apply charset if needed! - private String findContentType() { - String requestContentType = headers.getValue(CONTENT_TYPE); - if (StringUtils.isBlank(requestContentType) && !multiParts.isEmpty()) { - requestContentType = "multipart/" + config.getMultiPartConfig().defaultSubtype(); - } - - EncoderConfig encoderConfig = config.getEncoderConfig(); - if (requestContentType != null && encoderConfig.shouldAppendDefaultContentCharsetToContentTypeIfUndefined() && !StringUtils.containsIgnoreCase(requestContentType, CHARSET)) { - // Append default charset to request content type - requestContentType += "; charset="; - if (encoderConfig.hasDefaultCharsetForContentType(requestContentType)) { - requestContentType += encoderConfig.defaultCharsetForContentType(requestContentType); - } else { - requestContentType += encoderConfig.defaultContentCharset(); - } - } - return requestContentType; - } - - - private static byte[] toByteArray(File file) { - ByteArrayOutputStream ous = null; - InputStream ios = null; - try { - byte[] buffer = new byte[4096]; - ous = new ByteArrayOutputStream(); - ios = new FileInputStream(file); - int read = 0; - while ((read = ios.read(buffer)) != -1) { - ous.write(buffer, 0, read); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - try { - if (ous != null) { - ous.close(); - } - if (ios != null) { - ios.close(); - } - } catch (IOException ignored) { - } - } - - return ous.toByteArray(); - } - private void setContentTypeToApplicationFormUrlEncoded(MockHttpServletRequestBuilder request) { - String contentType = APPLICATION_FORM_URLENCODED_VALUE; - EncoderConfig encoderConfig = config.getEncoderConfig(); - if (encoderConfig.shouldAppendDefaultContentCharsetToContentTypeIfUndefined()) { - contentType += "; charset="; - if (encoderConfig.hasDefaultCharsetForContentType(contentType)) { - contentType += encoderConfig.defaultCharsetForContentType(contentType); - } else { - contentType += encoderConfig.defaultContentCharset(); - - } - } - MediaType mediaType = MediaType.parseMediaType(contentType); + MediaType mediaType = MediaType.parseMediaType(HeaderHelper.buildApplicationFormEncodedContentType(config, APPLICATION_FORM_URLENCODED_VALUE)); request.contentType(mediaType); List
newHeaders = new ArrayList
(headers.asList()); newHeaders.add(new Header(CONTENT_TYPE, mediaType.toString())); @@ -510,65 +466,8 @@ private void logRequestIfApplicable(HttpMethod method, String uri, String origin final RequestSpecificationImpl reqSpec = new RequestSpecificationImpl("http://localhost", RestAssured.UNDEFINED_PORT, "", new NoAuthScheme(), Collections.emptyList(), null, true, ConfigConverter.convertToRestAssuredConfig(config), logRepository, null); - reqSpec.setMethod(method.toString()); - reqSpec.path(uri); - reqSpec.buildUnnamedPathParameterTuples(unnamedPathParams); - if (params != null) { - new ParamLogger(params) { - protected void logParam(String paramName, Object paramValue) { - reqSpec.param(paramName, paramValue); - } - }.logParams(); - } - - if (queryParams != null) { - new ParamLogger(queryParams) { - protected void logParam(String paramName, Object paramValue) { - reqSpec.queryParam(paramName, paramValue); - } - }.logParams(); - } - - if (formParams != null) { - new ParamLogger(formParams) { - protected void logParam(String paramName, Object paramValue) { - reqSpec.formParam(paramName, paramValue); - } - }.logParams(); - } - - if (headers != null) { - for (Header header : headers) { - reqSpec.header(header); - } - } - - if (cookies != null) { - for (Cookie cookie : cookies) { - reqSpec.cookie(cookie); - } - } - - if (requestBody != null) { - if (requestBody instanceof byte[]) { - reqSpec.body((byte[]) requestBody); - } else if (requestBody instanceof File) { - String contentType = findContentType(); - String charset = null; - if (StringUtils.isNotBlank(contentType)) { - charset = CharsetExtractor.getCharsetFromContentType(contentType); - } - - if (charset == null) { - charset = Charset.defaultCharset().toString(); - } - - String string = fileToString((File) requestBody, charset); - reqSpec.body(string); - } else { - reqSpec.body(requestBody); - } - } + logParamsAndHeaders(reqSpec, method.toString(), uri, unnamedPathParams, params, queryParams, formParams, headers, cookies); + logRequestBody(reqSpec, requestBody, headers, (List) (List) multiParts, config); if (multiParts != null) { for (MockMvcMultiPart multiPart : multiParts) { @@ -585,26 +484,6 @@ protected void logParam(String paramName, Object paramValue) { requestLoggingFilter.filter(reqSpec, null, new FilterContextImpl(uri, originalUriPath, uriPath, uri, uri, new Object[0], method.toString(), null, Collections.emptyList().iterator(), new HashMap())); } - private String fileToString(File file, String charset) { - StringBuilder fileContents = new StringBuilder((int) file.length()); - Scanner scanner; - try { - scanner = new Scanner(file, charset); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - String lineSeparator = System.getProperty(LINE_SEPARATOR); - - try { - while (scanner.hasNextLine()) { - fileContents.append(scanner.nextLine()).append(lineSeparator); - } - return fileContents.toString(); - } finally { - scanner.close(); - } - } - public MockMvcResponse get(String path, Object... pathParams) { return sendRequest(GET, path, pathParams); } @@ -806,63 +685,6 @@ public MockMvcRequestAsyncConfigurer async() { basePath, responseSpecification, authentication, logRepository, true); } - private abstract static class ParamApplier { - private Map map; - - protected ParamApplier(Map parameters) { - this.map = parameters; - } - - public void applyParams() { - for (Map.Entry listEntry : map.entrySet()) { - Object value = listEntry.getValue(); - String[] stringValues; - if (value instanceof Collection) { - Collection col = (Collection) value; - stringValues = new String[col.size()]; - int index = 0; - for (Object val : col) { - stringValues[index] = val == null ? null : val.toString(); - index++; - } - } else { - stringValues = new String[1]; - stringValues[0] = value == null ? null : value.toString(); - } - applyParam(listEntry.getKey(), stringValues); - } - } - - protected abstract void applyParam(String paramName, String[] paramValues); - } - - private abstract static class ParamLogger { - private Map map; - - protected ParamLogger(Map parameters) { - this.map = parameters; - } - - public void logParams() { - for (Map.Entry stringListEntry : map.entrySet()) { - Object value = stringListEntry.getValue(); - Collection values; - if (value instanceof Collection) { - values = (Collection) value; - } else { - values = new ArrayList(); - values.add(value); - } - - for (Object theValue : values) { - logParam(stringListEntry.getKey(), theValue); - } - } - } - - protected abstract void logParam(String paramName, Object paramValue); - } - private HttpMethod toValidHttpMethod(String method) { String httpMethodAsString = notNull(trimToNull(method), "HTTP Method"); HttpMethod httpMethod = HttpMethod.resolve(httpMethodAsString.toUpperCase()); diff --git a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSpecificationImpl.java b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSpecificationImpl.java index 52ef85cb1..82c029509 100644 --- a/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSpecificationImpl.java +++ b/modules/spring-mock-mvc/src/main/java/io/restassured/module/mockmvc/internal/MockMvcRequestSpecificationImpl.java @@ -16,27 +16,52 @@ package io.restassured.module.mockmvc.internal; -import io.restassured.config.EncoderConfig; -import io.restassured.config.HeaderConfig; +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + import io.restassured.config.LogConfig; import io.restassured.config.RestAssuredConfig; import io.restassured.filter.log.RequestLoggingFilter; -import io.restassured.http.*; +import io.restassured.http.ContentType; +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.http.Method; import io.restassured.internal.MapCreator; import io.restassured.internal.MapCreator.CollisionStrategy; -import io.restassured.internal.http.CharsetExtractor; import io.restassured.internal.log.LogRepository; -import io.restassured.internal.mapping.ObjectMapperSerializationContextImpl; import io.restassured.internal.mapping.ObjectMapping; import io.restassured.internal.support.ParameterUpdater; import io.restassured.mapper.ObjectMapper; import io.restassured.mapper.ObjectMapperType; -import io.restassured.module.mockmvc.config.AsyncConfig; import io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig; import io.restassured.module.mockmvc.intercept.MockHttpServletRequestBuilderInterceptor; import io.restassured.module.mockmvc.response.MockMvcResponse; -import io.restassured.module.mockmvc.specification.*; +import io.restassured.module.mockmvc.specification.MockMvcAuthenticationScheme; +import io.restassured.module.mockmvc.specification.MockMvcAuthenticationSpecification; +import io.restassured.module.mockmvc.specification.MockMvcRequestAsyncSender; +import io.restassured.module.mockmvc.specification.MockMvcRequestLogSpecification; +import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification; +import io.restassured.module.spring.commons.BodyHelper; +import io.restassured.module.spring.commons.CookieHelper; +import io.restassured.module.spring.commons.HeaderHelper; +import io.restassured.module.spring.commons.Serializer; +import io.restassured.module.spring.commons.config.AsyncConfig; +import io.restassured.module.spring.commons.config.ConfigConverter; +import io.restassured.module.spring.commons.config.ConfigMergeUtils; import io.restassured.specification.ResponseSpecification; + import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvcBuilder; import org.springframework.test.web.servlet.ResultHandler; @@ -46,13 +71,6 @@ import org.springframework.test.web.servlet.setup.MockMvcConfigurer; import org.springframework.web.context.WebApplicationContext; -import java.io.File; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.security.Principal; -import java.util.*; - import static io.restassured.internal.assertion.AssertParameter.notNull; import static io.restassured.internal.serialization.SerializationSupport.isSerializableCandidate; import static io.restassured.module.mockmvc.internal.SpringSecurityClassPathChecker.isSpringSecurityInClasspath; @@ -89,7 +107,8 @@ public class MockMvcRequestSpecificationImpl implements MockMvcRequestSpecificat private RequestLoggingFilter requestLoggingFilter; - private final ParameterUpdater parameterUpdater = new ParameterUpdater(new ParameterUpdater.Serializer() { + private final ParameterUpdater + parameterUpdater = new ParameterUpdater(new ParameterUpdater.Serializer() { public String serializeIfNeeded(Object value) { return MockMvcRequestSpecificationImpl.this.serializeIfNeeded(value); } @@ -208,88 +227,20 @@ public MockMvcRequestSpecification headers(String firstHeaderName, Object firstH public MockMvcRequestSpecification headers(Map headers) { notNull(headers, "headers"); - List
headerList = new ArrayList
(); - if (this.requestHeaders.exist()) { - for (Header requestHeader : this.requestHeaders) { - headerList.add(requestHeader); - } - } - - for (Map.Entry stringEntry : headers.entrySet()) { - Object value = stringEntry.getValue(); - if (value instanceof List) { - List values = (List) value; - for (Object o : values) { - headerList.add(new Header(stringEntry.getKey(), serializeIfNeeded(o))); - } - } else { - headerList.add(new Header(stringEntry.getKey(), serializeIfNeeded(value))); - } - } - - this.requestHeaders = new Headers(headerList); + this.requestHeaders = HeaderHelper.headers(requestHeaders, headers, cfg); return this; } public MockMvcRequestSpecification headers(Headers headers) { notNull(headers, "Headers"); - if (headers.exist()) { - List
headerList = new ArrayList
(); - if (this.requestHeaders.exist()) { - for (Header requestHeader : this.requestHeaders) { - headerList.add(requestHeader); - } - } - - for (Header requestHeader : headers) { - headerList.add(requestHeader); - } - - this.requestHeaders = new Headers(removeMergedHeadersIfNeeded(headerList)); - } + requestHeaders = HeaderHelper.headers(requestHeaders, headers, cfg.getHeaderConfig()); return this; } - private List
removeMergedHeadersIfNeeded(List
headerList) { - HeaderConfig headerConfig = cfg.getHeaderConfig(); - List
filteredList = new ArrayList
(); - for (Header header : headerList) { - String headerName = header.getName(); - if (headerConfig.shouldOverwriteHeaderWithName(headerName)) { - int index = -1; - for (int i = 0; i < filteredList.size(); i++) { - Header filteredHeader = filteredList.get(i); - if (filteredHeader.hasSameNameAs(header)) { - index = i; - break; - } - } - - if (index != -1) { - filteredList.remove(index); - } - } - - filteredList.add(header); - } - return filteredList; - } - public MockMvcRequestSpecification header(final String headerName, final Object headerValue, Object... additionalHeaderValues) { notNull(headerName, "Header name"); notNull(headerValue, "Header value"); - - List
headerList = new ArrayList
() {{ - add(new Header(headerName, serializeIfNeeded(headerValue))); - }}; - - if (additionalHeaderValues != null) { - for (Object additionalHeaderValue : additionalHeaderValues) { - headerList.add(new Header(headerName, serializeIfNeeded(additionalHeaderValue))); - } - } - - return headers(new Headers(headerList)); + return headers(HeaderHelper.headers(requestHeaders, headerName, headerValue, cfg, additionalHeaderValues)); } @@ -380,13 +331,13 @@ public MockMvcRequestSpecification formParam(String parameterName, Collection public MockMvcRequestSpecification attribute(String attributeName, Object attributeValue) { notNull(attributeName, "attributeName"); notNull(attributeValue, "attributeValue"); - parameterUpdater.updateZeroToManyParameters(convert(cfg.getParamConfig().attributeUpdateStrategy()), attributes, attributeName, attributeValue); + parameterUpdater.updateZeroToManyParameters(convert(cfg.getMockMvcParamConfig().attributeUpdateStrategy()), attributes, attributeName, attributeValue); return this; } public MockMvcRequestSpecification attributes(Map attributesMap) { notNull(attributesMap, "attributesMap"); - parameterUpdater.updateParameters(convert(cfg.getParamConfig().attributeUpdateStrategy()), (Map) attributesMap, attributes); + parameterUpdater.updateParameters(convert(cfg.getMockMvcParamConfig().attributeUpdateStrategy()), (Map) attributesMap, attributes); return this; } @@ -412,19 +363,15 @@ public MockMvcRequestSpecification body(Object object) { } String requestContentType = getRequestContentType(); - this.requestBody = ObjectMapping.serialize(object, requestContentType, findEncoderCharsetOrReturnDefault(requestContentType), null, cfg.getObjectMapperConfig(), cfg.getEncoderConfig()); + this.requestBody = ObjectMapping.serialize(object, requestContentType, + Serializer.findEncoderCharsetOrReturnDefault(requestContentType, cfg), null, cfg.getObjectMapperConfig(), cfg.getEncoderConfig()); return this; } public MockMvcRequestSpecification body(Object object, ObjectMapper mapper) { notNull(object, "object"); notNull(mapper, "Object mapper"); - String requestContentType = getRequestContentType(); - ObjectMapperSerializationContextImpl ctx = new ObjectMapperSerializationContextImpl(); - ctx.setObject(object); - ctx.setCharset(findEncoderCharsetOrReturnDefault(requestContentType)); - ctx.setContentType(requestContentType); - this.requestBody = mapper.serialize(ctx); + this.requestBody = BodyHelper.toSerializedBody(object, mapper, cfg, requestHeaders); return this; } @@ -432,7 +379,8 @@ public MockMvcRequestSpecification body(Object object, ObjectMapperType mapperTy notNull(object, "object"); notNull(mapperType, "Object mapper type"); String requestContentType = getRequestContentType(); - this.requestBody = ObjectMapping.serialize(object, requestContentType, findEncoderCharsetOrReturnDefault(requestContentType), mapperType, cfg.getObjectMapperConfig(), cfg.getEncoderConfig()); + this.requestBody = ObjectMapping.serialize(object, requestContentType, + Serializer.findEncoderCharsetOrReturnDefault(requestContentType, cfg), mapperType, cfg.getObjectMapperConfig(), cfg.getEncoderConfig()); return this; } @@ -442,55 +390,20 @@ public MockMvcRequestSpecification cookies(String firstCookieName, Object firstC public MockMvcRequestSpecification cookies(Map cookies) { notNull(cookies, "cookies"); - List cookieList = new ArrayList(); - if (this.cookies.exist()) { - for (Cookie requestCookie : this.cookies) { - cookieList.add(requestCookie); - } - } - - for (Map.Entry stringEntry : cookies.entrySet()) { - cookieList.add(new Cookie.Builder(stringEntry.getKey(), serializeIfNeeded(stringEntry.getValue())).build()); - } - - this.cookies = new Cookies(cookieList); + this.cookies = CookieHelper.cookies(this.cookies, cookies, requestHeaders, cfg); return this; } public MockMvcRequestSpecification cookies(Cookies cookies) { notNull(cookies, "Cookies"); - if (cookies.exist()) { - List cookieList = new ArrayList(); - if (this.cookies.exist()) { - for (Cookie cookie : this.cookies) { - cookieList.add(cookie); - } - } - - for (Cookie cookie : cookies) { - cookieList.add(cookie); - } - - this.cookies = new Cookies(cookieList); - } + this.cookies = CookieHelper.cookies(this.cookies, cookies); return this; } public MockMvcRequestSpecification cookie(final String cookieName, final Object cookieValue, Object... additionalValues) { notNull(cookieName, "Cookie name"); notNull(cookieValue, "Cookie value"); - - List cookieList = new ArrayList() {{ - add(new Cookie.Builder(cookieName, serializeIfNeeded(cookieValue)).build()); - }}; - - if (additionalValues != null) { - for (Object additionalCookieValue : additionalValues) { - cookieList.add(new Cookie.Builder(cookieName, serializeIfNeeded(additionalCookieValue)).build()); - } - } - - return cookies(new Cookies(cookieList)); + return cookies(CookieHelper.cookie(cookieName, cookieValue, requestHeaders, cfg, additionalValues)); } public MockMvcRequestSpecification cookie(Cookie cookie) { @@ -519,12 +432,13 @@ public MockMvcRequestSpecification multiPart(String controlName, Object object) } public MockMvcRequestSpecification multiPart(String controlName, Object object, String mimeType) { - multiParts.add(new MockMvcMultiPart(cfg.getMultiPartConfig(), controlName, serializeIfNeeded(object, mimeType), mimeType)); + multiParts.add(new MockMvcMultiPart(cfg.getMultiPartConfig(), controlName, + Serializer.serializeIfNeeded(object, mimeType, cfg), mimeType)); return this; } public MockMvcRequestSpecification multiPart(String controlName, String filename, Object object, String mimeType) { - multiParts.add(new MockMvcMultiPart(controlName, filename, serializeIfNeeded(object, mimeType), mimeType)); + multiParts.add(new MockMvcMultiPart(controlName, filename, Serializer.serializeIfNeeded(object, mimeType, cfg), mimeType)); return this; } @@ -624,64 +538,15 @@ public MockMvcRequestSpecification spec(MockMvcRequestSpecification requestSpeci return this; } - private static void mergeConfig(MockMvcRequestSpecificationImpl thisOne, MockMvcRequestSpecificationImpl other) { - RestAssuredMockMvcConfig thisConfig = thisOne.getRestAssuredMockMvcConfig(); - RestAssuredMockMvcConfig otherConfig = other.getRestAssuredMockMvcConfig(); - boolean thisIsUserConfigured = thisConfig.isUserConfigured(); - boolean otherIsUserConfigured = otherConfig.isUserConfigured(); - if (thisIsUserConfigured && otherIsUserConfigured) { - if (otherConfig.getDecoderConfig().isUserConfigured()) { - thisConfig = thisConfig.decoderConfig(otherConfig.getDecoderConfig()); - } - - if (otherConfig.getEncoderConfig().isUserConfigured()) { - thisConfig = thisConfig.encoderConfig(otherConfig.getEncoderConfig()); - } - - if (otherConfig.getHeaderConfig().isUserConfigured()) { - thisConfig = thisConfig.headerConfig(otherConfig.getHeaderConfig()); - } - - if (otherConfig.getJsonConfig().isUserConfigured()) { - thisConfig = thisConfig.jsonConfig(otherConfig.getJsonConfig()); - } - - if (otherConfig.getLogConfig().isUserConfigured()) { - thisConfig = thisConfig.logConfig(otherConfig.getLogConfig()); - } - - if (otherConfig.getObjectMapperConfig().isUserConfigured()) { - thisConfig = thisConfig.objectMapperConfig(otherConfig.getObjectMapperConfig()); - } - - if (otherConfig.getSessionConfig().isUserConfigured()) { - thisConfig = thisConfig.sessionConfig(otherConfig.getSessionConfig()); - } - - if (otherConfig.getXmlConfig().isUserConfigured()) { - thisConfig = thisConfig.xmlConfig(otherConfig.getXmlConfig()); - } - - if (otherConfig.getAsyncConfig().isUserConfigured()) { - thisConfig = thisConfig.asyncConfig(otherConfig.getAsyncConfig()); - } - - if (otherConfig.getMultiPartConfig().isUserConfigured()) { - thisConfig = thisConfig.multiPartConfig(otherConfig.getMultiPartConfig()); - } - - if (otherConfig.getMockMvcConfig().isUserConfigured()) { - thisConfig = thisConfig.mockMvcConfig(otherConfig.getMockMvcConfig()); - } - - if (otherConfig.getParamConfig().isUserConfigured()) { - thisConfig = thisConfig.paramConfig(otherConfig.getParamConfig()); - } - - thisOne.config(thisConfig); - } else if (!thisIsUserConfigured && otherIsUserConfigured) { - thisOne.config(otherConfig); - } + /** + * Set session attributes. + * + * @param sessionAttributes the session attributes + */ + public MockMvcRequestSpecification sessionAttrs(Map sessionAttributes) { + notNull(sessionAttributes, "sessionAttributes"); + parameterUpdater.updateParameters(convert(cfg.getMockMvcParamConfig().sessionAttributesUpdateStrategy()), sessionAttributes, this.sessionAttributes); + return this; } public MockMvcRequestSpecification sessionId(String sessionIdValue) { @@ -692,14 +557,7 @@ public MockMvcRequestSpecification sessionId(String sessionIdName, String sessio notNull(sessionIdName, "Session id name"); notNull(sessionIdValue, "Session id value"); if (cookies.hasCookieWithName(sessionIdName)) { - List allOtherCookies = new ArrayList(); - for (Cookie cookie : cookies) { - if (!cookie.getName().equalsIgnoreCase(sessionIdName)) { - allOtherCookies.add(cookie); - } - } - allOtherCookies.add(new Cookie.Builder(sessionIdName, sessionIdValue).build()); - this.cookies = new Cookies(allOtherCookies); + CookieHelper.sessionId(cookies, sessionIdName, sessionIdValue); } else { cookie(sessionIdName, sessionIdValue); } @@ -726,25 +584,8 @@ public MockMvcRequestAsyncSender when() { logRepository); } - private String findEncoderCharsetOrReturnDefault(String contentType) { - String charset = CharsetExtractor.getCharsetFromContentType(contentType); - if (charset == null) { - EncoderConfig encoderConfig = cfg.getEncoderConfig(); - if (encoderConfig.hasDefaultCharsetForContentType(contentType)) { - charset = encoderConfig.defaultCharsetForContentType(contentType); - } else { - charset = encoderConfig.defaultContentCharset(); - } - } - return charset; - } - private String serializeIfNeeded(Object object) { - return serializeIfNeeded(object, getRequestContentType()); - } - - private String serializeIfNeeded(Object object, String contentType) { - return isSerializableCandidate(object) ? ObjectMapping.serialize(object, contentType, findEncoderCharsetOrReturnDefault(contentType), null, cfg.getObjectMapperConfig(), cfg.getEncoderConfig()) : object.toString(); + return Serializer.serializeIfNeeded(object, getRequestContentType(), cfg); } public MockMvcResponse get(String path, Object... pathParams) { @@ -1075,18 +916,12 @@ public AsyncConfig getAsyncConfig() { */ public MockMvcRequestSpecification sessionAttr(String name, Object value) { notNull(name, "Session attribute name"); - parameterUpdater.updateZeroToManyParameters(convert(cfg.getParamConfig().sessionAttributesUpdateStrategy()), sessionAttributes, name, value); + parameterUpdater.updateZeroToManyParameters(convert(cfg.getMockMvcParamConfig().sessionAttributesUpdateStrategy()), sessionAttributes, name, value); return this; } - /** - * Set session attributes. - * - * @param sessionAttributes the session attributes - */ - public MockMvcRequestSpecification sessionAttrs(Map sessionAttributes) { - notNull(sessionAttributes, "sessionAttributes"); - parameterUpdater.updateParameters(convert(cfg.getParamConfig().sessionAttributesUpdateStrategy()), sessionAttributes, this.sessionAttributes); - return this; + private void mergeConfig(MockMvcRequestSpecificationImpl thisOne, MockMvcRequestSpecificationImpl other) { + config((RestAssuredMockMvcConfig) ConfigMergeUtils.mergeConfig(thisOne.getRestAssuredMockMvcConfig(), + other.getRestAssuredMockMvcConfig())); } } diff --git a/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/AsyncTest.java b/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/AsyncTest.java index c2dcd5694..cf2ed1a2b 100644 --- a/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/AsyncTest.java +++ b/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/AsyncTest.java @@ -16,15 +16,15 @@ package io.restassured.module.mockmvc; +import java.util.concurrent.TimeUnit; + import io.restassured.module.mockmvc.http.PostAsyncController; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import java.util.concurrent.TimeUnit; - -import static io.restassured.module.mockmvc.config.AsyncConfig.withTimeout; import static io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig.newConfig; +import static io.restassured.module.spring.commons.config.AsyncConfig.withTimeout; import static java.util.concurrent.TimeUnit.DAYS; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/MockMvcParamConfigTest.java b/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/MockMvcParamConfigTest.java index 402951420..747134ecd 100644 --- a/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/MockMvcParamConfigTest.java +++ b/modules/spring-mock-mvc/src/test/java/io/restassured/module/mockmvc/MockMvcParamConfigTest.java @@ -21,7 +21,7 @@ import org.junit.Before; import org.junit.Test; -import static io.restassured.module.mockmvc.config.MockMvcParamConfig.UpdateStrategy.REPLACE; +import static io.restassured.config.ParamConfig.UpdateStrategy.REPLACE; import static io.restassured.module.mockmvc.config.MockMvcParamConfig.paramConfig; import static io.restassured.module.mockmvc.config.RestAssuredMockMvcConfig.config; import static org.hamcrest.Matchers.equalTo; diff --git a/modules/spring-web-test-client/pom.xml b/modules/spring-web-test-client/pom.xml new file mode 100644 index 000000000..d347a80e7 --- /dev/null +++ b/modules/spring-web-test-client/pom.xml @@ -0,0 +1,137 @@ + + + + + 4.0.0 + + io.rest-assured + modules + 3.1.2-SNAPSHOT + + spring-web-test-client + 3.1.2-SNAPSHOT + spring-web-test-client + http://maven.apache.org + + UTF-8 + 5.1.0.RELEASE + 4.0.1 + 2.0.2.RELEASE + 1.7.4 + 2.5 + 3.11.1 + 2.9.6 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + + + io.rest-assured + rest-assured + ${project.version} + + + io.rest-assured + spring-commons + ${project.version} + + + org.springframework + spring-test + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-webflux + ${spring.version} + + + + + junit + junit + test + + + org.powermock + powermock-module-junit4 + ${powermock-module-junit4.version} + test + + + commons-io + commons-io + ${commons-io.version} + test + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + javax.servlet + javax.servlet-api + ${servlet-api.version} + test + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + test + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + test + + + org.springframework.restdocs + spring-restdocs-core + ${spring.restdocs.version} + test + + + org.springframework.restdocs + spring-restdocs-webtestclient + ${spring.restdocs.version} + test + + + \ No newline at end of file diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/RestAssuredWebTestClient.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/RestAssuredWebTestClient.java new file mode 100644 index 000000000..49659f5ec --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/RestAssuredWebTestClient.java @@ -0,0 +1,829 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.config.LogConfig; +import io.restassured.filter.log.LogDetail; +import io.restassured.http.Method; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.internal.BuilderBasedWebTestClientFactory; +import io.restassured.module.webtestclient.internal.StandaloneWebTestClientFactory; +import io.restassured.module.webtestclient.internal.WebTestClientFactory; +import io.restassured.module.webtestclient.internal.WebTestClientRequestSpecificationImpl; +import io.restassured.module.webtestclient.internal.WrapperWebTestClientFactory; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSender; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification; +import io.restassured.specification.ResponseSpecification; +import org.springframework.context.ApplicationContext; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClientConfigurer; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.util.UriBuilder; + +import java.net.URI; +import java.net.URL; +import java.util.Map; +import java.util.function.Function; + +import static io.restassured.config.LogConfig.logConfig; + +/** + * The Spring Web Test Client module's equivalent of {@link io.restassured.RestAssured}. This is the starting point of the DSL. + */ +public class RestAssuredWebTestClient { + + /** + * Define a REST Assured WebTestClient configuration. E.g. + *
+	 * given().config(newConfig().logConfig(new LogConfig(captor, true))). ..
+	 * 
+ *

+ * newConfig() can be statically imported from {@link RestAssuredWebTestClientConfig}. + */ + public static RestAssuredWebTestClientConfig config; + + /** + * Specify a default request specification that will be sent with each request. E,g. + *

+	 * RestAssuredWebTestClient.requestSpecification = new WebTestClientRequestSpecBuilder().addParam("parameter1", "value1").build();
+	 * 
+ *

+ * means that for each request by Rest Assured "parameter1" will be equal to "value1". + */ + public static WebTestClientRequestSpecification requestSpecification; + + /** + * Specify a default response specification that will be sent with each request. E,g. + *

+	 * RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder().expectStatusCode(200).build();
+	 * 
+ *

+ * means that for each response Rest Assured will assert that the status code is equal to 200. + */ + public static ResponseSpecification responseSpecification = null; + + /** + * The base path that's used by REST assured when making requests. The base path is prepended to the request path. + * Default value is /. + */ + public static String basePath = "/"; + + private static WebTestClientFactory webTestClientFactory = null; + + /** + * Set a {@link WebTestClient} instance that REST Assured will use when making requests unless overwritten + * by a {@link WebTestClientRequestSpecification}. + * + * @param webTestClient The WebTestClient instance to use. + */ + public static void webTestClient(WebTestClient webTestClient) { + RestAssuredWebTestClient.webTestClientFactory = new WrapperWebTestClientFactory(webTestClient); + } + + /** + * This is usually the entry-point of the API if you need to specify parameters or a body in the request. For example: + *

+ *

+	 * given().
+	 *         param("x", "y").
+	 * when().
+	 *         get("/something").
+	 * then().
+	 *        statusCode(200).
+	 *        body("x.y", notNullValue());
+	 * 
+ * Note that this method is the same as {@link #with()} but with another syntax. + * + * @return a {@link WebTestClientRequestSpecification}. + */ + public static WebTestClientRequestSpecification given() { + return new WebTestClientRequestSpecificationImpl(webTestClientFactory, config, basePath, requestSpecification, + responseSpecification); + } + + /** + * This is usually the entry-point of the API if you need to specify parameters or a body in the request. For example: + * Note that this method is the same as {@link #given()} but with another syntax. + * + * @return A {@link WebTestClientRequestSpecification}. + */ + public static WebTestClientRequestSpecification with() { + return given(); + } + + /** + * Build a {@link WebTestClient} by registering one or more {@code @Controller}'s + * instances and configuring WebTestClient programmatically. + * This allows full control over the instantiation, configuration and initialization of + * controllers, and their dependencies, similar to plain unit tests while + * also making it possible to test one controller at a time. + *

+ *

It uses {@link WebTestClient#bindToController(Object...)} under the hood. + * It also allows you to pass {@link WebTestClientConfigurer} and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction} + * instances that are used to set up the {@link WebTestClient} instance. + *

+ * + * @param controllersOrConfigurersOrExchangeFilterFunctions one or more {@link org.springframework.stereotype.Controller @Controller}s to test, + * as well as {@link WebTestClientConfigurer}s + * and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction}s to apply. + */ + public static void standaloneSetup(Object... controllersOrConfigurersOrExchangeFilterFunctions) { + webTestClientFactory = StandaloneWebTestClientFactory.of(controllersOrConfigurersOrExchangeFilterFunctions); + } + + /** + * Build a {@link WebTestClient} by using a provided {@link RouterFunction} + * for configuring WebTestClient programmatically. + * This allows full control over the instantiation, configuration and initialization of + * router functions, and their dependencies, similar to plain unit tests while + * also making it possible to test one router function at a time. + *

+ *

+ * It uses {@link WebTestClient#bindToRouterFunction(RouterFunction)} under the hood. + * It also allows you to pass {@link WebTestClientConfigurer} and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction} + * instances that are used to set up the {@link WebTestClient} instance + *

+ * + * @param routerFunction {@link RouterFunction} to build WebTestClient. + * @param configurersOrExchangeFilterFunctions {@link WebTestClientConfigurer}s and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction}s to apply. + */ + public static void standaloneSetup(RouterFunction routerFunction, Object... configurersOrExchangeFilterFunctions) { + webTestClientFactory = StandaloneWebTestClientFactory.of(routerFunction, configurersOrExchangeFilterFunctions); + } + + /** + * Build a {@link WebTestClient} by using a provided {@link org.springframework.test.web.reactive.server.WebTestClient.Builder} + * for configuring WebTestClient programmatically. + * This allows full control over the instantiation and initialization of + * controllers, and their dependencies, similar to plain unit tests while + * also making it possible to test one controller at a time. + * + * @param builder {@link org.springframework.test.web.reactive.server.WebTestClient.Builder} to build WebTestClient. + */ + public static void standaloneSetup(WebTestClient.Builder builder) { + webTestClientFactory = new BuilderBasedWebTestClientFactory(builder); + } + + /** + * Build a {@link WebTestClient} using the given, fully initialized, i.e. + * refreshed, {@link WebApplicationContext} and assign it to REST Assured. + *

+ * This is really an alias for {@link #webAppContextSetup(WebApplicationContext, Object...)}. + * The passed {@link WebApplicationContext} will be used as {@link ApplicationContext}. + * + * @param context The web application context to use + * @param configurersOrExchangeFilterFunctions {@link WebTestClientConfigurer}s and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction}s to apply. + */ + public static void webAppContextSetup(WebApplicationContext context, Object... configurersOrExchangeFilterFunctions) { + webTestClientFactory = StandaloneWebTestClientFactory.of(context, configurersOrExchangeFilterFunctions); + } + + /** + * Build a {@link WebTestClient} using the given, fully initialized, i.e. + * refreshed, {@link ApplicationContext} and assign it to REST Assured. + * + * @param context The application context to use + * @param configurersOrExchangeFilterFunctions {@link WebTestClientConfigurer}s and {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction}s to apply. + */ + public static void applicationContextSetup(ApplicationContext context, + Object... configurersOrExchangeFilterFunctions) { + webTestClientFactory = StandaloneWebTestClientFactory.of(context, configurersOrExchangeFilterFunctions); + } + + /** + * Reset all static configurations to their default values. + */ + public static void reset() { + webTestClientFactory = null; + config = null; + basePath = "/"; + responseSpecification = null; + requestSpecification = null; + } + + /** + * Perform a GET request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do get("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the GET request. + */ + public static WebTestClientResponse get(String path, Object... pathParams) { + return given().get(path, pathParams); + } + + /** + * Perform a GET request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the GET request. + */ + public static WebTestClientResponse get(String path, Map pathParams) { + return given().get(path, pathParams); + } + + /** + * Perform a GET request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse get(Function uriFunction) { + return given().get(uriFunction); + } + + /** + * Perform a POST request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do post("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse post(String path, Object... pathParams) { + return given().post(path, pathParams); + } + + /** + * Perform a GET request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse get(URI uri) { + return given().get(uri); + } + + /** + * Perform a GET request to a url. + * + * @param url The url to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse get(URL url) { + return given().get(url); + } + + /** + * Perform a GET request to the statically configured base path. + * + * @return The response of the GET request. + */ + public static WebTestClientResponse get() { + return given().get(); + } + + /** + * Perform a request to the pre-configured path (by default http://localhost:8080). + * + * @param method The HTTP method to use + * @return The response of the request. + */ + public static WebTestClientResponse request(Method method) { + return given().request(method); + } + + /** + * Perform a custom HTTP request to the pre-configured path (by default http://localhost:8080). + * + * @param method The HTTP method to use + * @return The response of the request. + */ + public static WebTestClientResponse request(String method) { + return given().request(method); + } + + /** + * Perform a HTTP request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param method The HTTP method to use + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do request(Method.TRACE,"/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse request(Method method, String path, Object... pathParams) { + return given().request(method, path, pathParams); + } + + /** + * Perform a custom HTTP request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param method The HTTP method to use + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do request("method","/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse request(String method, String path, Object... pathParams) { + return given().request(method, path, pathParams); + } + + /** + * Perform a request to a uri. + * + * @param method The HTTP method to use + * @param uri The uri to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse request(Method method, URI uri) { + return given().request(method, uri); + } + + /** + * Perform a request to a path generated from the provided {@link Function} uriFunction. + * + * @param method The HTTP method to use + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse request(Method method, Function uriFunction) { + return given().request(method, uriFunction); + } + + /** + * Perform a request to a url. + * + * @param method The HTTP method to use + * @param url The url to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse request(Method method, URL url) { + return given().request(method, url); + } + + /** + * Perform a custom HTTP request to a uri. + * + * @param method The HTTP method to use + * @param uri The uri to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse request(String method, URI uri) { + return given().request(method, uri); + } + + /** + * Perform a request to a path generated from the provided {@link Function} uriFunction. + * + * @param method The HTTP method to use + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse request(String method, Function uriFunction) { + return given().request(method, uriFunction); + } + + /** + * Perform a custom HTTP request to a url. + * + * @param method The HTTP method to use + * @param url The url to send the request to. + * @return The response of the GET request. + */ + public static WebTestClientResponse request(String method, URL url) { + return given().request(method, url); + } + + /** + * Perform a POST request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the request. + */ + public static WebTestClientResponse post(String path, Map pathParams) { + return given().post(path, pathParams); + } + + /** + * Perform a PUT request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do put("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse put(String path, Object... pathParams) { + return given().put(path, pathParams); + } + + /** + * Perform a POST request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the POST request. + */ + public static WebTestClientResponse post(Function uriFunction) { + return given().post(uriFunction); + } + + /** + * Perform a POST request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse post(URI uri) { + return given().post(uri); + } + + /** + * Perform a POST request to a url. + * + * @param url The url to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse post(URL url) { + return given().post(url); + } + + /** + * Perform a POST request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse post() { + return given().post(); + } + + /** + * Perform a DELETE request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do delete("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse delete(String path, Object... pathParams) { + return given().delete(path, pathParams); + } + + public static WebTestClientResponse put(String path, Map pathParams) { + return given().put(path, pathParams); + } + + /** + * Perform a PUT request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the PUT request. + */ + public static WebTestClientResponse put(Function uriFunction) { + return given().put(uriFunction); + } + + /** + * Perform a PUT request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse put(URI uri) { + return given().put(uri); + } + + public static WebTestClientResponse put(URL url) { + return given().put(url); + } + + /** + * Perform a PUT request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse put() { + return given().put(); + } + + /** + * Perform a DELETE request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the request. + */ + public static WebTestClientResponse delete(String path, Map pathParams) { + return given().delete(path, pathParams); + } + + /** + * Perform a HEAD request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do head("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse head(String path, Object... pathParams) { + return given().head(path, pathParams); + } + + /** + * Perform a DELETE request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the DELETE request. + */ + public static WebTestClientResponse delete(Function uriFunction) { + return given().delete(uriFunction); + } + + /** + * Perform a DELETE request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse delete(URI uri) { + return given().delete(uri); + } + + /** + * Perform a DELETE request to a url. + * + * @param url The url to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse delete(URL url) { + return given().delete(url); + } + + /** + * Perform a DELETE request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse delete() { + return given().delete(); + } + + /** + * Perform a HEAD request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the request. + */ + public static WebTestClientResponse head(String path, Map pathParams) { + return given().head(path, pathParams); + } + + /** + * Perform a PATCH request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do head("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse patch(String path, Object... pathParams) { + return given().patch(path, pathParams); + } + + /** + * Perform a HEAD request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the HEAD request. + */ + public static WebTestClientResponse head(Function uriFunction) { + return given().head(uriFunction); + } + + /** + * Perform a HEAD request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse head(URI uri) { + return given().head(uri); + } + + /** + * Perform a HEAD request to a url. + * + * @param url The url to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse head(URL url) { + return given().head(url); + } + + /** + * Perform a HEAD request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse head() { + return given().head(); + } + + /** + * Perform a PATCH request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the request. + */ + public static WebTestClientResponse patch(String path, Map pathParams) { + return given().patch(path, pathParams); + } + + /** + * Perform a PATCH request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the PATCH request. + */ + public static WebTestClientResponse patch(Function uriFunction) { + return given().patch(uriFunction); + } + + /** + * Perform a PATCH request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse patch(URI uri) { + return given().patch(uri); + } + + /** + * Perform a PATCH request to a url. + * + * @param url The url to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse patch(URL url) { + return given().patch(url); + } + + /** + * Perform a PATCH request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse patch() { + return given().patch(); + } + + /** + * Perform a OPTIONS request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. E.g. if path is "/book/{hotelId}/{roomNumber}" you can do head("/book/{hotelName}/{roomNumber}", "Hotels R Us", 22);. + * @return The response of the request. + */ + public static WebTestClientResponse options(String path, Object... pathParams) { + return given().options(path, pathParams); + } + + /** + * Perform a OPTIONS request to a path. Normally the path doesn't have to be fully-qualified e.g. you don't need to + * specify the path as http://localhost:8080/path. In this case it's enough to use /path. + * + * @param path The path to send the request to. + * @param pathParams The path parameters. + * @return The response of the request. + */ + public static WebTestClientResponse options(String path, Map pathParams) { + return given().options(path, pathParams); + } + + /** + * Perform a OPTIONS request to a path generated from the provided {@link Function} uriFunction. + * + * @param uriFunction The {@code Function} used to generate the path to send the request to. + * @return The response of the OPTIONS request. + */ + public static WebTestClientResponse options(Function uriFunction) { + return given().options(uriFunction); + } + + /** + * Perform a OPTIONS request to a uri. + * + * @param uri The uri to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse options(URI uri) { + return given().options(uri); + } + + /** + * Perform a OPTIONS request to a url. + * + * @param url The url to send the request to. + * @return The response of the request. + */ + public static WebTestClientResponse options(URL url) { + return given().options(url); + } + + /** + * Perform a OPTIONS request to the statically configured base path. + * + * @return The response of the request. + */ + public static WebTestClientResponse options() { + return given().options(); + } + + /** + * Enable logging of both the request and the response if REST Assured test validation fails with log detail equal to {@link LogDetail#ALL}. + *

+ *

+ * This is just a shortcut for: + *

+ *
+	 * RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig().logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails());
+	 * 
+ */ + public static void enableLoggingOfRequestAndResponseIfValidationFails() { + enableLoggingOfRequestAndResponseIfValidationFails(LogDetail.ALL); + } + + /** + * Enable logging of both the request and the response if REST Assured test validation fails with the specified log detail. + *

+ *

+ * This is just a shortcut for: + *

+ *
+	 * RestAssured.config = new RestAssuredWebTestClientConfig().logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails(logDetail));
+	 * 
+ * + * @param logDetail The log detail to show in the log + */ + public static void enableLoggingOfRequestAndResponseIfValidationFails(LogDetail logDetail) { + config = config == null ? new RestAssuredWebTestClientConfig() : config; + config = config.logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails(logDetail)); + // Update request specification if already defined otherwise it'll override the configs. + // Note that request spec also influence response spec when it comes to logging if validation fails + // due to the way filters work + if (requestSpecification instanceof WebTestClientRequestSpecificationImpl) { + RestAssuredWebTestClientConfig restAssuredConfig = ((WebTestClientRequestSpecificationImpl) requestSpecification) + .getRestAssuredWebTestClientConfig(); + if (restAssuredConfig == null) { + restAssuredConfig = config; + } else { + LogConfig logConfigForRequestSpec = restAssuredConfig.getLogConfig().enableLoggingOfRequestAndResponseIfValidationFails(logDetail); + restAssuredConfig = restAssuredConfig.logConfig(logConfigForRequestSpec); + } + requestSpecification.config(restAssuredConfig); + } + } + + /** + * This is usually the entry-point of the API if you need to specify parameters or a body in the request. For example: + *

+ *

+	 * when().
+	 *        get("/x").
+	 * then().
+	 *        body("x.y.z1", equalTo("Z1")).
+	 *        body("x.y.z2", equalTo("Z2"));
+	 * 
+ *

+ * Note that if you need to add parameters, headers, cookies or other request properties use the {@link #given()} method. + *

+ * + * @return A request sender interface that lets you call resources on the server. + */ + public WebTestClientRequestSender when() { + return given().when(); + } + + /** + * @return The assigned config or a new config is no config is assigned + */ + public static RestAssuredWebTestClientConfig config() { + return config == null ? new RestAssuredWebTestClientConfig() : config; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/RestAssuredWebTestClientConfig.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/RestAssuredWebTestClientConfig.java new file mode 100644 index 000000000..5fbbd1f29 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/RestAssuredWebTestClientConfig.java @@ -0,0 +1,420 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.config; + +import io.restassured.config.DecoderConfig; +import io.restassured.config.EncoderConfig; +import io.restassured.config.HeaderConfig; +import io.restassured.config.JsonConfig; +import io.restassured.config.LogConfig; +import io.restassured.config.MultiPartConfig; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.config.ParamConfig; +import io.restassured.config.SessionConfig; +import io.restassured.config.XmlConfig; +import io.restassured.module.spring.commons.config.AsyncConfig; +import io.restassured.module.spring.commons.config.ClientConfig; +import io.restassured.module.spring.commons.config.SpecificationConfig; + +import static io.restassured.internal.assertion.AssertParameter.notNull; + +/** + * Main configuration for REST Assured WebTestClient that allows you to configure advanced settings. + *

+ * Usage example: + *

+ * RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig().logConfig(new LogConfig(captor, true));
+ * 
+ *

+ */ +public class RestAssuredWebTestClientConfig implements SpecificationConfig { + + // When adding a config here don't forget to update isUserConfigured method + private final LogConfig logConfig; + private final EncoderConfig encoderConfig; + private final DecoderConfig decoderConfig; + private final SessionConfig sessionConfig; + private final ObjectMapperConfig objectMapperConfig; + private final JsonConfig jsonConfig; + private final XmlConfig xmlConfig; + private final HeaderConfig headerConfig; + private final AsyncConfig asyncConfig; + private final WebTestClientConfig webTestClientConfig; + private final MultiPartConfig multiPartConfig; + private final WebTestClientParamConfig paramConfig; + + /** + * Create a new RestAssuredWebTestClientConfig with the default configurations. + */ + public RestAssuredWebTestClientConfig() { + this(new LogConfig(), new EncoderConfig(), new DecoderConfig(), new SessionConfig(), new ObjectMapperConfig(), new JsonConfig(), new XmlConfig(), + new HeaderConfig(), new AsyncConfig(), new MultiPartConfig(), new WebTestClientConfig(), new WebTestClientParamConfig()); + } + + /** + * Create a new RestAssuredWebTestClientConfig with the supplied configs. + */ + private RestAssuredWebTestClientConfig(LogConfig logConfig, + EncoderConfig encoderConfig, + DecoderConfig decoderConfig, + SessionConfig sessionConfig, + ObjectMapperConfig objectMapperConfig, + JsonConfig jsonConfig, + XmlConfig xmlConfig, + HeaderConfig headerConfig, + AsyncConfig asyncConfig, + MultiPartConfig multiPartConfig, + WebTestClientConfig webTestClientConfig, + WebTestClientParamConfig paramConfig) { + notNull(logConfig, "Log config"); + notNull(encoderConfig, "Encoder config"); + notNull(decoderConfig, "Decoder config"); + notNull(sessionConfig, "Session config"); + notNull(objectMapperConfig, "Object mapper config"); + notNull(jsonConfig, "Json config"); + notNull(xmlConfig, "Xml config"); + notNull(headerConfig, "Header config"); + notNull(multiPartConfig, "MultiPart config"); + notNull(webTestClientConfig, "webTestClient config"); + notNull(paramConfig, "Param config"); + this.logConfig = logConfig; + this.encoderConfig = encoderConfig; + this.decoderConfig = decoderConfig; + this.sessionConfig = sessionConfig; + this.objectMapperConfig = objectMapperConfig; + this.jsonConfig = jsonConfig; + this.xmlConfig = xmlConfig; + this.headerConfig = headerConfig; + this.asyncConfig = asyncConfig; + this.multiPartConfig = multiPartConfig; + this.webTestClientConfig = webTestClientConfig; + this.paramConfig = paramConfig; + } + + /** + * @return A static way to create a new RestAssuredWebTestClientConfiguration instance without calling "new" explicitly. Mainly for syntactic sugar. + */ + public static RestAssuredWebTestClientConfig newConfig() { + return new RestAssuredWebTestClientConfig(); + } + + /** + * @return A static way to create a new RestAssuredWebTestClientConfiguration instance without calling "new" explicitly. Mainly for syntactic sugar. + */ + public static RestAssuredWebTestClientConfig config() { + return new RestAssuredWebTestClientConfig(); + } + + /** + * Syntactic sugar. + * + * @return The same RestAssuredWebTestClientConfig instance. + */ + public RestAssuredWebTestClientConfig and() { + return this; + } + + /** + * Syntactic sugar. + * + * @return The same RestAssuredWebTestClientConfig instance. + */ + public RestAssuredWebTestClientConfig set() { + return this; + } + + /** + * Syntactic sugar. + * + * @return The same RestAssuredWebTestClientConfig instance. + */ + public RestAssuredWebTestClientConfig with() { + return this; + } + + public boolean isUserConfigured() { + // When adding a config here don't forget to update merging in WebTestClientRequestSpecificationImpl#mergeConfig and potentially also ConfigConverter#convertToRestAssuredConfig + return decoderConfig.isUserConfigured() || encoderConfig.isUserConfigured() || logConfig.isUserConfigured() + || sessionConfig.isUserConfigured() || objectMapperConfig.isUserConfigured() + || xmlConfig.isUserConfigured() || jsonConfig.isUserConfigured() || headerConfig.isUserConfigured() + || asyncConfig.isUserConfigured() || multiPartConfig.isUserConfigured() + || webTestClientConfig.isUserConfigured() || paramConfig.isUserConfigured(); + } + + /** + * @return The DecoderConfig + */ + public DecoderConfig getDecoderConfig() { + return decoderConfig; + } + + /** + * Set the decoder config + * + * @param decoderConfig The {@link DecoderConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig decoderConfig(DecoderConfig decoderConfig) { + notNull(encoderConfig, DecoderConfig.class); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The EncoderConfig + */ + public EncoderConfig getEncoderConfig() { + return encoderConfig; + } + + /** + * Set the encoder config + * + * @param encoderConfig The {@link EncoderConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig encoderConfig(EncoderConfig encoderConfig) { + notNull(encoderConfig, "EncoderConfig"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The Header Config + */ + public HeaderConfig getHeaderConfig() { + return headerConfig; + } + + /** + * Set the header config + * + * @param headerConfig The {@link HeaderConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig headerConfig(HeaderConfig headerConfig) { + notNull(headerConfig, "HeaderConfig"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The JsonPath Config + */ + public JsonConfig getJsonConfig() { + return jsonConfig; + } + + /** + * Set the Json config. + * + * @param jsonConfig The {@link JsonConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig jsonConfig(JsonConfig jsonConfig) { + notNull(jsonConfig, "JsonConfig"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The LogConfig + */ + public LogConfig getLogConfig() { + return logConfig; + } + + /** + * Set the Log config. + * + * @param logConfig The {@link LogConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig logConfig(LogConfig logConfig) { + notNull(logConfig, "Log config"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The ObjectMapperConfig + */ + public ObjectMapperConfig getObjectMapperConfig() { + return objectMapperConfig; + } + + /** + * Set the object mapper config. + * + * @param objectMapperConfig The {@link ObjectMapperConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig objectMapperConfig(ObjectMapperConfig objectMapperConfig) { + notNull(objectMapperConfig, "Object mapper config"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The SessionConfig + */ + public SessionConfig getSessionConfig() { + return sessionConfig; + } + + /** + * Set the session config. + * + * @param sessionConfig The {@link SessionConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig sessionConfig(SessionConfig sessionConfig) { + notNull(sessionConfig, "Session config"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The Xml Config + */ + public XmlConfig getXmlConfig() { + return xmlConfig; + } + + /** + * Set the Xml config. + * + * @param xmlConfig The {@link XmlConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig xmlConfig(XmlConfig xmlConfig) { + notNull(xmlConfig, "XmlConfig"); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The WebTestClientAsync Config + */ + public AsyncConfig getAsyncConfig() { + return asyncConfig; + } + + /** + * Set the async config + * + * @param asyncConfig The {@link AsyncConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig asyncConfig(AsyncConfig asyncConfig) { + notNull(asyncConfig, AsyncConfig.class); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + /** + * @return The MultiPart Config + */ + public MultiPartConfig getMultiPartConfig() { + return multiPartConfig; + } + + /** + * Set the multi-part config + * + * @param multiPartConfig The {@link MultiPartConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig multiPartConfig(MultiPartConfig multiPartConfig) { + notNull(multiPartConfig, MultiPartConfig.class); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, + webTestClientConfig, paramConfig); + } + + @Override + public ClientConfig getClientConfig() { + return getWebTestClientConfig(); + } + + @Override + public RestAssuredWebTestClientConfig clientConfig(ClientConfig clientConfig) { + if (!(clientConfig instanceof WebTestClientConfig)) { + throw new IllegalArgumentException("Wrong ClientConfig type supplied"); + } + return webTestClientConfig((WebTestClientConfig) clientConfig); + } + + /** + * Set the webTestClient config + * + * @param webTestClientConfig The {@link WebTestClientConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig webTestClientConfig(WebTestClientConfig webTestClientConfig) { + notNull(webTestClientConfig, WebTestClientConfig.class); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, webTestClientConfig, paramConfig); + } + + /** + * @return The Param Config + */ + public ParamConfig getParamConfig() { + return paramConfig; + } + + public WebTestClientParamConfig getWebTestClientParamConfig() { + return paramConfig; + } + + @Override + public SpecificationConfig paramConfig(ParamConfig paramConfig) { + if (!(paramConfig instanceof WebTestClientParamConfig)) { + throw new IllegalArgumentException("Wrong ClientConfig type supplied"); + } + return paramConfig((WebTestClientParamConfig) paramConfig); + } + + /** + * Set the parameter config + * + * @param paramConfig The {@link WebTestClientParamConfig} to set + * @return An updated RestAssuredWebTestClientConfig + */ + public RestAssuredWebTestClientConfig paramConfig(WebTestClientParamConfig paramConfig) { + notNull(paramConfig, MultiPartConfig.class); + return new RestAssuredWebTestClientConfig(logConfig, encoderConfig, decoderConfig, sessionConfig, + objectMapperConfig, jsonConfig, xmlConfig, headerConfig, asyncConfig, multiPartConfig, webTestClientConfig, paramConfig); + } + + /** + * @return The WebTestClient Config + */ + public WebTestClientConfig getWebTestClientConfig() { + return webTestClientConfig; + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientConfig.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientConfig.java new file mode 100644 index 000000000..65398d09a --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientConfig.java @@ -0,0 +1,53 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.config; + +import io.restassured.config.Config; +import io.restassured.module.spring.commons.config.ClientConfig; + +public class WebTestClientConfig implements ClientConfig, Config { + + private final boolean userConfigured; + + public WebTestClientConfig() { + this(true); + } + + public WebTestClientConfig(boolean userConfigured) { + this.userConfigured = userConfigured; + } + + @Override + public boolean isUserConfigured() { + return userConfigured; + } + + /** + * Just syntactic sugar. + * + * @return A new instance of {@link WebTestClientConfig}. + */ + public static WebTestClientConfig webTestClientConfig() { + return new WebTestClientConfig(); + } + + /** + * Just syntactic sugar to make the DSL more English-like. + */ + public WebTestClientConfig with() { + return this; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientParamConfig.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientParamConfig.java new file mode 100644 index 000000000..4bbdcab58 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/config/WebTestClientParamConfig.java @@ -0,0 +1,180 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.config; + +import io.restassured.config.ParamConfig; + +import static io.restassured.config.ParamConfig.UpdateStrategy.MERGE; +import static io.restassured.config.ParamConfig.UpdateStrategy.REPLACE; +import static io.restassured.internal.assertion.AssertParameter.notNull; + +public class WebTestClientParamConfig extends ParamConfig { + + private final boolean userConfigured; + private final UpdateStrategy queryParamsUpdateStrategy; + private final UpdateStrategy formParamsUpdateStrategy; + private final UpdateStrategy requestParameterUpdateStrategy; + private final UpdateStrategy attributeUpdateStrategy; + + + public WebTestClientParamConfig() { + this(MERGE, MERGE, MERGE, MERGE, false); + } + + public WebTestClientParamConfig(UpdateStrategy queryParamsUpdateStrategy, UpdateStrategy formParamsUpdateStrategy, + UpdateStrategy requestParameterUpdateStrategy, UpdateStrategy attributeUpdateStrategy, + boolean userConfigured) { + notNull(queryParamsUpdateStrategy, "Query param update strategy"); + notNull(requestParameterUpdateStrategy, "Request param update strategy"); + notNull(formParamsUpdateStrategy, "Form param update strategy"); + notNull(attributeUpdateStrategy, "Attribute update strategy"); + this.queryParamsUpdateStrategy = queryParamsUpdateStrategy; + this.formParamsUpdateStrategy = formParamsUpdateStrategy; + this.requestParameterUpdateStrategy = requestParameterUpdateStrategy; + this.attributeUpdateStrategy = attributeUpdateStrategy; + this.userConfigured = userConfigured; + } + + + /** + * @return The update strategy for form parameters + */ + public UpdateStrategy attributeUpdateStrategy() { + return attributeUpdateStrategy; + } + + /** + * @return The update strategy for form parameters + */ + public UpdateStrategy formParamsUpdateStrategy() { + return formParamsUpdateStrategy; + } + + /** + * @return The update strategy for request parameters + */ + public UpdateStrategy requestParamsUpdateStrategy() { + return requestParameterUpdateStrategy; + } + + /** + * @return The update strategy for query parameters + */ + public UpdateStrategy queryParamsUpdateStrategy() { + return queryParamsUpdateStrategy; + } + + /** + * {@inheritDoc} + */ + public boolean isUserConfigured() { + return userConfigured; + } + + /** + * @return A static way to create a new WebTestClientParamConfig instance without calling "new" explicitly. + * Mainly for syntactic sugar. + */ + public static WebTestClientParamConfig paramConfig() { + return new WebTestClientParamConfig(); + } + + /** + * Merge all parameter types. + * + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig mergeAllParameters() { + return new WebTestClientParamConfig(MERGE, MERGE, MERGE, MERGE, true); + } + + /** + * Replace parameter values for all kinds of parameter types. + * + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig replaceAllParameters() { + return new WebTestClientParamConfig(REPLACE, REPLACE, REPLACE, REPLACE, true); + } + + /** + * Set form parameter update strategy to the given value. + * + * @param updateStrategy The update strategy to use for form parameters + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig formParamsUpdateStrategy(UpdateStrategy updateStrategy) { + return new WebTestClientParamConfig(queryParamsUpdateStrategy, updateStrategy, + requestParameterUpdateStrategy, attributeUpdateStrategy, true); + } + + /** + * Set request parameter update strategy to the given value. + * A "request parameter" is a parameter that will turn into a form or query parameter depending on the request. For example: + *

+ * given().param("name", "value").when().get("/x"). .. + *

+ * + * @param updateStrategy The update strategy to use for request parameters + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig requestParamsUpdateStrategy(UpdateStrategy updateStrategy) { + return new WebTestClientParamConfig(queryParamsUpdateStrategy, formParamsUpdateStrategy, + updateStrategy, attributeUpdateStrategy, true); + } + + + /** + * Set query parameter update strategy to the given value. + * + * @param updateStrategy The update strategy to use for query parameters + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig queryParamsUpdateStrategy(UpdateStrategy updateStrategy) { + return new WebTestClientParamConfig(updateStrategy, formParamsUpdateStrategy, + requestParameterUpdateStrategy, attributeUpdateStrategy, true); + } + + /** + * Syntactic sugar. + * + * @return The same WebTestClientParamConfig instance. + */ + public WebTestClientParamConfig and() { + return this; + } + + /** + * Syntactic sugar. + * + * @return The same WebTestClientParamConfig instance. + */ + public WebTestClientParamConfig with() { + return this; + } + + /** + * Set attribute update strategy to the given value. + * + * @param updateStrategy The update strategy to use for attribute parameters + * @return A new instance of {@link WebTestClientParamConfig} + */ + public WebTestClientParamConfig attributeUpdateStrategy(UpdateStrategy updateStrategy) { + return new WebTestClientParamConfig(queryParamsUpdateStrategy, formParamsUpdateStrategy, + requestParameterUpdateStrategy, updateStrategy, true); + } + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/BuilderBasedWebTestClientFactory.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/BuilderBasedWebTestClientFactory.java new file mode 100644 index 000000000..a370437d9 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/BuilderBasedWebTestClientFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.module.webtestclient.config.WebTestClientConfig; + +import org.springframework.test.web.reactive.server.WebTestClient; + +public class BuilderBasedWebTestClientFactory implements WebTestClientFactory { + + private final WebTestClient.Builder builder; + + public BuilderBasedWebTestClientFactory(WebTestClient.Builder builder) { + this.builder = builder; + } + + @Override + public synchronized WebTestClient build(WebTestClientConfig webTestClientConfig) { + if (!isAssigned()) { + throw new IllegalStateException("You haven't configured a MockMVC instance. You can do this statically\n\nRestAssuredMockMvc.mockMvc(..)\nRestAssuredMockMvc.standaloneSetup(..);\nRestAssuredMockMvc.webAppContextSetup(..);\n\nor using the DSL:\n\ngiven().\n\t\tmockMvc(..). ..\n"); + } + return builder.build(); + } + + @Override + public boolean isAssigned() { + return builder != null; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ExchangeResultConverter.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ExchangeResultConverter.java new file mode 100644 index 000000000..3dec09b1b --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ExchangeResultConverter.java @@ -0,0 +1,101 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.filter.time.TimingFilter; +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.internal.ResponseParserRegistrar; +import io.restassured.internal.log.LogRepository; +import io.restassured.module.spring.commons.config.ConfigConverter; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseCookie; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.test.web.reactive.server.FluxExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.MimeType; +import org.springframework.util.MultiValueMap; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +class ExchangeResultConverter { + + WebTestClientRestAssuredResponseImpl toRestAssuredResponse(FluxExchangeResult result, + WebTestClient.ResponseSpec responseSpec, + long responseTime, LogRepository logRepository, + RestAssuredWebTestClientConfig config, + Consumer> consumer, + ResponseParserRegistrar responseParserRegistrar) { + WebTestClientRestAssuredResponseImpl restAssuredResponse = new WebTestClientRestAssuredResponseImpl(responseSpec, + logRepository); + restAssuredResponse.setConfig(ConfigConverter.convertToRestAssuredConfig(config)); + byte[] responseBodyContent = ofNullable(consumer).map(theConsumer -> + responseSpec.expectBody().consumeWith(theConsumer).returnResult().getResponseBodyContent()) + .orElseGet(() -> responseSpec.expectBody().returnResult().getResponseBodyContent()); + restAssuredResponse.setContent(responseBodyContent); + MediaType contentType = result.getResponseHeaders().getContentType(); + restAssuredResponse.setContentType(ofNullable(contentType).map(MimeType::toString).orElse(null)); + restAssuredResponse.setHasExpectations(false); + restAssuredResponse.setStatusCode(result.getStatus().value()); + List
responseHeaders = assembleHeaders(result.getResponseHeaders()); + restAssuredResponse.setResponseHeaders(new Headers(responseHeaders)); + restAssuredResponse.setRpr(responseParserRegistrar); + restAssuredResponse.setStatusLine(buildResultString(result.getStatus())); + restAssuredResponse.setFilterContextProperties(new HashMap() {{ + put(TimingFilter.RESPONSE_TIME_MILLISECONDS, responseTime); + }}); + restAssuredResponse.setCookies(convertCookies(result.getResponseCookies())); + return restAssuredResponse; + } + + private List
assembleHeaders(HttpHeaders headers) { + return headers.keySet().stream() + .map(headerName -> headers.get(headerName).stream() + .map(headerValue -> new Header(headerName, headerValue)) + .collect(Collectors.toList())).flatMap(Collection::stream).collect(Collectors.toList()); + } + + private String buildResultString(HttpStatus status) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(status.value()); + if (status.isError() && isNotBlank(status.getReasonPhrase())) { + stringBuilder.append(": "); + stringBuilder.append(status.getReasonPhrase()); + } + return stringBuilder.toString(); + } + + private Cookies convertCookies(MultiValueMap responseCookies) { + List cookies = responseCookies.keySet().stream().map(cookie -> responseCookies.get(cookie).stream() + .map(responseCookie -> new Cookie.Builder(responseCookie.getName(), responseCookie.getValue()).build()) + .collect(Collectors.toList()) + ).flatMap(Collection::stream).collect(Collectors.toList()); + return new Cookies(cookies); + } + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ResponseConverter.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ResponseConverter.java new file mode 100644 index 000000000..35c3ac62b --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ResponseConverter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.internal.RestAssuredResponseImpl; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.response.Response; + +class ResponseConverter { + + private ResponseConverter() { + } + + static Response toStandardResponse(WebTestClientResponse response) { + if (!(response instanceof WebTestClientRestAssuredResponseImpl)) { + throw new IllegalArgumentException(WebTestClientResponse.class.getName() + " must be an instance of " + + WebTestClientRestAssuredResponseImpl.class.getName()); + } + WebTestClientRestAssuredResponseImpl webTestClientRestAssuredResponse = (WebTestClientRestAssuredResponseImpl) response; + + RestAssuredResponseImpl standardResponse = new RestAssuredResponseImpl(); + standardResponse.setConnectionManager(webTestClientRestAssuredResponse.getConnectionManager()); + standardResponse.setContent(webTestClientRestAssuredResponse.getContent()); + standardResponse.setContentType(webTestClientRestAssuredResponse.getContentType()); + standardResponse.setCookies(webTestClientRestAssuredResponse.detailedCookies()); + standardResponse.setDecoderConfig(webTestClientRestAssuredResponse.getDecoderConfig()); + standardResponse.setDefaultContentType(webTestClientRestAssuredResponse.getDefaultContentType()); + standardResponse.setHasExpectations(webTestClientRestAssuredResponse.getHasExpectations()); + standardResponse.setResponseHeaders(webTestClientRestAssuredResponse.getResponseHeaders()); + standardResponse.setSessionIdName(webTestClientRestAssuredResponse.getSessionIdName()); + standardResponse.setStatusCode(webTestClientRestAssuredResponse.getStatusCode()); + standardResponse.setStatusLine(webTestClientRestAssuredResponse.getStatusLine()); + standardResponse.setRpr(webTestClientRestAssuredResponse.getRpr()); + standardResponse.setFilterContextProperties(webTestClientRestAssuredResponse.getFilterContextProperties()); + standardResponse.setLogRepository(webTestClientRestAssuredResponse.getLogRepository()); + return standardResponse; + } + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/StandaloneWebTestClientFactory.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/StandaloneWebTestClientFactory.java new file mode 100644 index 000000000..2e220f3d7 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/StandaloneWebTestClientFactory.java @@ -0,0 +1,80 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import org.springframework.context.ApplicationContext; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClientConfigurer; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.server.RouterFunction; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.partitioningBy; +import static java.util.stream.Collectors.toList; + +public class StandaloneWebTestClientFactory { + + public static WebTestClientFactory of(RouterFunction routerFunction, Object[] configurersOrExchangeFilterFunctions) { + WebTestClient.Builder builder = WebTestClient.bindToRouterFunction(routerFunction) + .configureClient(); + applyConfigurersAndFilter(configurersOrExchangeFilterFunctions, builder); + return new BuilderBasedWebTestClientFactory(builder); + } + + public static WebTestClientFactory of(Object[] controllersOrConfigurersOrExchangeFilterFunctions) { + Map> partitionedByConfigurer = Arrays.stream(controllersOrConfigurersOrExchangeFilterFunctions) + .collect(partitioningBy(element -> element instanceof WebTestClientConfigurer)); + List controllersAndExchangeFunctions = partitionedByConfigurer.get(false); + Map> partitionedByExchangeFunction = controllersAndExchangeFunctions.stream() + .collect(partitioningBy(element -> element instanceof ExchangeFilterFunction)); + List configurers = partitionedByConfigurer.get(true).stream() + .map(configurer -> (WebTestClientConfigurer) configurer) + .collect(toList()); + List exchangeFilterFunctions = partitionedByExchangeFunction.get(true).stream() + .map(element -> (ExchangeFilterFunction) element) + .collect(toList()); + WebTestClient.Builder builder = WebTestClient.bindToController(partitionedByExchangeFunction.get(false) + .toArray()) + .configureClient(); + configurers.forEach(builder::apply); + exchangeFilterFunctions.forEach(builder::filter); + return new BuilderBasedWebTestClientFactory(builder); + } + + public static WebTestClientFactory of(ApplicationContext applicationContext, + Object[] configurersOrExchangeFilterFunctions) { + WebTestClient.Builder builder = WebTestClient.bindToApplicationContext(applicationContext) + .configureClient(); + applyConfigurersAndFilter(configurersOrExchangeFilterFunctions, builder); + return new BuilderBasedWebTestClientFactory(builder); + } + + private static void applyConfigurersAndFilter(Object[] configurersOrExchangeFilterFunctions, + WebTestClient.Builder builder) { + Map> partitionedByConfigurer = Arrays.stream(configurersOrExchangeFilterFunctions) + .collect(partitioningBy(element -> element instanceof WebTestClientConfigurer)); + partitionedByConfigurer.get(true).stream().map(configurer -> (WebTestClientConfigurer) configurer) + .forEach(builder::apply); + partitionedByConfigurer.get(false).stream() + .filter(element -> element instanceof ExchangeFilterFunction) + .map(element -> (ExchangeFilterFunction) element) + .forEach(builder::filter); + } +} + diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ValidatableWebTestClientResponseImpl.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ValidatableWebTestClientResponseImpl.java new file mode 100644 index 000000000..45c7bebb9 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/ValidatableWebTestClientResponseImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.config.RestAssuredConfig; +import io.restassured.internal.ResponseParserRegistrar; +import io.restassured.internal.ValidatableResponseOptionsImpl; +import io.restassured.internal.assertion.AssertParameter; +import io.restassured.internal.log.LogRepository; +import io.restassured.module.webtestclient.response.ValidatableWebTestClientResponse; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.response.ExtractableResponse; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static io.restassured.module.webtestclient.internal.ResponseConverter.toStandardResponse; + +public class ValidatableWebTestClientResponseImpl extends ValidatableResponseOptionsImpl + implements ValidatableWebTestClientResponse { + + private final WebTestClientResponse response; + + public ValidatableWebTestClientResponseImpl(WebTestClient.ResponseSpec responseSpec, + ResponseParserRegistrar responseParserRegistrar, + RestAssuredConfig config, + WebTestClientResponse response, + ExtractableResponse extractableResponse, + LogRepository logRepository) { + super(responseParserRegistrar, config, toStandardResponse(response), extractableResponse, logRepository); + AssertParameter.notNull(responseSpec, WebTestClient.ResponseSpec.class); + this.response = response; + } + + @Override + public WebTestClientResponse originalResponse() { + return response; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientFactory.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientFactory.java new file mode 100644 index 000000000..91a6b1692 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.module.webtestclient.config.WebTestClientConfig; + +import org.springframework.test.web.reactive.server.WebTestClient; + +public interface WebTestClientFactory { + + /** + * Builds and returns a {@link WebTestClient} instance based on provided configuration + * @param webTestClientConfig configuration to be used during WebTestClient instantiation + * @return a WebTestClient instance + */ + WebTestClient build(WebTestClientConfig webTestClientConfig); + + /** + * Checks if underlying {@link WebTestClient} or {@link org.springframework.test.web.reactive.server.WebTestClient.Builder} + * is not null + * @return verification result + */ + boolean isAssigned(); +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestLogSpecificationImpl.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestLogSpecificationImpl.java new file mode 100644 index 000000000..a7535dfce --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestLogSpecificationImpl.java @@ -0,0 +1,129 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.authentication.NoAuthScheme; +import io.restassured.filter.Filter; +import io.restassured.filter.log.LogDetail; +import io.restassured.filter.log.RequestLoggingFilter; +import io.restassured.internal.LogSpecificationImpl; +import io.restassured.internal.RequestSpecificationImpl; +import io.restassured.module.webtestclient.specification.WebTestClientRequestLogSpecification; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Collections; + +public class WebTestClientRequestLogSpecificationImpl extends LogSpecificationImpl implements WebTestClientRequestLogSpecification { + + private final WebTestClientRequestSpecificationImpl requestSpecification; + + public WebTestClientRequestLogSpecificationImpl(WebTestClientRequestSpecificationImpl requestSpecification) { + this.requestSpecification = requestSpecification; + } + + @Override + public WebTestClientRequestSpecification body() { + return body(shouldPrettyPrint(toRequestSpecification())); + } + + @Override + public WebTestClientRequestSpecification body(boolean shouldPrettyPrint) { + return logWith(LogDetail.BODY, shouldPrettyPrint); + } + + @Override + public WebTestClientRequestSpecification all() { + return all(shouldPrettyPrint(toRequestSpecification())); + } + + @Override + public WebTestClientRequestSpecification all(boolean shouldPrettyPrint) { + return logWith(LogDetail.ALL, shouldPrettyPrint); + } + + @Override + public WebTestClientRequestSpecification everything() { + return all(); + } + + @Override + public WebTestClientRequestSpecification everything(boolean shouldPrettyPrint) { + return all(shouldPrettyPrint); + } + + @Override + public WebTestClientRequestSpecification headers() { + return logWith(LogDetail.HEADERS); + } + + @Override + public WebTestClientRequestSpecification cookies() { + return logWith(LogDetail.COOKIES); + } + + @Override + public WebTestClientRequestSpecification ifValidationFails() { + return ifValidationFails(LogDetail.ALL); + } + + @Override + public WebTestClientRequestSpecification ifValidationFails(LogDetail logDetail) { + return ifValidationFails(logDetail, shouldPrettyPrint(toRequestSpecification())); + } + + @Override + public WebTestClientRequestSpecification ifValidationFails(LogDetail logDetail, boolean shouldPrettyPrint) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(byteArrayOutputStream); + requestSpecification.getLogRepository().registerRequestLog(byteArrayOutputStream); + return logWith(logDetail, shouldPrettyPrint, printStream); + } + + public WebTestClientRequestSpecification params() { + return logWith(LogDetail.PARAMS); + } + + public WebTestClientRequestSpecification parameters() { + return logWith(LogDetail.PARAMS); + } + + private WebTestClientRequestSpecification logWith(LogDetail logDetail, boolean prettyPrintingEnabled, + PrintStream printStream) { + boolean shouldUrlEncodeRequestUri = requestSpecification.getRestAssuredWebTestClientConfig() + .getLogConfig().shouldUrlEncodeRequestUri(); + requestSpecification.setRequestLoggingFilter(new RequestLoggingFilter(logDetail, prettyPrintingEnabled, printStream, shouldUrlEncodeRequestUri)); + return requestSpecification; + } + + private WebTestClientRequestSpecification logWith(LogDetail logDetail) { + RequestSpecificationImpl reqSpec = toRequestSpecification(); + return logWith(logDetail, shouldPrettyPrint(reqSpec)); + } + + private RequestSpecificationImpl toRequestSpecification() { + return new RequestSpecificationImpl("", 8080, "", new NoAuthScheme(), + Collections.emptyList(), null, true, + requestSpecification.getRestAssuredConfig(), requestSpecification.getLogRepository(), null + ); + } + + private WebTestClientRequestSpecification logWith(LogDetail logDetail, boolean prettyPrintingEnabled) { + return logWith(logDetail, prettyPrintingEnabled, getPrintStream(toRequestSpecification())); + } + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSenderImpl.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSenderImpl.java new file mode 100644 index 000000000..799e34a4f --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSenderImpl.java @@ -0,0 +1,644 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.RestAssured; +import io.restassured.authentication.NoAuthScheme; +import io.restassured.builder.MultiPartSpecBuilder; +import io.restassured.filter.Filter; +import io.restassured.filter.log.RequestLoggingFilter; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.http.Method; +import io.restassured.internal.RequestSpecificationImpl; +import io.restassured.internal.ResponseParserRegistrar; +import io.restassured.internal.ResponseSpecificationImpl; +import io.restassured.internal.filter.FilterContextImpl; +import io.restassured.internal.log.LogRepository; +import io.restassured.internal.multipart.MultiPartInternal; +import io.restassured.internal.support.PathSupport; +import io.restassured.internal.util.SafeExceptionRethrower; +import io.restassured.module.spring.commons.HeaderHelper; +import io.restassured.module.spring.commons.ParamApplier; +import io.restassured.module.spring.commons.config.ConfigConverter; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSender; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import org.apache.commons.codec.Charsets; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.test.web.reactive.server.FluxExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriUtils; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +import static io.restassured.internal.assertion.AssertParameter.notNull; +import static io.restassured.internal.support.PathSupport.mergeAndRemoveDoubleSlash; +import static io.restassured.module.spring.commons.BodyHelper.toByteArray; +import static io.restassured.module.spring.commons.HeaderHelper.mapToArray; +import static io.restassured.module.spring.commons.RequestLogger.logParamsAndHeaders; +import static io.restassured.module.spring.commons.RequestLogger.logRequestBody; +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.trimToNull; +import static org.springframework.http.HttpMethod.DELETE; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.HEAD; +import static org.springframework.http.HttpMethod.OPTIONS; +import static org.springframework.http.HttpMethod.PATCH; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.http.HttpMethod.PUT; +import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; +import static org.springframework.http.MediaType.parseMediaType; + +public class WebTestClientRequestSenderImpl implements WebTestClientRequestSender { + + private static final String CONTENT_TYPE = "Content-Type"; + + private final WebTestClient webTestClient; + private final Map params; + private final Map queryParams; + private final Map formParams; + private final Map attributes; + private final RestAssuredWebTestClientConfig config; + private final Object requestBody; + private final Cookies cookies; + private final List multiParts; + private final String basePath; + private final ResponseSpecification responseSpecification; + private final LogRepository logRepository; + private Headers headers; + private final RequestLoggingFilter requestLoggingFilter; + private Consumer> consumer; + + @Override + public WebTestClientResponse get(Function uriFunction) { + return sendRequest(GET, uriFunction); + } + + @Override + public WebTestClientResponse post(Function uriFunction) { + return sendRequest(POST, uriFunction); + } + + @Override + public WebTestClientResponse put(Function uriFunction) { + return sendRequest(PUT, uriFunction); + } + + @Override + public WebTestClientResponse delete(Function uriFunction) { + return sendRequest(DELETE, uriFunction); + } + + @Override + public WebTestClientResponse patch(Function uriFunction) { + return sendRequest(PATCH, uriFunction); + } + + @Override + public WebTestClientResponse head(Function uriFunction) { + return sendRequest(HEAD, uriFunction); + } + + @Override + public WebTestClientResponse options(Function uriFunction) { + return sendRequest(OPTIONS, uriFunction); + } + + @Override + public WebTestClientResponse request(Method method, Function uriFunction) { + return request(notNull(method, Method.class).name(), uriFunction); + } + + @Override + public WebTestClientResponse request(String method, Function uriFunction) { + return sendRequest(toValidHttpMethod(method), uriFunction); + } + + private HttpMethod toValidHttpMethod(String method) { + String httpMethodAsString = notNull(trimToNull(method), "HTTP Method"); + HttpMethod httpMethod = HttpMethod.resolve(httpMethodAsString.toUpperCase()); + if (httpMethod == null) { + throw new IllegalArgumentException("HTTP method '" + method + "' is not supported by WebTestClient"); + } + return httpMethod; + } + + @Override + public WebTestClientResponse get(String path, Object... pathParams) { + return sendRequest(GET, path, pathParams); + } + + public WebTestClientRequestSenderImpl(WebTestClient webTestClient, Map params, Map queryParams, Map formParams, Map attributes, + RestAssuredWebTestClientConfig config, Object requestBody, Headers headers, + Cookies cookies, List multiParts, + RequestLoggingFilter requestLoggingFilter, String basePath, + ResponseSpecification responseSpecification, + LogRepository logRepository) { + this.webTestClient = webTestClient; + this.params = params; + this.queryParams = queryParams; + this.formParams = formParams; + this.attributes = attributes; + this.config = config; + this.requestBody = requestBody; + this.headers = headers; + this.cookies = cookies; + this.multiParts = multiParts; + this.basePath = basePath; + this.responseSpecification = responseSpecification; + this.logRepository = logRepository; + this.requestLoggingFilter = requestLoggingFilter; + } + + @Override + public WebTestClientRequestSender consumeWith(Consumer> consumer) { + this.consumer = consumer; + return this; + } + + @Override + public WebTestClientResponse get(String path, Map pathParams) { + return get(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse post(String path, Object... pathParams) { + return sendRequest(POST, path, pathParams); + } + + @Override + public WebTestClientResponse post(String path, Map pathParams) { + return post(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse put(String path, Object... pathParams) { + return sendRequest(PUT, path, pathParams); + } + + @Override + public WebTestClientResponse put(String path, Map pathParams) { + return put(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse delete(String path, Object... pathParams) { + return sendRequest(DELETE, path, pathParams); + } + + @Override + public WebTestClientResponse delete(String path, Map pathParams) { + return delete(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse head(String path, Object... pathParams) { + return sendRequest(HEAD, path, pathParams); + } + + @Override + public WebTestClientResponse head(String path, Map pathParams) { + return head(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse patch(String path, Object... pathParams) { + return sendRequest(PATCH, path, pathParams); + } + + @Override + public WebTestClientResponse patch(String path, Map pathParams) { + return patch(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse options(String path, Object... pathParams) { + return sendRequest(OPTIONS, path, pathParams); + } + + @Override + public WebTestClientResponse options(String path, Map pathParams) { + return options(path, mapToArray(pathParams)); + } + + @Override + public WebTestClientResponse get(URI uri) { + return get(uri.toString()); + } + + @Override + public WebTestClientResponse post(URI uri) { + return post(uri.toString()); + } + + @Override + public WebTestClientResponse put(URI uri) { + return put(uri.toString()); + } + + @Override + public WebTestClientResponse delete(URI uri) { + return delete(uri.toString()); + } + + @Override + public WebTestClientResponse head(URI uri) { + return head(uri.toString()); + } + + @Override + public WebTestClientResponse patch(URI uri) { + return patch(uri.toString()); + } + + @Override + public WebTestClientResponse options(URI uri) { + return options(uri.toString()); + } + + @Override + public WebTestClientResponse get(URL url) { + return get(url.toString()); + } + + @Override + public WebTestClientResponse post(URL url) { + return post(url.toString()); + } + + @Override + public WebTestClientResponse put(URL url) { + return put(url.toString()); + } + + @Override + public WebTestClientResponse delete(URL url) { + return delete(url.toString()); + } + + @Override + public WebTestClientResponse head(URL url) { + return head(url.toString()); + } + + @Override + public WebTestClientResponse patch(URL url) { + return patch(url.toString()); + } + + @Override + public WebTestClientResponse options(URL url) { + return options(url.toString()); + } + + @Override + public WebTestClientResponse get() { + return get(""); + } + + @Override + public WebTestClientResponse post() { + return post(""); + } + + @Override + public WebTestClientResponse put() { + return put(""); + } + + @Override + public WebTestClientResponse delete() { + return delete(""); + } + + @Override + public WebTestClientResponse head() { + return head(""); + } + + @Override + public WebTestClientResponse patch() { + return patch(""); + } + + @Override + public WebTestClientResponse options() { + return options(""); + } + + @Override + public WebTestClientResponse request(Method method) { + return request(method, ""); + } + + @Override + public WebTestClientResponse request(String method) { + return request(method, ""); + } + + @Override + public WebTestClientResponse request(Method method, String path, Object... pathParams) { + return request(notNull(method, Method.class).name(), path, pathParams); + } + + @Override + public WebTestClientResponse request(String method, String path, Object... pathParams) { + return sendRequest(toValidHttpMethod(method), path, pathParams); + } + + @Override + public WebTestClientResponse request(Method method, URI uri) { + return request(method, notNull(uri, URI.class).toString()); + } + + @Override + public WebTestClientResponse request(Method method, URL url) { + return request(method, notNull(url, URL.class).toString()); + } + + @Override + public WebTestClientResponse request(String method, URI uri) { + return request(method, notNull(uri, URI.class).toString()); + } + + @Override + public WebTestClientResponse request(String method, URL url) { + return request(method, notNull(url, URL.class).toString()); + } + + private WebTestClientResponse sendRequest(HttpMethod method, String path, Object[] pathParams) { + String requestContentType = HeaderHelper.findContentType(headers, (List) (List) multiParts, config); + WebTestClient.RequestBodySpec requestBodySpec = buildFromPath(method, requestContentType, path, pathParams); + addRequestElements(method, requestContentType, requestBodySpec); + logRequestIfApplicable(method, getBaseUri(path), path, pathParams); + return performRequest(requestBodySpec); + } + + private WebTestClient.RequestBodySpec buildFromPath(HttpMethod method, String requestContentType, String path, + Object[] pathParams) { + notNull(path, "Path"); + String baseUri = getBaseUri(path); + String uri = buildUri(method, requestContentType, baseUri); + return webTestClient.method(method).uri(uri, resolvePathParams(pathParams)); + } + + private void addRequestElements(HttpMethod method, String requestContentType, WebTestClient.RequestBodySpec requestBodySpec) { + verifyNoBodyAndMultipartTogether(); + if (isNotBlank(requestContentType)) { + requestBodySpec.contentType(parseMediaType(requestContentType)); + } + applyRequestBody(requestBodySpec); + applyMultipartBody(method, requestBodySpec); + applyAttributes(requestBodySpec); + headers.forEach(header -> requestBodySpec.header(header.getName(), header.getValue())); + cookies.asList().forEach(cookie -> requestBodySpec.cookie(cookie.getName(), cookie.getValue())); + } + + private void logRequestIfApplicable(HttpMethod method, String uri, String originalPath, Object[] unnamedPathParams) { + if (requestLoggingFilter == null) { + return; + } + final RequestSpecificationImpl reqSpec = new RequestSpecificationImpl("http://localhost", + RestAssured.UNDEFINED_PORT, "", new NoAuthScheme(), Collections.emptyList(), + null, true, ConfigConverter.convertToRestAssuredConfig(config), logRepository, null); + logParamsAndHeaders(reqSpec, method.toString(), uri, unnamedPathParams, params, queryParams, formParams, headers, cookies); + logRequestBody(reqSpec, requestBody, headers, (List) (List) multiParts, config); + ofNullable(multiParts).map(List::stream).orElseGet(Stream::empty) + .forEach(multiPart -> addMultipartToReqSpec(reqSpec, multiPart)); + String originalUriPath = PathSupport.getPath(originalPath); + String uriPath = PathSupport.getPath(uri); + requestLoggingFilter.filter(reqSpec, null, new FilterContextImpl(uri, originalUriPath, + uriPath, uri, uri, new Object[0], method.toString(), null, + Collections.emptyList().iterator(), new HashMap<>())); + } + + private String getBaseUri(String path) { + String baseUri; + if (isNotBlank(basePath)) { + baseUri = mergeAndRemoveDoubleSlash(basePath, path); + } else { + baseUri = path; + } + return baseUri; + } + + private WebTestClientResponse performRequest(WebTestClient.RequestBodySpec requestBuilder) { + FluxExchangeResult result; + WebTestClientRestAssuredResponseImpl restAssuredResponse; + try { + final long start = System.currentTimeMillis(); + WebTestClient.ResponseSpec responseSpec = requestBuilder.exchange(); + final long responseTime = System.currentTimeMillis() - start; + result = responseSpec.returnResult(byte[].class); + restAssuredResponse = new ExchangeResultConverter().toRestAssuredResponse(result, responseSpec, responseTime, + logRepository, config, consumer, getRpr()); + if (responseSpecification != null) { + responseSpecification.validate(ResponseConverter.toStandardResponse(restAssuredResponse)); + } + } catch (Exception e) { + return SafeExceptionRethrower.safeRethrow(e); + } + return restAssuredResponse; + } + + private String buildUri(HttpMethod method, String requestContentType, String baseUri) { + final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri); + applyQueryParams(uriComponentsBuilder); + applyParams(method, uriComponentsBuilder, requestContentType); + applyFormParams(method, uriComponentsBuilder, requestContentType); + return uriComponentsBuilder.build().toUriString(); + } + + private Object[] resolvePathParams(Object[] pathParams) { + Arrays.stream(pathParams).filter(param -> !(param instanceof String)) + .findAny().ifPresent(param -> { + throw new IllegalArgumentException("Only Strings allowed in path parameters."); + }); + return Arrays.stream(pathParams) + .map(param -> UriUtils.encode((String) param, Charsets.UTF_8)).toArray(); + } + + private void verifyNoBodyAndMultipartTogether() { + if (requestBody != null && !multiParts.isEmpty()) { + throw new IllegalStateException("You cannot specify a request body and a multi-part body in the same request." + + " Perhaps you want to change the body to a multi part?"); + } + } + + private void applyRequestBody(WebTestClient.RequestBodySpec requestBodySpec) { + if (requestBody != null) { + if (requestBody instanceof byte[]) { + requestBodySpec.syncBody(requestBody); + } else if (requestBody instanceof File) { + byte[] bytes = toByteArray((File) requestBody); + requestBodySpec.syncBody(bytes); + } else { + requestBodySpec.syncBody(requestBody.toString()); + } + } + } + + private void applyMultipartBody(HttpMethod method, WebTestClient.RequestBodySpec requestBodySpec) { + if (!multiParts.isEmpty()) { + if (method != POST) { + throw new IllegalArgumentException("Currently multi-part file data uploading only works for " + POST); + } + requestBodySpec.syncBody(getMultipartBody()); + } + } + + private void applyAttributes(WebTestClient.RequestBodySpec requestBodySpec) { + if (!attributes.isEmpty()) { + new ParamApplier(attributes) { + @Override + protected void applyParam(String paramName, String[] paramValues) { + requestBodySpec.attribute(paramName, paramValues[0]); + } + }.applyParams(); + } + } + + private void addMultipartToReqSpec(RequestSpecification requestSpecification, MultiPartInternal multiPart) { + requestSpecification.multiPart(new MultiPartSpecBuilder(multiPart.getContent()) + .controlName(multiPart.getControlName()). + fileName(multiPart.getFileName()). + mimeType(multiPart.getMimeType()). + build()); + } + + private void applyQueryParams(UriComponentsBuilder uriComponentsBuilder) { + if (!queryParams.isEmpty()) { + new ParamApplier(queryParams) { + @Override + protected void applyParam(String paramName, String[] paramValues) { + uriComponentsBuilder.queryParam(paramName, paramValues); + } + }.applyParams(); + } + } + + private void applyParams(HttpMethod method, UriComponentsBuilder uriComponentsBuilder, String requestContentType) { + if (!params.isEmpty()) { + new ParamApplier(params) { + @Override + protected void applyParam(String paramName, String[] paramValues) { + uriComponentsBuilder.queryParam(paramName, paramValues); + } + }.applyParams(); + + if (isBlank(requestContentType) && method == POST && !isMultipartRequest()) { + setContentTypeToApplicationFormUrlEncoded(); + } + } + } + + private void applyFormParams(HttpMethod method, UriComponentsBuilder uriComponentsBuilder, String requestContentType) { + if (!formParams.isEmpty()) { + if (method == GET) { + throw new IllegalArgumentException("Cannot use form parameters in a GET request"); + } + new ParamApplier(formParams) { + @Override + protected void applyParam(String paramName, String[] paramValues) { + uriComponentsBuilder.queryParam(paramName, paramValues); + } + }.applyParams(); + if (isBlank(requestContentType) && !isMultipartRequest()) { + setContentTypeToApplicationFormUrlEncoded(); + } + } + } + + private MultiValueMap> getMultipartBody() { + MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder(); + multiParts.stream().forEach(multipart -> multipartBodyBuilder.part(multipart.getFileName(), multipart.getContentBody())); + return multipartBodyBuilder.build(); + } + + private boolean isMultipartRequest() { + return !multiParts.isEmpty(); + } + + private void setContentTypeToApplicationFormUrlEncoded() { + String requestContentType = parseMediaType(HeaderHelper.buildApplicationFormEncodedContentType(config, + APPLICATION_FORM_URLENCODED_VALUE)).toString(); + List
newHeaders = new ArrayList<>(headers.asList()); + newHeaders.add(new Header(CONTENT_TYPE, requestContentType)); + headers = new Headers(newHeaders); + } + + private WebTestClientResponse sendRequest(HttpMethod method, Function uriFunction) { + String requestContentType = HeaderHelper.findContentType(headers, (List) (List) multiParts, config); + WebTestClient.RequestBodySpec requestBodySpec = buildFromUriFunction(method, uriFunction); + addRequestElements(method, requestContentType, requestBodySpec); + logRequestIfApplicable(method, uriFunction); + return performRequest(requestBodySpec); + } + + private WebTestClient.RequestBodySpec buildFromUriFunction(HttpMethod method, Function uriFunction) { + return webTestClient.method(method).uri(uriFunction); + } + + private void logRequestIfApplicable(HttpMethod method, Function uriFunction) { + if (requestLoggingFilter == null) { + return; + } + final RequestSpecificationImpl reqSpec = new RequestSpecificationImpl("http://localhost", + RestAssured.UNDEFINED_PORT, "", new NoAuthScheme(), Collections.emptyList(), + null, true, ConfigConverter.convertToRestAssuredConfig(config), logRepository, null); + logParamsAndHeaders(reqSpec, method.toString(), "Request from uri function" + uriFunction.toString(), + null, params, queryParams, formParams, + headers, cookies); + logRequestBody(reqSpec, requestBody, headers, (List) (List) multiParts, config); + ofNullable(multiParts).map(List::stream).orElseGet(Stream::empty) + .forEach(multiPart -> addMultipartToReqSpec(reqSpec, multiPart)); + requestLoggingFilter.filter(reqSpec, null, + new FilterContextImpl("Request from uri function" + uriFunction.toString(), + null, null, null, null, new Object[0], + method.toString(), null, Collections.emptyList().iterator(), new HashMap<>())); + } + + private ResponseParserRegistrar getRpr() { + if (responseSpecification instanceof ResponseSpecificationImpl) { + return ((ResponseSpecificationImpl) responseSpecification).getRpr(); + } + return new ResponseParserRegistrar(); + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSpecificationImpl.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSpecificationImpl.java new file mode 100644 index 000000000..aeaf8ad59 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRequestSpecificationImpl.java @@ -0,0 +1,970 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +import io.restassured.config.LogConfig; +import io.restassured.config.MultiPartConfig; +import io.restassured.config.ParamConfig; +import io.restassured.config.RestAssuredConfig; +import io.restassured.filter.log.RequestLoggingFilter; +import io.restassured.http.ContentType; +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.http.Method; +import io.restassured.internal.MapCreator; +import io.restassured.internal.log.LogRepository; +import io.restassured.internal.mapping.ObjectMapping; +import io.restassured.internal.multipart.MultiPartInternal; +import io.restassured.internal.support.ParameterUpdater; +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperType; +import io.restassured.module.spring.commons.BodyHelper; +import io.restassured.module.spring.commons.CookieHelper; +import io.restassured.module.spring.commons.HeaderHelper; +import io.restassured.module.spring.commons.Serializer; +import io.restassured.module.spring.commons.config.AsyncConfig; +import io.restassured.module.spring.commons.config.ConfigConverter; +import io.restassured.module.spring.commons.config.ConfigMergeUtils; +import io.restassured.module.spring.commons.config.SpecificationConfig; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.config.WebTestClientParamConfig; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.module.webtestclient.specification.WebTestClientRequestLogSpecification; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSender; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification; +import io.restassured.specification.ResponseSpecification; + +import org.springframework.context.ApplicationContext; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClientConfigurer; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.util.UriBuilder; + +import static io.restassured.internal.MapCreator.CollisionStrategy.OVERWRITE; +import static io.restassured.internal.assertion.AssertParameter.notNull; +import static io.restassured.internal.multipart.MultiPartInternal.OCTET_STREAM; +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +public class WebTestClientRequestSpecificationImpl implements WebTestClientRequestSpecification { + + private static final String CONTENT_TYPE = "Content-Type"; + private static final String ACCEPT = "Accept"; + private final Map params = new LinkedHashMap(); + private final Map queryParams = new LinkedHashMap(); + private final Map formParams = new LinkedHashMap(); + private final Map attributes = new LinkedHashMap(); + private final ResponseSpecification responseSpecification; + private RestAssuredWebTestClientConfig config; + private Object requestBody = null; + private LogRepository logRepository; + private WebTestClientFactory webTestClientFactory; + private final ParameterUpdater + parameterUpdater = new ParameterUpdater(WebTestClientRequestSpecificationImpl.this::serializeIfNeeded); + private Headers requestHeaders = new Headers(); + private String basePath; + private RequestLoggingFilter requestLoggingFilter; + private List multiParts = new ArrayList(); + private Cookies cookies = new Cookies(); + private AsyncConfig asyncConfig; + + + public WebTestClientRequestSpecificationImpl(WebTestClientFactory webTestClientFactory, + RestAssuredWebTestClientConfig config, + String basePath, + WebTestClientRequestSpecification requestSpecification, + ResponseSpecification responseSpecification) { + this.logRepository = new LogRepository(); + this.basePath = basePath; + this.responseSpecification = responseSpecification; + assignConfig(config); + this.webTestClientFactory = webTestClientFactory == null ? new BuilderBasedWebTestClientFactory(null) + : webTestClientFactory; + if (requestSpecification != null) { + spec(requestSpecification); + } + } + + private void assignConfig(RestAssuredWebTestClientConfig config) { + if (config == null) { + this.config = new RestAssuredWebTestClientConfig(); + } else { + this.config = config; + } + } + + @Override + public WebTestClientRequestSpecification contentType(ContentType contentType) { + notNull(contentType, "contentType"); + return header(CONTENT_TYPE, contentType.toString()); + } + + @Override + public WebTestClientRequestSpecification contentType(String contentType) { + notNull(contentType, "contentType"); + return header(CONTENT_TYPE, contentType); + } + + @Override + public WebTestClientRequestSpecification accept(ContentType contentType) { + notNull(contentType, "contentType"); + return header(ACCEPT, contentType.getAcceptHeader()); + } + + @Override + public WebTestClientRequestSpecification accept(String mediaTypes) { + notNull(mediaTypes, "mediaTypes"); + return header(ACCEPT, mediaTypes); + } + + @Override + public WebTestClientRequestSpecification headers(String firstHeaderName, Object firstHeaderValue, Object... headerNameValuePairs) { + return headers(MapCreator.createMapFromParams(MapCreator.CollisionStrategy.MERGE, + firstHeaderName, firstHeaderValue, headerNameValuePairs)); + } + + @Override + public WebTestClientRequestSpecification headers(Map headers) { + notNull(headers, "headers"); + this.requestHeaders = HeaderHelper.headers(requestHeaders, headers, config); + return this; + } + + @Override + public WebTestClientRequestSpecification headers(Headers headers) { + notNull(headers, "Headers"); + requestHeaders = HeaderHelper.headers(requestHeaders, headers, config.getHeaderConfig()); + return this; + } + + @Override + public WebTestClientRequestSpecification header(String headerName, Object headerValue, Object... additionalHeaderValues) { + notNull(headerName, "Header name"); + notNull(headerValue, "Header value"); + return headers(HeaderHelper.headers(requestHeaders, headerName, headerValue, config, additionalHeaderValues)); + } + + @Override + public WebTestClientRequestSpecification header(Header header) { + notNull(header, "Header"); + return headers(new Headers(Collections.singletonList(header))); + } + + @Override + public WebTestClientRequestLogSpecification log() { + return new WebTestClientRequestLogSpecificationImpl(this); + } + + @Override + public WebTestClientRequestSpecification params(String firstParameterName, Object firstParameterValue, + Object... parameterNameValuePairs) { + notNull(firstParameterName, "firstParameterName"); + notNull(firstParameterValue, "firstParameterValue"); + return params(MapCreator.createMapFromParams(OVERWRITE, firstParameterName, + firstParameterValue, parameterNameValuePairs)); + } + + @Override + public WebTestClientRequestSpecification params(Map parametersMap) { + notNull(parametersMap, "parametersMap"); + parameterUpdater.updateParameters(convert(config.getParamConfig().requestParamsUpdateStrategy()), + (Map) parametersMap, params); + return this; + } + + @Override + public WebTestClientRequestSpecification param(String parameterName, Object... parameterValues) { + notNull(parameterName, "parameterName"); + parameterUpdater.updateZeroToManyParameters(convert(config.getParamConfig().requestParamsUpdateStrategy()), + params, parameterName, parameterValues); + return this; + } + + @Override + public WebTestClientRequestSpecification param(String parameterName, Collection parameterValues) { + notNull(parameterName, "parameterName"); + notNull(parameterValues, "parameterValues"); + parameterUpdater.updateCollectionParameter(convert(config.getParamConfig().requestParamsUpdateStrategy()), + params, parameterName, (Collection) parameterValues); + return this; + } + + @Override + public WebTestClientRequestSpecification queryParams(String firstParameterName, Object firstParameterValue, + Object... parameterNameValuePairs) { + notNull(firstParameterName, "firstParameterName"); + notNull(firstParameterValue, "firstParameterValue"); + return queryParams(MapCreator.createMapFromParams(OVERWRITE, firstParameterName, + firstParameterValue, parameterNameValuePairs)); + } + + @Override + public WebTestClientRequestSpecification queryParams(Map parametersMap) { + notNull(parametersMap, "parametersMap"); + parameterUpdater.updateParameters(convert(config.getParamConfig().queryParamsUpdateStrategy()), + (Map) parametersMap, queryParams); + return this; + } + + @Override + public WebTestClientRequestSpecification queryParam(String parameterName, Object... parameterValues) { + notNull(parameterName, "parameterName"); + parameterUpdater.updateZeroToManyParameters(convert(config.getParamConfig().queryParamsUpdateStrategy()), + queryParams, parameterName, parameterValues); + return this; + } + + @Override + public WebTestClientRequestSpecification queryParam(String parameterName, Collection parameterValues) { + notNull(parameterName, "parameterName"); + notNull(parameterValues, "parameterValues"); + parameterUpdater.updateCollectionParameter(convert(config.getParamConfig().queryParamsUpdateStrategy()), + queryParams, parameterName, (Collection) parameterValues); + return this; + } + + @Override + public WebTestClientRequestSpecification formParams(String firstParameterName, Object firstParameterValue, + Object... parameterNameValuePairs) { + notNull(firstParameterName, "firstParameterName"); + notNull(firstParameterValue, "firstParameterValue"); + return formParams(MapCreator.createMapFromParams(OVERWRITE, firstParameterName, + firstParameterValue, parameterNameValuePairs)); + } + + @Override + public WebTestClientRequestSpecification formParams(Map parametersMap) { + notNull(parametersMap, "parametersMap"); + parameterUpdater.updateParameters(convert(config.getParamConfig().formParamsUpdateStrategy()), + (Map) parametersMap, formParams); + return this; + } + + @Override + public WebTestClientRequestSpecification formParam(String parameterName, Object... parameterValues) { + notNull(parameterName, "parameterName"); + parameterUpdater.updateZeroToManyParameters(convert(config.getParamConfig().formParamsUpdateStrategy()), + formParams, parameterName, parameterValues); + return this; + } + + @Override + public WebTestClientRequestSpecification formParam(String parameterName, Collection parameterValues) { + notNull(parameterName, "parameterName"); + notNull(parameterValues, "parameterValues"); + parameterUpdater.updateCollectionParameter(convert(config.getParamConfig().formParamsUpdateStrategy()), + formParams, parameterName, (Collection) parameterValues); + return this; + } + + /** + * + * @param attributeName The attribute name + * @param attributeValue The attribute value + * @return WebTestClientRequestSpecification with updated attributes + * Note: This will set attributes on `ClientRequest` in `WebTestClient`; given the way `WebTesClient` works under + * the hood, these arguments remain on client side only and will not be propagated to the `ServerRequest`. + */ + @Override + public WebTestClientRequestSpecification attribute(String attributeName, Object attributeValue) { + notNull(attributeName, "attributeName"); + notNull(attributeValue, "attributeValue"); + ParamConfig paramConfig = config.getParamConfig(); + parameterUpdater.updateZeroToManyParameters(convert(toWebTestClientParamConfig(paramConfig) + .attributeUpdateStrategy()), + attributes, attributeName, attributeValue); + return this; + } + + /** + * + * @param attributesMap The Map containing the request attribute names and their values + * @return WebTestClientRequestSpecification with updated attributes + * Note: This will set attributes on `ClientRequest` in `WebTestClient`; given the way `WebTesClient` works under + * the hood, these arguments remain on client side only and will not be propagated to the `ServerRequest`. + */ + @Override + public WebTestClientRequestSpecification attributes(Map attributesMap) { + notNull(attributesMap, "attributesMap"); + parameterUpdater.updateParameters(convert(toWebTestClientParamConfig(config.getParamConfig()) + .attributeUpdateStrategy()), (Map) attributesMap, attributes); + return this; + } + + @Override + public WebTestClientRequestSpecification body(String body) { + this.requestBody = body; + return this; + } + + @Override + public WebTestClientRequestSpecification body(byte[] body) { + this.requestBody = body; + return this; + } + + @Override + public WebTestClientRequestSpecification body(File body) { + this.requestBody = body; + return this; + } + + @Override + public WebTestClientRequestSpecification body(Object object) { + notNull(object, "object"); + this.requestBody = BodyHelper.toStringBody(object, config, requestHeaders); + return this; + } + + @Override + public WebTestClientRequestSpecification body(Object object, ObjectMapper mapper) { + notNull(object, "object"); + notNull(mapper, "Object mapper"); + this.requestBody = BodyHelper.toSerializedBody(object, mapper, config, requestHeaders); + return this; + } + + @Override + public WebTestClientRequestSpecification body(Object object, ObjectMapperType mapperType) { + notNull(object, "object"); + notNull(mapperType, "Object mapper type"); + String requestContentType = getRequestContentType(); + this.requestBody = ObjectMapping.serialize(object, requestContentType, + Serializer.findEncoderCharsetOrReturnDefault(requestContentType, config), mapperType, + config.getObjectMapperConfig(), config.getEncoderConfig()); + return this; + } + + @Override + public WebTestClientRequestSpecification cookies(String firstCookieName, Object firstCookieValue, Object... cookieNameValuePairs) { + return cookies(MapCreator.createMapFromParams(OVERWRITE, firstCookieName, firstCookieValue, cookieNameValuePairs)); + } + + @Override + public WebTestClientRequestSpecification cookies(Map cookies) { + notNull(cookies, "cookies"); + this.cookies = CookieHelper.cookies(this.cookies, cookies, requestHeaders, config); + return this; + } + + @Override + public WebTestClientRequestSpecification cookies(Cookies cookies) { + notNull(cookies, "Cookies"); + this.cookies = CookieHelper.cookies(this.cookies, cookies); + return this; + } + + @Override + public WebTestClientRequestSpecification cookie(String cookieName, Object cookieValue, Object... additionalValues) { + notNull(cookieName, "Cookie name"); + notNull(cookieValue, "Cookie value"); + return cookies(CookieHelper.cookie(cookieName, cookieValue, requestHeaders, config, additionalValues)); + } + + @Override + public WebTestClientRequestSpecification cookie(Cookie cookie) { + notNull(cookie, "Cookie"); + return cookies(new Cookies(Collections.singletonList(cookie))); + } + + @Override + public WebTestClientRequestSpecification multiPart(File file) { + MultiPartConfig multiPartConfig = config.getMultiPartConfig(); + multiParts.add(new MultiPartInternal(file, multiPartConfig.defaultControlName(), file.getName(), OCTET_STREAM)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, File file) { + multiParts.add(new MultiPartInternal(file, controlName, file.getName(), OCTET_STREAM)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, File file, String mimeType) { + multiParts.add(new MultiPartInternal(file, controlName, file.getName(), mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, Object object) { + MultiPartConfig multiPartConfig = config.getMultiPartConfig(); + multiParts.add(new MultiPartInternal(serializeIfNeeded(object), controlName, multiPartConfig.defaultFileName())); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, Object object, String mimeType) { + MultiPartConfig multiPartConfig = config.getMultiPartConfig(); + multiParts.add(new MultiPartInternal(Serializer.serializeIfNeeded(object, mimeType, config), controlName, + multiPartConfig.defaultFileName(), mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String filename, Object object, String mimeType) { + multiParts.add(new MultiPartInternal(Serializer.serializeIfNeeded(object, mimeType, config), + controlName, filename, mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String fileName, byte[] bytes) { + multiParts.add(new MultiPartInternal(bytes, controlName, fileName, OCTET_STREAM)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String fileName, byte[] bytes, String mimeType) { + multiParts.add(new MultiPartInternal(bytes, controlName, fileName, mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String fileName, InputStream stream) { + multiParts.add(new MultiPartInternal(stream, controlName, fileName, OCTET_STREAM)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String fileName, InputStream stream, String mimeType) { + multiParts.add(new MultiPartInternal(stream, controlName, fileName, mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String contentBody) { + MultiPartConfig multiPartConfig = config.getMultiPartConfig(); + multiParts.add(new MultiPartInternal(contentBody, controlName, multiPartConfig.defaultFileName(), OCTET_STREAM)); + return this; + } + + @Override + public WebTestClientRequestSpecification multiPart(String controlName, String contentBody, String mimeType) { + MultiPartConfig multiPartConfig = config.getMultiPartConfig(); + multiParts.add(new MultiPartInternal(contentBody, controlName, multiPartConfig.defaultFileName(), mimeType)); + return this; + } + + @Override + public WebTestClientRequestSpecification config(RestAssuredWebTestClientConfig config) { + assignConfig(config); + return this; + } + + @Override + public WebTestClientRequestSpecification config(SpecificationConfig config) { + if (!(config instanceof RestAssuredWebTestClientConfig)) { + throw new IllegalArgumentException("Only WebTestClientRequestSpecificationConfig allowed here"); + } + assignConfig((RestAssuredWebTestClientConfig) config); + return this; + } + + @Override + public WebTestClientRequestSpecification spec(WebTestClientRequestSpecification requestSpecificationToMerge) { + notNull(requestSpecificationToMerge, WebTestClientRequestSpecification.class); + + if (!(requestSpecificationToMerge instanceof WebTestClientRequestSpecificationImpl)) { + throw new IllegalArgumentException("requestSpecificationToMerge must be an instance of " + WebTestClientRequestSpecificationImpl.class.getName()); + } + WebTestClientRequestSpecificationImpl specificationToMerge = (WebTestClientRequestSpecificationImpl) requestSpecificationToMerge; + Object otherRequestBody = specificationToMerge.getRequestBody(); + if (otherRequestBody != null) { + requestBody = otherRequestBody; + } + if (isNotEmpty(specificationToMerge.getBasePath())) { + basePath = specificationToMerge.getBasePath(); + } + WebTestClientFactory otherWebTestClientFactory = specificationToMerge.getWebTestClientFactory(); + if (otherWebTestClientFactory != null && otherWebTestClientFactory.isAssigned()) { + webTestClientFactory = otherWebTestClientFactory; + } + cookies(specificationToMerge.getCookies()); + headers(specificationToMerge.getRequestHeaders()); + mergeConfig(this, specificationToMerge); + formParams(specificationToMerge.getFormParams()); + queryParams(specificationToMerge.getQueryParams()); + params(specificationToMerge.getParams()); + attributes(specificationToMerge.getAttributes()); + multiParts.addAll(specificationToMerge.getMultiParts()); + RequestLoggingFilter otherRequestLoggingFilter = specificationToMerge.getRequestLoggingFilter(); + if (otherRequestLoggingFilter != null) { + requestLoggingFilter = otherRequestLoggingFilter; + } + AsyncConfig otherAsyncConfig = specificationToMerge.getAsyncConfig(); + if (otherAsyncConfig != null) { + asyncConfig = otherAsyncConfig; + } + return this; + } + + @Override + public WebTestClientRequestSpecification sessionId(String sessionIdValue) { + return sessionId(config.getSessionConfig().sessionIdName(), sessionIdValue); + } + + @Override + public WebTestClientRequestSpecification sessionId(String sessionIdName, String sessionIdValue) { + notNull(sessionIdName, "Session id name"); + notNull(sessionIdValue, "Session id value"); + if (cookies.hasCookieWithName(sessionIdName)) { + CookieHelper.sessionId(cookies, sessionIdName, sessionIdValue); + } else { + cookie(sessionIdName, sessionIdValue); + } + return this; + } + + @Override + public WebTestClientRequestSender when() { + LogConfig logConfig = config.getLogConfig(); + if (requestLoggingFilter == null && logConfig.isLoggingOfRequestAndResponseIfValidationFailsEnabled()) { + log().ifValidationFails(logConfig.logDetailOfRequestAndResponseIfValidationFails(), + logConfig.isPrettyPrintingEnabled()); + } + WebTestClient webTestClient = webTestClientFactory.build(config.getWebTestClientConfig()); + return new WebTestClientRequestSenderImpl(webTestClient, params, queryParams, formParams, attributes, config, requestBody, + requestHeaders, cookies, multiParts, requestLoggingFilter, basePath, + responseSpecification, logRepository); + } + + @Override + public WebTestClientRequestSpecification standaloneSetup(Object... controllerOrWebTestClientConfigurer) { + WebTestClientFactory webTestClientFactory = StandaloneWebTestClientFactory.of(controllerOrWebTestClientConfigurer); + return toRequestSpecification(webTestClientFactory); + } + + @Override + public WebTestClientRequestSpecification standaloneSetup(WebTestClient.Builder builder) { + notNull(builder, WebTestClient.Builder.class); + return toRequestSpecification(new BuilderBasedWebTestClientFactory(builder)); + } + + @Override + public WebTestClientRequestSpecification standaloneSetup(RouterFunction routerFunction, WebTestClientConfigurer... configurers) { + notNull(routerFunction, RouterFunction.class); + WebTestClientFactory webTestClientFactory = StandaloneWebTestClientFactory.of(routerFunction, configurers); + return toRequestSpecification(webTestClientFactory); + } + + @Override + public WebTestClientRequestSpecification webTestClient(WebTestClient webTestClient) { + notNull(webTestClient, WebTestClient.class); + return toRequestSpecification(new WrapperWebTestClientFactory(webTestClient)); + } + + @Override + public WebTestClientRequestSpecification webAppContextSetup(WebApplicationContext context, WebTestClientConfigurer... configurers) { + return applicationContextSetup(context, configurers); + } + + @Override + public WebTestClientRequestSpecification applicationContextSetup(ApplicationContext context, WebTestClientConfigurer... configurers) { + WebTestClientFactory webTestClientFactory = StandaloneWebTestClientFactory.of(context, configurers); + return toRequestSpecification(webTestClientFactory); + } + + @Override + public WebTestClientRequestSpecification and() { + return this; + } + + private WebTestClientRequestSpecification toRequestSpecification(WebTestClientFactory webTestClientFactory) { + this.webTestClientFactory = webTestClientFactory; + return this; + } + + public Object getRequestBody() { + return requestBody; + } + + public String getRequestContentType() { + Header header = requestHeaders.get(CONTENT_TYPE); + if (header != null) { + return header.getValue(); + } + return null; + } + + @Override + public WebTestClientResponse get(Function uriFunction) { + return when().get(uriFunction); + } + + @Override + public WebTestClientResponse post(Function uriFunction) { + return when().post(uriFunction); + } + + @Override + public WebTestClientResponse put(Function uriFunction) { + return when().put(uriFunction); + } + + @Override + public WebTestClientResponse delete(Function uriFunction) { + return when().delete(uriFunction); + } + + @Override + public WebTestClientResponse patch(Function uriFunction) { + return when().patch(uriFunction); + } + + @Override + public WebTestClientResponse head(Function uriFunction) { + return when().head(uriFunction); + } + + @Override + public WebTestClientResponse options(Function uriFunction) { + return when().options(uriFunction); + } + + @Override + public WebTestClientResponse request(Method method, Function uriFunction) { + return when().request(method, uriFunction); + } + + @Override + public WebTestClientResponse request(String method, Function uriFunction) { + return when().request(method, uriFunction); + } + + @Override + public WebTestClientRequestSender consumeWith(Consumer> consumer) { + return when().consumeWith(consumer); + } + + @Override + public WebTestClientResponse get(String path, Object... pathParams) { + return when().get(path, pathParams); + } + + @Override + public WebTestClientResponse get(String path, Map pathParams) { + return when().get(path, pathParams); + } + + @Override + public WebTestClientResponse post(String path, Object... pathParams) { + return when().post(path, pathParams); + } + + @Override + public WebTestClientResponse post(String path, Map pathParams) { + return when().post(path, pathParams); + } + + @Override + public WebTestClientResponse put(String path, Object... pathParams) { + return when().put(path, pathParams); + } + + @Override + public WebTestClientResponse put(String path, Map pathParams) { + return when().put(path, pathParams); + } + + @Override + public WebTestClientResponse delete(String path, Object... pathParams) { + return when().delete(path, pathParams); + } + + @Override + public WebTestClientResponse delete(String path, Map pathParams) { + return when().delete(path, pathParams); + } + + @Override + public WebTestClientResponse head(String path, Object... pathParams) { + return when().head(path, pathParams); + } + + @Override + public WebTestClientResponse head(String path, Map pathParams) { + return when().head(path, pathParams); + } + + @Override + public WebTestClientResponse patch(String path, Object... pathParams) { + return when().patch(path, pathParams); + } + + @Override + public WebTestClientResponse patch(String path, Map pathParams) { + return when().patch(path, pathParams); + } + + @Override + public WebTestClientResponse options(String path, Object... pathParams) { + return when().options(path, pathParams); + } + + @Override + public WebTestClientResponse options(String path, Map pathParams) { + return when().options(path, pathParams); + } + + @Override + public WebTestClientResponse get(URI uri) { + return when().get(uri); + } + + @Override + public WebTestClientResponse post(URI uri) { + return when().post(uri); + } + + @Override + public WebTestClientResponse put(URI uri) { + return when().put(uri); + } + + @Override + public WebTestClientResponse delete(URI uri) { + return when().delete(uri); + } + + @Override + public WebTestClientResponse head(URI uri) { + return when().head(uri); + } + + @Override + public WebTestClientResponse patch(URI uri) { + return when().patch(uri); + } + + @Override + public WebTestClientResponse options(URI uri) { + return when().options(uri); + } + + @Override + public WebTestClientResponse get(URL url) { + return when().get(url); + } + + @Override + public WebTestClientResponse post(URL url) { + return when().post(url); + } + + @Override + public WebTestClientResponse put(URL url) { + return when().put(url); + } + + @Override + public WebTestClientResponse delete(URL url) { + return when().delete(url); + } + + @Override + public WebTestClientResponse head(URL url) { + return when().head(url); + } + + @Override + public WebTestClientResponse patch(URL url) { + return when().patch(url); + } + + @Override + public WebTestClientResponse options(URL url) { + return when().options(url); + } + + @Override + public WebTestClientResponse get() { + return when().get(); + } + + @Override + public WebTestClientResponse post() { + return when().post(); + } + + @Override + public WebTestClientResponse put() { + return when().put(); + } + + @Override + public WebTestClientResponse delete() { + return when().delete(); + } + + @Override + public WebTestClientResponse head() { + return when().head(); + } + + @Override + public WebTestClientResponse patch() { + return when().patch(); + } + + @Override + public WebTestClientResponse options() { + return when().options(); + } + + @Override + public WebTestClientResponse request(Method method) { + return when().request(method); + } + + @Override + public WebTestClientResponse request(String method) { + return when().request(method); + } + + @Override + public WebTestClientResponse request(Method method, String path, Object... pathParams) { + return when().request(method, path, pathParams); + } + + @Override + public WebTestClientResponse request(String method, String path, Object... pathParams) { + return when().request(method, path, pathParams); + } + + @Override + public WebTestClientResponse request(Method method, URI uri) { + return when().request(method, uri); + } + + @Override + public WebTestClientResponse request(Method method, URL url) { + return when().request(method, url); + } + + @Override + public WebTestClientResponse request(String method, URI uri) { + return when().request(method, uri); + } + + @Override + public WebTestClientResponse request(String method, URL url) { + return when().request(method, url); + } + + public String getBasePath() { + return basePath; + } + + public WebTestClientFactory getWebTestClientFactory() { + return webTestClientFactory; + } + + public Cookies getCookies() { + return cookies; + } + + public Headers getRequestHeaders() { + return requestHeaders; + } + + private void mergeConfig(WebTestClientRequestSpecificationImpl thisOne, WebTestClientRequestSpecificationImpl other) { + config((RestAssuredWebTestClientConfig) ConfigMergeUtils.mergeConfig(thisOne.getRestAssuredWebTestClientConfig(), + other.getRestAssuredWebTestClientConfig())); + } + + public Map getFormParams() { + return formParams; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getParams() { + return params; + } + + public Map getAttributes() { + return attributes; + } + + public List getMultiParts() { + return multiParts; + } + + public RequestLoggingFilter getRequestLoggingFilter() { + return requestLoggingFilter; + } + + public AsyncConfig getAsyncConfig() { + return asyncConfig; + } + + public RestAssuredWebTestClientConfig getRestAssuredWebTestClientConfig() { + return config; + } + + public LogRepository getLogRepository() { + return logRepository; + } + + public void setRequestLoggingFilter(RequestLoggingFilter requestLoggingFilter) { + this.requestLoggingFilter = requestLoggingFilter; + } + + public RestAssuredConfig getRestAssuredConfig() { + return ConfigConverter.convertToRestAssuredConfig(config); + } + + public WebTestClientRequestSpecification basePath(String path) { + notNull(path, "Base path"); + this.basePath = path; + return this; + } + + private String serializeIfNeeded(Object object) { + return Serializer.serializeIfNeeded(object, getRequestContentType(), config); + } + + private static WebTestClientParamConfig toWebTestClientParamConfig(ParamConfig paramConfig) { + if (!(paramConfig instanceof WebTestClientParamConfig)) { + throw new IllegalArgumentException("Wrong ParamConfig passed to method."); + } + return (WebTestClientParamConfig) paramConfig; + } + + private static ParamConfig.UpdateStrategy convert(WebTestClientParamConfig.UpdateStrategy updateStrategy) { + return ParamConfig.UpdateStrategy.valueOf(updateStrategy.name()); + } + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRestAssuredResponseImpl.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRestAssuredResponseImpl.java new file mode 100644 index 000000000..10b96c525 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WebTestClientRestAssuredResponseImpl.java @@ -0,0 +1,46 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.config.LogConfig; +import io.restassured.internal.RestAssuredResponseOptionsImpl; +import io.restassured.internal.log.LogRepository; +import io.restassured.module.webtestclient.response.ValidatableWebTestClientResponse; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import org.springframework.test.web.reactive.server.WebTestClient; + +public class WebTestClientRestAssuredResponseImpl extends RestAssuredResponseOptionsImpl implements WebTestClientResponse { + + private final WebTestClient.ResponseSpec responseSpec; + private final LogRepository logRepository; + + public WebTestClientRestAssuredResponseImpl(WebTestClient.ResponseSpec responseSpec, + LogRepository logRepository) { + this.responseSpec = responseSpec; + this.logRepository = logRepository; + } + + @Override + public ValidatableWebTestClientResponse then() { + ValidatableWebTestClientResponse response = new ValidatableWebTestClientResponseImpl( + responseSpec, getRpr(), getConfig(), this, this, logRepository); + LogConfig logConfig = getConfig().getLogConfig(); + if (logConfig.isLoggingOfRequestAndResponseIfValidationFailsEnabled()) { + response.log().ifValidationFails(logConfig.logDetailOfRequestAndResponseIfValidationFails(), logConfig.isPrettyPrintingEnabled()); + } + return response; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WrapperWebTestClientFactory.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WrapperWebTestClientFactory.java new file mode 100644 index 000000000..2803d0228 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/internal/WrapperWebTestClientFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.internal; + +import io.restassured.module.webtestclient.config.WebTestClientConfig; + +import org.springframework.test.web.reactive.server.WebTestClient; + +public class WrapperWebTestClientFactory implements WebTestClientFactory { + + private final WebTestClient webTestClient; + + public WrapperWebTestClientFactory(WebTestClient webTestClient) { + this.webTestClient = webTestClient; + } + + @Override + public synchronized WebTestClient build(WebTestClientConfig webTestClientConfig) { + if (!isAssigned()) { + throw new IllegalStateException("You haven't configured a MockMVC instance. You can do this statically\n\nRestAssuredMockMvc.mockMvc(..)\nRestAssuredMockMvc.standaloneSetup(..);\nRestAssuredMockMvc.webAppContextSetup(..);\n\nor using the DSL:\n\ngiven().\n\t\tmockMvc(..). ..\n"); + } + return webTestClient; + } + + @Override + public boolean isAssigned() { + return webTestClient != null; + } +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/matcher/RestAssuredWebTestClientMatchers.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/matcher/RestAssuredWebTestClientMatchers.java new file mode 100644 index 000000000..036844c40 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/matcher/RestAssuredWebTestClientMatchers.java @@ -0,0 +1,229 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.matcher; + +import io.restassured.internal.matcher.xml.XmlDtdMatcher; +import io.restassured.internal.matcher.xml.XmlXsdMatcher; +import io.restassured.matcher.ResponseAwareMatcher; +import io.restassured.matcher.RestAssuredMatchers; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import org.hamcrest.Matcher; + +import java.io.File; +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; + +/** + * Providers Hamcrest matchers that may be useful when validating a WebTestClient response. + */ +public class RestAssuredWebTestClientMatchers { + + /** + * Evaluates to true if an XML string matches the supplied XSD (Xml Schema). + * + * @param xsd The XSD to match + * @return The XSD matcher + */ + public static Matcher matchesXsd(String xsd) { + return RestAssuredMatchers.matchesXsd(xsd); + } + + /** + * Evaluates to true if an XML string matches the supplied XSD (Xml Schema). + * + * @param xsd The XSD to match + * @return The XSD matcher + */ + public static Matcher matchesXsd(InputStream xsd) { + return RestAssuredMatchers.matchesXsd(xsd); + } + + /** + * Evaluates to true if an XML string matches the supplied XSD (Xml Schema). + * + * @param xsd The XSD to match + * @return The XSD matcher + */ + public static Matcher matchesXsd(Reader xsd) { + return RestAssuredMatchers.matchesXsd(xsd); + } + + /** + * Evaluates to true if an XML string matches the supplied XSD (Xml Schema). + * + * @param xsd The XSD to match + * @return The XSD matcher + */ + public static Matcher matchesXsd(File xsd) { + return RestAssuredMatchers.matchesXsd(xsd); + } + + /** + * Evaluates to true if an XML file in classpath matches the supplied XSD. + * + * @param path The path to the XSD located in classpath + * @return The DTD matcher + */ + public static Matcher matchesXsdInClasspath(String path) { + return XmlXsdMatcher.matchesXsdInClasspath(path); + } + + /** + * Evaluates to true if an XML string matches the supplied DTD. + * + * @param dtd The DTD to match + * @return The DTD matcher + */ + public static Matcher matchesDtd(String dtd) { + return RestAssuredMatchers.matchesDtd(dtd); + } + + /** + * Evaluates to true if an XML string matches the supplied DTD. + * + * @param dtd The DTD to match + * @return The DTD matcher + */ + public static Matcher matchesDtd(InputStream dtd) { + return RestAssuredMatchers.matchesDtd(dtd); + } + + /** + * Evaluates to true if an XML string matches the supplied DTD. + * + * @param dtd The DTD to match + * @return The DTD matcher + */ + public static Matcher matchesDtd(File dtd) { + return RestAssuredMatchers.matchesDtd(dtd); + } + + /** + * Evaluates to true if an XML string matches the supplied DTD. + * + * @param url The DTD to match + * @return The DTD matcher + */ + public static Matcher matchesDtd(URL url) { + return RestAssuredMatchers.matchesDtd(url); + } + + /** + * Evaluates to true if an XML file in classpath matches the supplied DTD. + * + * @param path The path to the DTD file in classpath + * @return The DTD matcher + */ + public static Matcher matchesDtdInClasspath(String path) { + return XmlDtdMatcher.matchesDtdInClasspath(path); + } + + /** + * Creates a {@link ResponseAwareMatcher} that extracts the given path from the response and + * wraps it in a {@link org.hamcrest.Matchers#equalTo(Object)} matcher. + * This is useful if you have a resource that e.g. returns the given JSON: + *
+	 * {
+	 *      "userId" : "my-id",
+	 *      "playerId" : "my-id"
+	 * }
+	 * 
+ * you can then test it like this: + *
+	 * get("/x").then().body("userId", equalToPath("playerId"));
+	 * 
+ * + * @param path The path to check + * @return A {@link ResponseAwareMatcher} + */ + public static ResponseAwareMatcher equalToPath(final String path) { + return response -> equalTo(response.path(path)); + } + + /** + * Creates a {@link ResponseAwareMatcher} that extracts the given path from the response and + * wraps it in a {@link org.hamcrest.Matchers#equalTo(Object)} matcher. + * This is useful if you have a resource that e.g. returns the given JSON: + *
+	 * {
+	 *      "userId" : "my-id",
+	 *      "href" : "http://localhost:8080/my-id"
+	 * }
+	 * 
+ * you can then test it like this: + *
+	 * get("/x").then().body("href", endsWithPath("userId"));
+	 * 
+ * + * @param path The path to check + * @return A {@link ResponseAwareMatcher} + */ + public static ResponseAwareMatcher endsWithPath(final String path) { + return response -> endsWith(response.path(path)); + } + + /** + * Creates a {@link ResponseAwareMatcher} that extracts the given path from the response and + * wraps it in a {@link org.hamcrest.Matchers#equalTo(Object)} matcher. + * This is useful if you have a resource that e.g. returns the given JSON: + *
+	 * {
+	 *      "userId" : "my-id",
+	 *      "baseUri" : "http://localhost:8080",
+	 *      "href" : "http://localhost:8080/my-id"
+	 * }
+	 * 
+ * you can then test it like this: + *
+	 * get("/x").then().body("href", startsWithPath("baseUri"));
+	 * 
+ * + * @param path The path to check + * @return A {@link ResponseAwareMatcher} + */ + public static ResponseAwareMatcher startsWithPath(final String path) { + return response -> startsWith(response.path(path)); + } + + /** + * Creates a {@link ResponseAwareMatcher} that extracts the given path from the response and + * wraps it in a {@link org.hamcrest.Matchers#equalTo(Object)} matcher. + * This is useful if you have a resource that e.g. returns the given JSON: + *
+	 * {
+	 *      "userId" : "my-id",
+	 *      "href" : "http://localhost:8080/my-id"
+	 * }
+	 * 
+ * you can then test it like this: + *
+	 * get("/x").then().body("href", containsPath("userId"));
+	 * 
+ * + * @param path The path to check + * @return A {@link ResponseAwareMatcher} + */ + public static ResponseAwareMatcher containsPath(final String path) { + return response -> containsString(response.path(path)); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/ValidatableWebTestClientResponse.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/ValidatableWebTestClientResponse.java new file mode 100644 index 000000000..48a1defc7 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/ValidatableWebTestClientResponse.java @@ -0,0 +1,30 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.response; + +import io.restassured.response.ValidatableResponseOptions; +import org.springframework.test.web.reactive.server.WebTestClient; + +/** + * A validatable response of a request made by REST Assured WebTestClient. Returns an instance of + * {@link WebTestClient.ResponseSpec} so that user can make subsequent assertions using the + * {@link WebTestClient.ResponseSpec} API. + */ +public interface ValidatableWebTestClientResponse extends ValidatableResponseOptions { + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/WebTestClientResponse.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/WebTestClientResponse.java new file mode 100644 index 000000000..1dac3fb1c --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/response/WebTestClientResponse.java @@ -0,0 +1,26 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.response; + +import io.restassured.response.ResponseBody; +import io.restassured.response.ResponseOptions; +import io.restassured.response.Validatable; + +public interface WebTestClientResponse extends ResponseBody, + ResponseOptions, Validatable { + +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestLogSpecification.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestLogSpecification.java new file mode 100644 index 000000000..b009078e1 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestLogSpecification.java @@ -0,0 +1,35 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.specification; + +import io.restassured.specification.LogSpecification; + +public interface WebTestClientRequestLogSpecification extends LogSpecification { + + /** + * Logs only the parameters of the request. Same as {@link #parameters()} but slightly shorter syntax. + * + * @return The response specification + */ + WebTestClientRequestSpecification params(); + + /** + * Logs only the parameters of the request. Same as {@link #params()} but more explicit syntax. + * + * @return The response specification + */ + WebTestClientRequestSpecification parameters(); +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSender.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSender.java new file mode 100644 index 000000000..81b31de3b --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSender.java @@ -0,0 +1,147 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.specification; + +import io.restassured.http.Method; +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.specification.RequestSenderOptions; +import org.springframework.test.web.reactive.server.EntityExchangeResult; +import org.springframework.web.util.UriBuilder; + +import java.net.URI; +import java.util.function.Consumer; +import java.util.function.Function; + +/* +As the result of evaluating the {@link Function} will not be known while sending the request, path and +parameters information will not be logged for the methods that take uriFunctions and not path and parameters +as arguments. + */ +public interface WebTestClientRequestSender extends RequestSenderOptions { + + /** + * Perform a GET request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse get(Function uriFunction); + + /** + * Perform a POST request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse post(Function uriFunction); + + /** + * * Perform a PUT request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse put(Function uriFunction); + + /** + * * Perform a DELETE request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse delete(Function uriFunction); + + /** + * * Perform a PATCH request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse patch(Function uriFunction); + + /** + * * Perform a HEAD request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse head(Function uriFunction); + + /** + * * Perform a OPTIONS request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse options(Function uriFunction); + + /** + * * Perform a request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param method The HTTP method to use while sending the request expressed as {@link Method} + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse request(Method method, Function uriFunction); + + /** + * * Perform a request to a uri obtained from a {@link Function<>} that uses {@link UriBuilder} + * to generate {@link URI}. + * + * @param method The HTTP method to use while sending the request expressed as {@link String} + * @param uriFunction The function that will be used for evaluating the URI. + * @return The response of the request. + */ + WebTestClientResponse request(String method, Function uriFunction); + + /** + * Specify a {@link Consumer} to process the request result. The consumer will be applied before processing the result + * into a {@link WebTestClientResponse} and before extracting the response body content as byte array, which closes + * the stream. + * + * This is very useful, for example for extracting Spring Rest Docs. + * + * Usage example: + *

+ *

+	 *RestAssuredWebTestClient.given()
+	 * 				.standaloneSetup(new GreetingController(), documentationConfiguration(restDocumentation))
+	 * 				.queryParam("name", "John")
+	 * 				.when()
+	 * 				.consumeWith(document("greeting",
+	 * 						pathParameters(
+	 * 								parameterWithName("path").description("The path to greeting")),
+	 * 						responseFields(
+	 * 								fieldWithPath("id").description("The ID of the greeting"),
+	 * 								fieldWithPath("content").description("The content of the greeting"))
+	 * 				))
+	 * 				.get("/{path}", "greeting")
+	 * 
+ * + * @param consumer to be applied on the exchange result. + * @return a {@link WebTestClientRequestSender} instance. + */ + WebTestClientRequestSender consumeWith(Consumer> consumer); +} diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecBuilder.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecBuilder.java new file mode 100644 index 000000000..71bad67f5 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecBuilder.java @@ -0,0 +1,663 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.specification; + +import io.restassured.config.LogConfig; +import io.restassured.config.SessionConfig; +import io.restassured.filter.log.LogDetail; +import io.restassured.filter.log.RequestLoggingFilter; +import io.restassured.http.ContentType; +import io.restassured.http.Cookie; +import io.restassured.http.Header; +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperType; +import io.restassured.module.webtestclient.RestAssuredWebTestClient; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.internal.WebTestClientFactory; +import io.restassured.module.webtestclient.internal.WebTestClientRequestSpecificationImpl; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClientConfigurer; +import org.springframework.web.context.WebApplicationContext; + +import java.io.File; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Map; + +import static io.restassured.internal.assertion.AssertParameter.notNull; + +public class WebTestClientRequestSpecBuilder { + + private WebTestClientRequestSpecificationImpl spec; + + public WebTestClientRequestSpecBuilder() { + this.spec = new WebTestClientRequestSpecificationImpl(getConfiguredWebTestClientFactory(), RestAssuredWebTestClient.config, + RestAssuredWebTestClient.basePath, RestAssuredWebTestClient.requestSpecification, + RestAssuredWebTestClient.responseSpecification); + } + + private static WebTestClientFactory getConfiguredWebTestClientFactory() { + try { + Field WebTestClientFactory = RestAssuredWebTestClient.class.getDeclaredField("webTestClientFactory"); + WebTestClientFactory.setAccessible(true); + Object instance = WebTestClientFactory.get(RestAssuredWebTestClient.class); + WebTestClientFactory.setAccessible(false); + return (WebTestClientFactory) instance; + } catch (Exception e) { + throw new RuntimeException("Internal error: Cannot find WebTestClientFactory field in " + RestAssuredWebTestClient.class.getName()); + } + } + + /** + * Specify a String request body (such as e.g. JSON or XML) to be sent with the request. This works for the + * POST, PUT and PATCH methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * + * @param body The body to send. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder setBody(String body) { + spec.body(body); + return this; + } + + /** + * Specify a byte array request body to be sent with the request. This only works for the + * POST http method. Trying to do this for the other http methods will cause an exception to be thrown. + * + * @param body The body to send. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder setBody(byte[] body) { + spec.body(body); + return this; + } + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request. + * If the object is a primitive or Number the object will + * be converted to a String and put in the request body. This works for the POST, PUT and PATCH methods only. + * Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * + * @param object The object to serialize and send with the request + * @return The request specification + */ + public WebTestClientRequestSpecBuilder setBody(Object object) { + spec.body(object); + return this; + } + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request using a specific object mapper. + * This works for the POST, PATCH and PUT methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Note that {@link #setBody(Object, ObjectMapperType)} + * are the same except for the syntactic difference. + *

+ * + * @param object The object to serialize and send with the request + * @param mapper The object mapper + * @return The request specification + */ + public WebTestClientRequestSpecBuilder setBody(Object object, ObjectMapper mapper) { + spec.body(object, mapper); + return this; + } + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request using a specific object mapper type. + * This works for the POST, PATCH and PUT methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * Message message = new Message();
+	 * message.setMessage("My beautiful message");
+	 *
+	 * given().
+	 *         body(message, ObjectMapper.GSON).
+	 * expect().
+	 *         content(equalTo("Response to a beautiful message")).
+	 * when().
+	 *         post("/beautiful-message");
+	 * 
+ *

+ * Note that {@link #setBody(Object, ObjectMapper)} + * are the same except for the syntactic difference. + *

+ * + * @param object The object to serialize and send with the request + * @param mapperType The object mapper type to be used + * @return The request specification + */ + public WebTestClientRequestSpecBuilder setBody(Object object, ObjectMapperType mapperType) { + spec.body(object, mapperType); + return this; + } + + /** + * Add cookies to be sent with the request as Map e.g: + * + * @param cookies The Map containing the cookie names and their values to set in the request. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addCookies(Map cookies) { + spec.cookies(cookies); + return this; + } + + /** + * Add a detailed cookie + * + * @param cookie The cookie to add. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addCookie(Cookie cookie) { + spec.cookie(cookie); + return this; + } + + /** + * Add a cookie to be sent with the request. + * + * @param key The cookie key + * @param value The cookie value + * @param cookieNameValuePairs Additional cookies values. This will actually create two cookies with the same name but with different values. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addCookie(String key, Object value, Object... cookieNameValuePairs) { + spec.cookie(key, value, cookieNameValuePairs); + return this; + } + + /** + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addParams(Map parametersMap) { + spec.params(parametersMap); + return this; + } + + /** + * @param parameterValues Zero to many parameter values for this parameter name. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addParam(String parameterName, Object... parameterValues) { + spec.param(parameterName, parameterValues); + return this; + } + + /** + * @param parameterName The parameter key + * @param parameterValues The parameter values + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addParam(String parameterName, Collection parameterValues) { + spec.param(parameterName, parameterValues); + return this; + } + + /** + * @param parameterName The parameter key + * @param parameterValues The parameter values + * @return The request specification builder + * + * @see #addQueryParam(String, Object...) + */ + public WebTestClientRequestSpecBuilder addQueryParam(String parameterName, Collection parameterValues) { + spec.queryParam(parameterName, parameterValues); + return this; + } + + /** + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addQueryParams(Map parametersMap) { + spec.queryParams(parametersMap); + return this; + } + + /** + * @param parameterName The parameter key + * @param parameterValues Zero to many parameter values for this parameter name. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addQueryParam(String parameterName, Object... parameterValues) { + spec.queryParam(parameterName, parameterValues); + return this; + } + + /** + * @param parameterName The parameter key + * @param parameterValues The parameter values + * @return The request specification builder + * + * @see #addFormParam(String, Object...) + */ + public WebTestClientRequestSpecBuilder addFormParam(String parameterName, Collection parameterValues) { + spec.formParam(parameterName, parameterValues); + return this; + } + + /** + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addFormParams(Map parametersMap) { + spec.formParams(parametersMap); + return this; + } + + /** + * @param parameterName The parameter name + * @param parameterValues Zero to many parameter values for this parameter name. + * @return The request specification builder + * + * @see #addFormParam(String, Object...) + */ + public WebTestClientRequestSpecBuilder addFormParam(String parameterName, Object... parameterValues) { + spec.formParam(parameterName, parameterValues); + return this; + } + + /** + * Add request attribute + * + * @param attributeName The attribute name + * @param attributeValue The attribute value + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addAttribute(String attributeName, Object attributeValue) { + spec.attribute(attributeName, attributeValue); + return this; + } + + /** + * Add request attributes + * + * @param attributesMap The Map containing the request attribute names and their values + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addAttributes(Map attributesMap) { + spec.attributes(attributesMap); + return this; + } + + /** + * Add headers to be sent with the request as Map. + * + * @param headers The Map containing the header names and their values to send with the request. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addHeaders(Map headers) { + spec.headers(headers); + return this; + } + + /** + * Add a header to be sent with the request + * + * @param headerName The header name + * @param headerValue The header value + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addHeader(String headerName, String headerValue) { + spec.header(headerName, headerValue); + return this; + } + + /** + * Add a header to be sent with the request. + * + * @param header The header + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addHeader(Header header) { + spec.header(header); + return this; + } + + /** + * Specify the content type of the request. + * + * @param contentType The content type of the request + * @return The request specification builder + * + * @see ContentType + */ + public WebTestClientRequestSpecBuilder setContentType(ContentType contentType) { + spec.contentType(contentType); + return this; + } + + /** + * Specify the content type of the request as string. + * + * @param contentType The content type of the request + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder setContentType(String contentType) { + spec.contentType(contentType); + return this; + } + + /** + * Specify a file to upload to the server using multi-part form data uploading. + * It will assume that the control name is file and the content-type is application/octet-stream. + * If this is not what you want please use an overloaded method. + * + * @param file The file to upload + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(File file) { + spec.multiPart(file); + return this; + } + + /** + * Specify a file to upload to the server using multi-part form data uploading with a specific + * control name. It will use the content-type application/octet-stream. + * If this is not what you want please use an overloaded method. + * + * @param file The file to upload + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, File file) { + spec.multiPart(controlName, file); + return this; + } + + /** + * Specify a file to upload to the server using multi-part form data uploading with a specific + * control name and content-type. + * + * @param file The file to upload + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param mimeType The content-type + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, File file, String mimeType) { + spec.multiPart(controlName, file, mimeType); + return this; + } + + /** + * Specify a byte-array to upload to the server using multi-part form data. + * It will use the content-type application/octet-stream. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param bytes The bytes you want to send + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String fileName, byte[] bytes) { + spec.multiPart(controlName, fileName, bytes); + return this; + } + + /** + * Specify a byte-array to upload to the server using multi-part form data. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param bytes The bytes you want to send + * @param mimeType The content-type + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String fileName, byte[] bytes, String mimeType) { + spec.multiPart(controlName, fileName, bytes, mimeType); + return this; + } + + /** + * Specify an inputstream to upload to the server using multi-part form data. + * It will use the content-type application/octet-stream. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param stream The stream you want to send + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String fileName, InputStream stream) { + spec.multiPart(controlName, fileName, stream); + return this; + } + + /** + * Specify an inputstream to upload to the server using multi-part form data. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param stream The stream you want to send + * @param mimeType The content-type + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String fileName, InputStream stream, String mimeType) { + spec.multiPart(controlName, fileName, stream, mimeType); + return this; + } + + /** + * Specify a string to send to the server using multi-part form data. + * It will use the content-type text/plain. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param contentBody The string to send + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String contentBody) { + spec.multiPart(controlName, contentBody); + return this; + } + + /** + * Specify a string to send to the server using multi-part form data with a specific mime-type. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param contentBody The string to send + * @param mimeType The mime-type + * @return The request specification + */ + public WebTestClientRequestSpecBuilder addMultiPart(String controlName, String contentBody, String mimeType) { + spec.multiPart(controlName, mimeType); + return this; + } + + /** + * Set the session id for this request. It will use the configured session id name from the configuration (by default this is {@value SessionConfig#DEFAULT_SESSION_ID_NAME}). + * You can configure the session id name by using: + *
+	 *     RestAssuredWebTestClient.config = newConfig().sessionConfig(new SessionConfig().sessionIdName(<sessionIdName>));
+	 * 
+ * or you can use the {@link #setSessionId(String, String)} method to set it for this request only. + * + * @param sessionIdValue The session id value. + * @return The request specification + */ + public WebTestClientRequestSpecBuilder setSessionId(String sessionIdValue) { + spec.sessionId(sessionIdValue); + return this; + } + + /** + * Set the session id name and value for this request. It'll override the default session id name from the configuration (by default this is {@value SessionConfig#DEFAULT_SESSION_ID_NAME}). + * You can configure the default session id name by using: + *
+	 *     RestAssuredWebTestClient.config = newConfig().sessionConfig(new SessionConfig().sessionIdName(<sessionIdName>));
+	 * 
+ * and then you can use the {@link WebTestClientRequestSpecBuilder#setSessionId(String)} method to set the session id value without specifying the name for each request. + * + * @param sessionIdName The session id name + * @param sessionIdValue The session id value. + * @return The request specification + */ + public WebTestClientRequestSpecBuilder setSessionId(String sessionIdName, String sessionIdValue) { + spec.sessionId(sessionIdName, sessionIdValue); + return this; + } + + /** + * Merge this builder with settings from another specification. Note that the supplied specification + * can overwrite data in the current specification. The following settings are overwritten: + *
    + *
  • Content type
  • + *
  • Request body
  • + *
  • Interceptors
  • + *
  • Config (if defined)
  • + *
+ * The following settings are merged: + *
    + *
  • Parameters
  • + *
  • Cookies
  • + *
  • Headers
  • + *
+ * + * @param specification The specification to add + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder addWebTestClientRequestSpecification(WebTestClientRequestSpecification specification) { + this.spec.spec(specification); + return this; + } + + /** + * Define a configuration for redirection settings and http client parameters. + * + * @param config The configuration to use for this request. If null no config will be used. + * @return The request specification builder + */ + public WebTestClientRequestSpecBuilder setConfig(RestAssuredWebTestClientConfig config) { + spec.config(config); + return this; + } + + /** + * Build the request specification. + * + * @return The assembled request specification + */ + public WebTestClientRequestSpecification build() { + return spec; + } + + /** + * Set the basePath property of the WebTestClientRequestSpecBuilder instead of using static field RestAssuredWebTestClient.basePath. + *

+ *

+	 * WebTestClientRequestSpecBuilder builder = new WebTestClientRequestSpecBuilder();
+	 * builder.setBasePath("/something");
+	 * WebTestClientRequestSpecification specs = builder.build();
+	 * given().spec(specs)
+	 * 
+ * + * @param basePath + * @return WebTestClientRequestSpecBuilder + */ + public WebTestClientRequestSpecBuilder setBasePath(String basePath) { + spec.basePath(basePath); + return this; + } + + /** + * The webTestClient instance to use. + *

+ * Note that this will override the any {@link org.springframework.test.web.reactive.server.WebTestClient} instances configured by other setters.* + * + * @param webTestClient The WebTestClient instance + * @return WebTestClientRequestSpecBuilder + */ + public WebTestClientRequestSpecBuilder setWebTestClient(WebTestClient webTestClient) { + spec.webTestClient(webTestClient); + return this; + } + + /** + * The standalone setup to be used by supplying a set of controllers. + *

+ * Note that this will override the any {@link WebTestClient} instances configured by other setters. + * + * @param controllers The controllers to use + * @return WebTestClientRequestSpecBuilder + * + * @see WebTestClientRequestSpecification#standaloneSetup(Object...) + */ + public WebTestClientRequestSpecBuilder setStandaloneSetup(Object... controllers) { + spec.standaloneSetup(controllers); + return this; + } + + /** + * Initialize with a WebTestClientBuilder that will be used to create the {@link WebTestClient} instance. + *

+ * Note that this will override the any {@link WebTestClient} instances configured by other setters. + * + * @param builder The builder to use + * @return WebTestClientRequestSpecBuilder + * + * @see WebTestClientRequestSpecification#standaloneSetup(WebTestClient.Builder) + */ + public WebTestClientRequestSpecBuilder setStandaloneSetup(WebTestClient.Builder builder) { + spec.standaloneSetup(builder); + return this; + } + + /** + * Initialize with a {@link WebApplicationContext} that will be used to create the {@link WebTestClient} instance. + *

+ * Note that this will override the any {@link WebTestClient} instances configured by other setters. + * + * @param context The WebApplicationContext to use + * @param WebTestClientConfigurers {@link org.springframework.test.web.reactive.server.WebTestClientConfigurer}'s to be applied when creating a {@link WebTestClient} instance of this WebApplicationContext (optional) + * @return WebTestClientRequestSpecBuilder + * + * @see WebTestClientRequestSpecification#webAppContextSetup(WebApplicationContext, WebTestClientConfigurer...) + */ + public WebTestClientRequestSpecBuilder setWebAppContextSetup(WebApplicationContext context, WebTestClientConfigurer... WebTestClientConfigurers) { + spec.webAppContextSetup(context, WebTestClientConfigurers); + return this; + } + + /** + * Enabled logging with the specified log detail. Set a {@link LogConfig} to configure the print stream and pretty printing options. + * + * @param logDetail The log detail. + * @return WebTestClientRequestSpecBuilder + */ + public WebTestClientRequestSpecBuilder log(LogDetail logDetail) { + notNull(logDetail, LogDetail.class); + LogConfig logConfig = spec.getRestAssuredWebTestClientConfig().getLogConfig(); + PrintStream printStream = logConfig.defaultStream(); + boolean prettyPrintingEnabled = logConfig.isPrettyPrintingEnabled(); + boolean shouldUrlEncodeRequestUri = logConfig.shouldUrlEncodeRequestUri(); + spec.setRequestLoggingFilter(new RequestLoggingFilter(logDetail, prettyPrintingEnabled, printStream, shouldUrlEncodeRequestUri)); + return this; + } + + /** + * Returns the same WebTestClientRequestSpecBuilder instance for syntactic sugar. + * + * @return WebTestClientRequestSpecBuilder + */ + public WebTestClientRequestSpecBuilder and() { + return this; + } +} + diff --git a/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecification.java b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecification.java new file mode 100644 index 000000000..68b90d873 --- /dev/null +++ b/modules/spring-web-test-client/src/main/java/io/restassured/module/webtestclient/specification/WebTestClientRequestSpecification.java @@ -0,0 +1,929 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.specification; + +import io.restassured.config.SessionConfig; +import io.restassured.http.ContentType; +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperType; +import io.restassured.module.spring.commons.config.SpecificationConfig; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import org.springframework.context.ApplicationContext; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClientConfigurer; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.reactive.function.server.RouterFunction; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Map; + +public interface WebTestClientRequestSpecification extends WebTestClientRequestSender { + + /** + * Specify the content type of the request. + * + * @param contentType The content type of the request + * @return The request specification + * + * @see ContentType + */ + WebTestClientRequestSpecification contentType(ContentType contentType); + + /** + * Specify the content type of the request. + * + * @param contentType The content type of the request + * @return The request specification + * + * @see ContentType + */ + WebTestClientRequestSpecification contentType(String contentType); + + /** + * Specify the accept header of the request. This just a shortcut for: + *

+	 * header("Accept", contentType);
+	 * 
+ * + * @param contentType The content type whose accept header {@link ContentType#getAcceptHeader()} will be used as Accept header in the request. + * @return The request specification + * + * @see ContentType + * @see #header(String, Object, Object...) + */ + WebTestClientRequestSpecification accept(ContentType contentType); + + /** + * Specify the accept header of the request. This just a shortcut for: + *
+	 * header("Accept", contentType);
+	 * 
+ * + * @param mediaTypes The media type(s) that will be used as Accept header in the request. + * @return The request specification + * + * @see ContentType + * @see #header(String, Object, Object...) + */ + WebTestClientRequestSpecification accept(String mediaTypes); + + /** + * Specify the headers that'll be sent with the request. This is done by specifying the headers in name-value pairs, e.g: + *
+	 * given().headers("headerName1", "headerValue1", "headerName2", "headerValue2").then().expect().body(equalTo("something")).when().get("/headers");
+	 * 
+ *

+ * This will send a GET request to "/headers" with two headers: + *

    + *
  1. headerName1=headerValue1
  2. + *
  3. headerName2=headerValue2
  4. + *
+ * and expect that the response body is equal to "something". + * + * @param firstHeaderName The name of the first header + * @param firstHeaderValue The value of the first header + * @param headerNameValuePairs Additional headers in name-value pairs. + * @return The request specification + */ + WebTestClientRequestSpecification headers(String firstHeaderName, Object firstHeaderValue, Object... headerNameValuePairs); + + /** + * Specify the headers that'll be sent with the request as Map e.g: + *
+	 * Map<String, String> headers = new HashMap<String, String>();
+	 * parameters.put("headerName1", "headerValue1");
+	 * parameters.put("headerName2", "headerValue2");
+	 * given().headers(headers).then().expect().body(equalTo("something")).when().get("/headers");
+	 * 
+ *

+ * This will send a GET request to "/headers" with two headers: + *

    + *
  1. headerName1=headerValue1
  2. + *
  3. headerName2=headerValue2
  4. + *
+ * and expect that the response body is equal to "something". + * + * @param headers The Map containing the header names and their values to send with the request. + * @return The request specification + */ + WebTestClientRequestSpecification headers(Map headers); + + /** + * Specify the headers that'll be sent with the request as {@link Headers}, e.g: + *
+	 * Header first = new Header("headerName1", "headerValue1");
+	 * Header second = new Header("headerName2", "headerValue2");
+	 * Headers headers = new Header(first, second);
+	 * given().headers(headers).then().expect().body(equalTo("something")).when().get("/headers");
+	 * 
+ *

+ * This will send a GET request to "/headers" with two headers: + *

    + *
  1. headerName1=headerValue1
  2. + *
  3. headerName2=headerValue2
  4. + *
+ * and expect that the response body is equal to "something". + * + * @param headers The headers to use in the request + * @return The request specification + */ + WebTestClientRequestSpecification headers(Headers headers); + + /** + * Specify a header that'll be sent with the request e.g: + *

+ *

+	 * given().header("username", "John").and().expect().body(equalTo("something")).when().get("/header");
+	 * 
+ * This will set the header username=John in the GET request to "/header". + *

+ *

+ *

+ * You can also specify several headers like this: + *

+	 * given().header("username", "John").and().header("zipCode", "12345").and().expect().body(equalTo("something")).when().get("/header");
+	 * 
+ *

+ *

+ * If you specify additionalHeaderValues then the Header will be a multi-value header. This means that you'll create several headers with the + * same name but with different values. + * + * @param headerName The header name + * @param headerValue The header value + * @param additionalHeaderValues Additional header values. This will actually create two headers with the same name but with different values. + * @return The request specification + * + * @see #headers(String, Object, Object...) + */ + WebTestClientRequestSpecification header(String headerName, Object headerValue, Object... additionalHeaderValues); + + /** + * Specify a {@link Header} to send with the request. + *

+ *

+	 * Header someHeader = new Header("some_name", "some_value");
+	 * given().header(someHeader).and().expect().body(equalTo("x")).when().get("/header");
+	 * 
+ * This will set the header some_name=some_value in the GET request to "/header". + *

+ * + * @param header The header to add to the request + * @return The request specification + * + * @see #headers(Headers) + */ + WebTestClientRequestSpecification header(Header header); + + /** + * Returns the {@link WebTestClientRequestLogSpecification} that allows you to log different parts of the {@link WebTestClientRequestSpecification}. + * This is mainly useful for debug purposes when writing your tests. + * + * @return the request log specification + */ + WebTestClientRequestLogSpecification log(); + + /** + * Specify the parameters that'll be sent with the request. This is done by specifying the parameters in name-value pairs, e.g: + *
+	 * given().params("username", "John", "token", "1234").when().get("/parameters").then().assertThat().body(equalTo("username, token"));
+	 * 
+ *

+ * This will send a GET request to "/parameters" with two parameters: + *

    + *
  1. username=John
  2. + *
  3. token=1234
  4. + *
+ * and expect that the response body is equal to "username, token". + * + * @param firstParameterName The name of the first parameter + * @param firstParameterValue The value of the first parameter + * @param parameterNameValuePairs Additional parameters in name-value pairs. + * @return The request specification + */ + WebTestClientRequestSpecification params(String firstParameterName, Object firstParameterValue, Object... parameterNameValuePairs); + + /** + * Specify the parameters that'll be sent with the request as Map e.g: + *
+	 * Map<String, String> parameters = new HashMap<String, String>();
+	 * parameters.put("username", "John");
+	 * parameters.put("token", "1234");
+	 * given().params(parameters).when().get("/cookie").then().assertThat().body(equalTo("username, token")).;
+	 * 
+ *

+ * This will send a GET request to "/cookie" with two parameters: + *

    + *
  1. username=John
  2. + *
  3. token=1234
  4. + *
+ * and expect that the response body is equal to "username, token". + * + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification + */ + WebTestClientRequestSpecification params(Map parametersMap); + + /** + * Specify a parameter that'll be sent with the request e.g: + *

+ *

+	 * given().parameter("username", "John").and().expect().body(equalTo("username")).when().get("/cookie");
+	 * 
+ * This will set the parameter username=John in the GET request to "/cookie". + *

+ *

+ *

+ * You can also specify several parameters like this: + *

+	 * given().param("username", "John").and().param("password", "1234").when().get("/cookie").then().assertThat().body(equalTo("username")).;
+	 * 
+ *

+ * + * @param parameterName The parameter name + * @param parameterValues Zero to many parameter values for this parameter name + * @return The request specification + * + * @see #params(String, Object, Object...) + */ + WebTestClientRequestSpecification param(String parameterName, Object... parameterValues); + + /** + * Specify a multi-value parameter that'll be sent with the request e.g: + *

+ *

+	 * given().param("cars", asList("Volvo", "Saab"))..;
+	 * 
+ * This will set the parameter cars=Volvo and cars=Saab. + *

+ * + * @param parameterName The parameter name + * @param parameterValues The parameter values + * @return The request specification + */ + WebTestClientRequestSpecification param(String parameterName, Collection parameterValues); + + /** + * Specify the query parameters that'll be sent with the request. Note that this method is the same as {@link #params(String, Object, Object...)} + * for all http methods except for POST where {@link #params(String, Object, Object...)} sets the form parameters and this method sets the + * query parameters. + * + * @param firstParameterName The name of the first parameter + * @param firstParameterValue The value of the first parameter + * @param parameterNameValuePairs The value of the first parameter followed by additional parameters in name-value pairs. + * @return The request specification + */ + WebTestClientRequestSpecification queryParams(String firstParameterName, Object firstParameterValue, Object... parameterNameValuePairs); + + /** + * Specify the query parameters that'll be sent with the request. Note that this method is the same as {@link #params(Map)} + * for all http methods except for POST where {@link #params(Map)} sets the form parameters and this method sets the + * query parameters. + * + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification + */ + WebTestClientRequestSpecification queryParams(Map parametersMap); + + /** + * Specify a query parameter that'll be sent with the request. Note that this method is the same as {@link #param(String, Object...)} + * for all http methods except for POST where {@link #param(String, Object...)} adds a form parameter and this method sets a + * query parameter. + * + * @param parameterName The parameter name + * @param parameterValues Zero to many parameter values, i.e. you can specify multiple values for the same parameter + * @return The request specification + * + * @see #param(String, Object...) + */ + WebTestClientRequestSpecification queryParam(String parameterName, Object... parameterValues); + + /** + * Specify a multi-value query parameter that'll be sent with the request e.g: + *

+ *

+	 * given().queryParam("cars", asList("Volvo", "Saab"))..;
+	 * 
+ * This will set the parameter cars=Volvo and cars=Saab. + *

+ *

+ * Note that this method is the same as {@link #param(String, java.util.Collection)} + * for all http methods except for POST where {@link #param(String, java.util.Collection)} adds a form parameter and + * this method sets a query parameter. + * + * @param parameterName The parameter name + * @param parameterValues The parameter values + * @return The request specification + */ + WebTestClientRequestSpecification queryParam(String parameterName, Collection parameterValues); + + /** + * Specify the form parameters that'll be sent with the request. Note that this method is the same as {@link #params(String, Object, Object...)} + * for all http methods except for POST where {@link #params(String, Object, Object...)} sets the form parameters and this method sets the + * form parameters. + * + * @param firstParameterName The name of the first parameter + * @param firstParameterValue The value of the first parameter + * @param parameterNameValuePairs The value of the first parameter followed by additional parameters in name-value pairs. + * @return The request specification + */ + WebTestClientRequestSpecification formParams(String firstParameterName, Object firstParameterValue, Object... parameterNameValuePairs); + + /** + * Specify the form parameters that'll be sent with the request. Note that this method is the same as {@link #params(Map)} + * for all http methods except for POST where {@link #params(Map)} sets the form parameters and this method sets the + * form parameters. + * + * @param parametersMap The Map containing the parameter names and their values to send with the request. + * @return The request specification + */ + WebTestClientRequestSpecification formParams(Map parametersMap); + + /** + * Specify a form parameter that'll be sent with the request. Note that this method is the same as {@link #param(String, Object...)} + * for all http methods except for POST where {@link #param(String, Object...)} adds a form parameter and this method sets a + * form parameter. + * + * @param parameterName The parameter name + * @param parameterValues Zero to many parameter values, i.e. you can specify multiple values for the same parameter + * @return The request specification + * + * @see #param(String, Object...) + */ + WebTestClientRequestSpecification formParam(String parameterName, Object... parameterValues); + + /** + * Specify a multi-value form parameter that'll be sent with the request e.g: + *

+ *

+	 * given().formParam("cars", asList("Volvo", "Saab"))..;
+	 * 
+ * This will set the parameter cars=Volvo and cars=Saab. + *

+ *

+ * Note that this method is the same as {@link #param(String, java.util.Collection)} + * for all http methods except for POST where {@link #param(String, java.util.Collection)} adds a form parameter and + * this method sets a form parameter. + * + * @param parameterName The parameter name + * @param parameterValues The parameter values + * @return The request specification + */ + WebTestClientRequestSpecification formParam(String parameterName, Collection parameterValues); + + /** + * Specify a single-value request attribute + * + * @param attributeName The attribute name + * @param attributeValue The attribute value + * @return The request specification + */ + WebTestClientRequestSpecification attribute(String attributeName, Object attributeValue); + + /** + * Specify request attributes as a map + * + * @param attributesMap The Map containing the request attribute names and their values + * @return The request specification + */ + WebTestClientRequestSpecification attributes(Map attributesMap); + + /** + * Specify a String request body (such as e.g. JSON or XML) that'll be sent with the request. This works for the + * POST and PUT methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * given().body("{ \"message\" : \"hello world\"}").then().expect().body(equalTo("hello world")).when().post("/json");
+	 * 
+ * This will POST a request containing JSON to "/json" and expect that the response body equals to "hello world". + *

+ *

+ * + * @param body The body to send. + * @return The request specification + */ + WebTestClientRequestSpecification body(String body); + + /** + * Specify a byte array request body that'll be sent with the request. This only works for the + * POST http method. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * byte[] someBytes = ..
+	 * given().body(someBytes).then().expect().body(equalTo("hello world")).when().post("/json");
+	 * 
+ * This will POST a request containing someBytes to "/json" and expect that the response body equals to "hello world". + *

+ *

+ * + * @param body The body to send. + * @return The request specification + */ + WebTestClientRequestSpecification body(byte[] body); + + /** + * Specify file content that'll be sent with the request. This only works for the + * POST, PATCH and PUT http method. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * File myFile = ..
+	 * given().content(myFile).when().post("/json").then().content(equalTo("hello world"));
+	 * 
+ * This will POST a request containing myFile to "/json" and expect that the response content equals to "hello world". + *

+ *

+ * + * @param body The content to send. + * @return The request specification + */ + WebTestClientRequestSpecification body(File body); + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request. + * If the object is a primitive or Number the object will + * be converted to a String and put in the request body. This works for the POST and PUT methods only. + * Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * Message message = new Message();
+	 * message.setMessage("My beautiful message");
+	 *
+	 * given().
+	 *         contentType("application/json").
+	 *         body(message).
+	 * expect().
+	 *         content(equalTo("Response to a beautiful message")).
+	 * when().
+	 *         post("/beautiful-message");
+	 * 
+ *

+ * Since the content-type is "application/json" then REST Assured will automatically try to serialize the object using + * Jackson or Gson if they are + * available in the classpath. If any of these frameworks are not in the classpath then an exception is thrown. + *
+ * If the content-type is "application/xml" then REST Assured will automatically try to serialize the object using JAXB + * if it's available in the classpath. Otherwise an exception will be thrown. + *
+ * If no request content-type is specified then REST Assured determine the parser in the following order: + *
    + *
  1. Jackson
  2. + *
  3. Gson
  4. + *
  5. JAXB
  6. + *
+ * + * @param object The object to serialize and send with the request + * @return The request specification + */ + WebTestClientRequestSpecification body(Object object); + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request using a specific object mapper. + * This works for the POST, PATCH and PUT methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * Message message = new Message();
+	 * message.setMessage("My beautiful message");
+	 *
+	 * given().
+	 *         body(message, new MyObjectMapper()).
+	 * expect().
+	 *         content(equalTo("Response to a beautiful message")).
+	 * when().
+	 *         post("/beautiful-message");
+	 * 
+ * + * @param object The object to serialize and send with the request + * @param mapper The object mapper + * @return The request specification + */ + WebTestClientRequestSpecification body(Object object, ObjectMapper mapper); + + /** + * Specify an Object request content that will automatically be serialized to JSON or XML and sent with the request using a specific object mapper type. + * This works for the POST, PATCH and PUT methods only. Trying to do this for the other http methods will cause an exception to be thrown. + *

+ * Example of use: + *

+	 * Message message = new Message();
+	 * message.setMessage("My beautiful message");
+	 *
+	 * given().
+	 *         body(message, ObjectMapper.GSON).
+	 * expect().
+	 *         content(equalTo("Response to a beautiful message")).
+	 * when().
+	 *         post("/beautiful-message");
+	 * 
+ * + * @param object The object to serialize and send with the request + * @param mapperType The object mapper type to be used + * @return The request specification + */ + WebTestClientRequestSpecification body(Object object, ObjectMapperType mapperType); + + /** + * Specify the cookies that'll be sent with the request. This is done by specifying the cookies in name-value pairs, e.g: + *
+	 * given().cookies("username", "John", "token", "1234").then().expect().body(equalTo("username, token")).when().get("/cookie");
+	 * 
+ *

+ * This will send a GET request to "/cookie" with two cookies: + *

    + *
  1. username=John
  2. + *
  3. token=1234
  4. + *
+ * and expect that the response body is equal to "username, token". + * + * @param firstCookieName The name of the first cookie + * @param firstCookieValue The value of the first cookie + * @param cookieNameValuePairs Additional cookies in name-value pairs. + * @return The request specification + */ + WebTestClientRequestSpecification cookies(String firstCookieName, Object firstCookieValue, Object... cookieNameValuePairs); + + /** + * Specify the cookies that'll be sent with the request as Map e.g: + *
+	 * Map<String, String> cookies = new HashMap<String, String>();
+	 * cookies.put("username", "John");
+	 * cookies.put("token", "1234");
+	 * given().cookies(cookies).then().expect().body(equalTo("username, token")).when().get("/cookie");
+	 * 
+ *

+ * This will send a GET request to "/cookie" with two cookies: + *

    + *
  1. username=John
  2. + *
  3. token=1234
  4. + *
+ * and expect that the response body is equal to "username, token". + * + * @param cookies The Map containing the cookie names and their values to set in the request. + * @return The request specification + */ + WebTestClientRequestSpecification cookies(Map cookies); + + /** + * Specify the cookies that'll be sent with the request as {@link Cookies}: + *
+	 * Cookie cookie1 = Cookie.Builder("username", "John").setComment("comment 1").build();
+	 * Cookie cookie2 = Cookie.Builder("token", 1234).setComment("comment 2").build();
+	 * Cookies cookies = new Cookies(cookie1, cookie2);
+	 * given().cookies(cookies).then().expect().body(equalTo("username, token")).when().get("/cookie");
+	 * 
+ *

+ * This will send a GET request to "/cookie" with two cookies: + *

    + *
  1. username=John
  2. + *
  3. token=1234
  4. + *
+ * and expect that the response body is equal to "username, token". + * + * @param cookies The cookies to set in the request. + * @return The request specification + */ + WebTestClientRequestSpecification cookies(Cookies cookies); + + /** + * Specify a cookie that'll be sent with the request e.g: + *

+ *

+	 * given().cookie("username", "John").and().expect().body(equalTo("username")).when().get("/cookie");
+	 * 
+ * This will set the cookie username=John in the GET request to "/cookie". + *

+ *

+ *

+ * You can also specify several cookies like this: + *

+	 * given().cookie("username", "John").and().cookie("password", "1234").and().expect().body(equalTo("username")).when().get("/cookie");
+	 * 
+ *

+ *

+ * If you specify additionalValues then the Cookie will be a multi-value cookie. This means that you'll create several cookies with the + * same name but with different values. + * + * @param cookieName The cookie cookieName + * @param value The cookie value + * @param additionalValues Additional cookies values. This will actually create two cookies with the same name but with different values. + * @return The request specification + * + * @see #cookies(String, Object, Object...) + */ + WebTestClientRequestSpecification cookie(String cookieName, Object value, Object... additionalValues); + + /** + * Specify a {@link Cookie} to send with the request. + *

+ *

+	 * Cookie someCookie = new Cookie.Builder("some_cookie", "some_value").setSecured(true).build();
+	 * given().cookie(someCookie).and().expect().body(equalTo("x")).when().get("/cookie");
+	 * 
+ * This will set the cookie someCookie in the GET request to "/cookie". + *

+ * + * @param cookie The cookie to add to the request + * @return The request specification + * + * @see #cookies(Cookies) + */ + WebTestClientRequestSpecification cookie(Cookie cookie); + + /** + * Specify a file to upload to the server using multi-part form data uploading. + * It will assume that the control name is file and the mime-type is application/octet-stream. + * If this is not what you want please use an overloaded method. + * + * @param file The file to upload + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(File file); + + /** + * Specify a file to upload to the server using multi-part form data uploading with a specific + * control name. It will use the mime-type application/octet-stream. + * If this is not what you want please use an overloaded method. + * + * @param file The file to upload + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, File file); + + /** + * Specify a file to upload to the server using multi-part form data uploading with a specific + * control name and mime-type. + * + * @param file The file to upload + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, File file, String mimeType); + + /** + * Specify an object that will be serialized to JSON and uploaded to the server using multi-part form data + * uploading with a specific control name. It will use mime-type application/json. + * If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param object The object to serialize to JSON or XML and send to the server + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, Object object); + + /** + * Specify an object that will be serialized and uploaded to the server using multi-part form data + * uploading with a specific control name. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param object The object to serialize to JSON or XML and send to the server + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, Object object, String mimeType); + + /** + * Specify an object that will be serialized and uploaded to the server using multi-part form data + * uploading with a specific control name. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param filename The name of the content you're uploading + * @param object The object to serialize to JSON or XML and send to the server + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String filename, Object object, String mimeType); + + /** + * Specify a byte-array to upload to the server using multi-part form data. + * It will use the mime-type application/octet-stream. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param bytes The bytes you want to send + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String fileName, byte[] bytes); + + /** + * Specify a byte-array to upload to the server using multi-part form data. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param bytes The bytes you want to send + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String fileName, byte[] bytes, String mimeType); + + /** + * Specify an inputstream to upload to the server using multi-part form data. + * It will use the mime-type application/octet-stream. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param stream The stream you want to send + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String fileName, InputStream stream); + + /** + * Specify an inputstream to upload to the server using multi-part form data. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param fileName The name of the content you're uploading + * @param stream The stream you want to send + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String fileName, InputStream stream, String mimeType); + + /** + * Specify a string to send to the server using multi-part form data. + * It will use the mime-type text/plain. If this is not what you want please use an overloaded method. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param contentBody The string to send + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String contentBody); + + /** + * Specify a string to send to the server using multi-part form data with a specific mime-type. + * + * @param controlName Defines the control name of the body part. In HTML this is the attribute name of the input tag. + * @param contentBody The string to send + * @param mimeType The mime-type + * @return The request specification + */ + WebTestClientRequestSpecification multiPart(String controlName, String contentBody, String mimeType); + + /** + * Define a REST Assured WebTestClient configuration. E.g. + *
+	 * given().config(newConfig().logConfig(new LogConfig(captor, true))). ..
+	 * 
+ *

+ * newConfig() can be statically imported from {@link RestAssuredWebTestClientConfig}. + * + * @param config The configuration to use for this request. If null no config will be used. + * @return The request specification + */ + WebTestClientRequestSpecification config(RestAssuredWebTestClientConfig config); + + WebTestClientRequestSpecification config(SpecificationConfig config); + + /** + * Add request data from a pre-defined specification. E.g. + *

+	 * WebTestClientRequestSpecification requestSpec = new WebTestClientRequestSpecBuilder().addParam("parameter1", "value1").build();
+	 *
+	 * given().
+	 *         spec(requestSpec).
+	 *         param("parameter2", "value2").
+	 * when().
+	 *        get("/something");
+	 * 
+ *

+ * This is useful when you want to reuse an entire specification across multiple requests. + *

+ * The specification passed to this method is merged with the current specification. Note that the supplied specification + * can overwrite data in the current specification. The following settings are overwritten: + *

    + *
  • Content type
  • + *
  • Request body
  • + *
  • Interceptions
  • + *
  • Log (if defined in requestSpecificationToMerge)
  • + *
  • Config
  • + *
+ * The following settings are merged: + *
    + *
  • Parameters
  • + *
  • Attributes
  • + *
  • Cookies
  • + *
  • Headers
  • + *
+ *

+ * + * @param requestSpecificationToMerge The specification to merge with. + * @return the request specification + */ + WebTestClientRequestSpecification spec(WebTestClientRequestSpecification requestSpecificationToMerge); + + /** + * Set the session id for this request. It will use the configured session id name from the configuration (by default this is {@value SessionConfig#DEFAULT_SESSION_ID_NAME}). + * You can configure the session id name by using: + *

+	 *     RestAssured.config = newConfig().sessionConfig(new SessionConfig().sessionIdName(<sessionIdName>));
+	 * 
+ * or you can use the {@link #sessionId(String, String)} method to set it for this request only. + * + * @param sessionIdValue The session id value. + * @return The request specification + */ + WebTestClientRequestSpecification sessionId(String sessionIdValue); + + /** + * Set the session id name and value for this request. It'll override the default session id name from the configuration (by default this is {@value SessionConfig#DEFAULT_SESSION_ID_NAME}). + * You can configure the default session id name by using: + *
+	 *     RestAssured.config = newConfig().sessionConfig(new SessionConfig().sessionIdName(<sessionIdName>));
+	 * 
+ * and then you can use the {@link #sessionId(String)} method to set the session id value without specifying the name for each request. + * + * @param sessionIdName The session id name + * @param sessionIdValue The session id value. + * @return The request specification + */ + WebTestClientRequestSpecification sessionId(String sessionIdName, String sessionIdValue); + + /** + * Call this method when you're done setting up the request specification. + * + * @return The {@link WebTestClientRequestSender} that let's you send the request. + */ + WebTestClientRequestSender when(); + + /** + * Build a {@link WebTestClient} by registering one or more {@code @Controller}'s + * instances and configuring Spring infrastructure programmatically. + * This allows full control over the instantiation and initialization of + * controllerOrWebTestClientConfigurer, and their dependencies, similar to plain unit tests while + * also making it possible to test one controller at a time. + *

+ *

This uses the {@link WebTestClient#bindToController(Object...)} method under the hood. + *

+ * + * @param controllerOrWebTestClientConfigurer one or more {@link org.springframework.stereotype.Controller @Controller}'s to test + * or a combination of controllers and {@link WebTestClientConfigurer} + */ + WebTestClientRequestSpecification standaloneSetup(Object... controllerOrWebTestClientConfigurer); + + /** + * Build a {@link WebTestClient} by using a provided {@code AbstractWebTestClientBuilder} + * for configuring Spring infrastructure programmatically. + * This allows full control over the instantiation and initialization of + * controllers, and their dependencies, similar to plain unit tests while + * also making it possible to test one controller at a time. + *

+ *

This uses the {@link WebTestClient.Builder} to set up the WebTestClient instance. + * + * @param builder {@link WebTestClient.Builder} to build the WebTestClient instance. + */ + WebTestClientRequestSpecification standaloneSetup(WebTestClient.Builder builder); + + WebTestClientRequestSpecification standaloneSetup(RouterFunction routerFunction, WebTestClientConfigurer... configurers); + + /** + * Provide a {@link org.springframework.test.web.reactive.server.WebTestClient} instance to that REST Assured will use when making this request. + * + * @param webTestClient WebTestClient instance to use. + * @return The request specification + */ + WebTestClientRequestSpecification webTestClient(WebTestClient webTestClient); + + /** + * Build a {@link WebTestClient} using the given, fully initialized, i.e. + * refreshed, {@link WebApplicationContext} and assign it to REST Assured. + * + * This method has been kept for consistency, but, actually, it is only be used as {@link ApplicationContext}. + * The effect of calling this method is same as for {@link WebTestClientRequestSpecification#applicationContextSetup(ApplicationContext, WebTestClientConfigurer...)} + * + * @param context The web application context to use + * @param configurers {@link WebTestClientConfigurer}'s to be applied when creating a {@link WebTestClient} instance of this WebApplicationContext (optional) + */ + WebTestClientRequestSpecification webAppContextSetup(WebApplicationContext context, WebTestClientConfigurer... configurers); + + WebTestClientRequestSpecification applicationContextSetup(ApplicationContext context, WebTestClientConfigurer... configurers); + + /** + * Syntactic sugar + * + * @return The same {@link WebTestClientRequestSpecification} instance. + */ + WebTestClientRequestSpecification and(); +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/BasePathTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/BasePathTest.java new file mode 100644 index 000000000..b127e3d94 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/BasePathTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.BasePathController; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.given; +import static org.hamcrest.Matchers.equalTo; + +public class BasePathTest { + + @Before + public void + given_rest_assured_is_initialized_with_controller() { + RestAssuredWebTestClient.standaloneSetup(new BasePathController()); + } + + @After + public void + rest_assured_is_reset_after_each_test() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + base_path_is_prepended_to_path() { + RestAssuredWebTestClient.basePath = "/my-path"; + + given() + .param("name", "Johan") + .when() + .get("/greetingPath") + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + default_base_path_is_slash() { + given() + .param("name", "Johan") + .when() + .get() + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + double_slashes_are_prevented() { + RestAssuredWebTestClient.basePath = "/my-path/"; + + given() + .param("name", "Johan") + .when() + .get("/greetingPath") + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + base_path_can_end_with_slash_and_path_doesnt_have_to_begin_with_slash() { + RestAssuredWebTestClient.basePath = "/my-path/"; + + given(). + param("name", "Johan") + .when() + .get("greetingPath") + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + base_path_doesnt_have_to_end_with_slash_even_though_path_doesnt_begin_with_slash2() { + RestAssuredWebTestClient.basePath = "/my-path"; + + given() + .param("name", "Johan") + .when() + .get("greetingPath") + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ContentTypeTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ContentTypeTest.java new file mode 100644 index 000000000..057daef87 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ContentTypeTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.config.EncoderConfig; +import io.restassured.http.ContentType; +import io.restassured.module.webtestclient.setup.ContentTypeProcessor; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static java.nio.charset.StandardCharsets.UTF_16; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; + +public class ContentTypeTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RouterFunction setAttributesRoute = route(path("/contentType") + .and(method(GET)), new ContentTypeProcessor()::processContentType); + RestAssuredWebTestClient.standaloneSetup(setAttributesRoute); + } + + @Test + public void + adds_default_charset_to_content_type_by_default() { + RestAssuredWebTestClient.given() + .contentType(ContentType.JSON) + .when() + .get("/contentType") + .then() + .body("requestContentType", equalTo("application/json;charset=" + + RestAssuredWebTestClient.config().getEncoderConfig().defaultContentCharset())); + } + + @Test + public void + adds_specific_charset_to_content_type_by_default() { + RestAssuredWebTestClient.given() + .config(RestAssuredWebTestClient.config().encoderConfig(EncoderConfig.encoderConfig() + .defaultCharsetForContentType(UTF_16.toString(), ContentType.JSON))) + .contentType(ContentType.JSON) + .when() + .get("/contentType") + .then() + .statusCode(200) + .body("requestContentType", equalTo("application/json;charset=" + UTF_16.toString())) + .body("requestContentType", not(contains(RestAssuredWebTestClient.config().getEncoderConfig() + .defaultContentCharset()))); + } + + @Test + public void + doesnt_add_default_charset_to_content_type_if_charset_is_defined_explicitly() { + RestAssuredWebTestClient.given() + .contentType(ContentType.JSON.withCharset("UTF-16")) + .when() + .get("/contentType") + .then() + .statusCode(200) + .body("requestContentType", equalTo("application/json;charset=UTF-16")); + } + + @Test + public void + doesnt_add_default_charset_to_content_type_if_configured_not_to_do_so() { + RestAssuredWebTestClient.given() + .config(RestAssuredWebTestClient.config() + .encoderConfig(EncoderConfig.encoderConfig() + .appendDefaultContentCharsetToContentTypeIfUndefined(false))) + .contentType(ContentType.JSON) + .when() + .get("/contentType") + .then() + .statusCode(200) + .body("requestContentType", equalTo("application/json")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ExtractTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ExtractTest.java new file mode 100644 index 000000000..6f9a2aa6c --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ExtractTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.response.WebTestClientResponse; +import io.restassured.module.webtestclient.setup.GreetingController; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class ExtractTest { + + @Test + public void + can_extract_rest_assured_web_test_client_response() { + WebTestClientResponse response = RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .param("name", "Johan") + .when() + .get("/greeting") + .then() + .statusCode(200) + .body("id", equalTo(1)) + .extract() + .response(); + + assertThat((String) response.path("content")).isEqualTo("Hello, Johan!"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetCookiesTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetCookiesTest.java new file mode 100644 index 000000000..707d95190 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetCookiesTest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.http.Cookie; +import io.restassured.http.Cookies; +import io.restassured.module.webtestclient.setup.CookieController; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; + +public class GetCookiesTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RestAssuredWebTestClient.standaloneSetup(new CookieController()); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test public void + can_send_cookie_using_cookie_class() { + RestAssuredWebTestClient.given() + .cookie(new Cookie.Builder("cookieName1", "John Doe").build()) + .when() + .get("/cookie") + .then() + .statusCode(200) + .body("cookieValue1", equalTo("John Doe")); + } + + @Test public void + can_send_cookie_using_cookie_name_and_value() { + RestAssuredWebTestClient.given() + .cookie("cookieName1", "John Doe") + .when() + .get("/cookie") + .then() + .statusCode(200) + .body("cookieValue1", equalTo("John Doe")); + } + + @Test public void + can_send_multiple_cookies() { + RestAssuredWebTestClient.given() + .cookie("cookieName1", "John Doe") + .cookie("cookieName2", "rest assured") + .when() + .get("/cookie") + .then() + .statusCode(200) + .body("cookieValue1", equalTo("John Doe")) + .body("cookieValue2", equalTo("rest assured")); + } + + @Test public void + can_send_cookies_using_map() { + Map cookies = new HashMap(); + cookies.put("cookieName1", "John Doe"); + cookies.put("cookieName2", "rest assured"); + + RestAssuredWebTestClient.given() + .cookies(cookies) + .when() + .get("/cookie") + .then() + .statusCode(200) + .body("cookieValue1", equalTo("John Doe")) + .body("cookieValue2", equalTo("rest assured")); + } + + @Test public void + can_send_cookies_using_cookies_class() { + RestAssuredWebTestClient.given(). + cookies(new Cookies(new Cookie.Builder("cookieName1", "John Doe") + .build(), new Cookie.Builder("cookieName2", "rest assured") + .build())) + .when() + .get("/cookie") + .then() + .statusCode(200) + .body("cookieValue1", equalTo("John Doe")) + .body("cookieValue2", equalTo("rest assured")); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetTest.java new file mode 100644 index 000000000..201b73c76 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GetTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; + +public class GetTest { + + @Test public void + unnamed_path_params_works() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting?name={name}", "Johan") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void simple_get_works() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .when() + .get() + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, World!")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GreetingControllerRestAssuredTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GreetingControllerRestAssuredTest.java new file mode 100644 index 000000000..9815f98f9 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/GreetingControllerRestAssuredTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import org.junit.Test; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.reactive.server.WebTestClient.bindToController; + +public class GreetingControllerRestAssuredTest { + + @Test + public void + uses_predefined_web_test_client_instance() { + WebTestClient webTestClient = bindToController(new GreetingController()).build(); + + RestAssuredWebTestClient.given() + .webTestClient(webTestClient) + .param("name", "Johan") + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + param_with_int() { + WebTestClient webTestClient = bindToController(new GreetingController()).build(); + + RestAssuredWebTestClient.given() + .webTestClient(webTestClient) + .param("name", 1) + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, 1!")); + } + + @Test + public void + uses_predefined_standalone() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .param("name", "Johan") + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + uses_static_web_test_client() { + RestAssuredWebTestClient.webTestClient(bindToController(new GreetingController()).build()); + + try { + RestAssuredWebTestClient.given() + .param("name", "Johan") + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + RestAssuredWebTestClient.given(). + param("name", "Erik") + .when() + .get("/greeting") + .then() + .body("id", equalTo(2)) + .body("content", equalTo("Hello, Erik!")); + } finally { + RestAssuredWebTestClient.reset(); + } + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/HeaderTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/HeaderTest.java new file mode 100644 index 000000000..2c0c7d9d1 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/HeaderTest.java @@ -0,0 +1,152 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.http.Header; +import io.restassured.http.Headers; +import io.restassured.module.webtestclient.setup.HeaderController; +import io.restassured.module.webtestclient.setup.RedirectController; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.HashMap; +import java.util.Map; + +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.given; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.lessThanOrEqualTo; + +public class HeaderTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @BeforeClass + public static void configureWebTestClientInstance() { + RestAssuredWebTestClient.standaloneSetup(new HeaderController()); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test public void + can_send_header_using_header_class() { + given() + .header(new Header("headerName", "John Doe")) + .when() + .get("/header") + .then() + .statusCode(200) + .body("headerName", equalTo("John Doe")); + } + + @Test public void + can_use_mapping_function_when_validating_header_value() { + given() + .header(new Header("headerName", "200")) + .when() + .get("/header") + .then() + .header("Content-Length", Integer::parseInt, lessThanOrEqualTo(1000)); + } + + @Test public void + validate_may_fail_when_using_mapping_function_when_validating_header_value() { + exception.expect(AssertionError.class); + exception.expectMessage("Expected header \"Content-Length\" was not a value greater than <1000>, " + + "was \"45\". Headers are:"); + + given() + .header(new Header("headerName", "200")) + .when() + .get("/header") + .then() + .header("Content-Length", Integer::parseInt, greaterThan(1000)); + } + + @Test public void + can_send_header_using_header_name_and_value() { + given() + .header("headerName", "John Doe") + .when() + .get("/header") + .then() + .statusCode(200) + .body("headerName", equalTo("John Doe")); + } + + @Test public void + can_send_multiple_headers() { + given() + .header("headerName", "John Doe") + .header("user-agent", "rest assured") + .when() + .get("/header") + .then() + .statusCode(200) + .body("headerName", equalTo("John Doe")) + .body("user-agent", equalTo("rest assured")); + } + + @Test public void + can_send_headers_using_map() { + Map headers = new HashMap(); + headers.put("headerName", "John Doe"); + headers.put("user-agent", "rest assured"); + + given() + .headers(headers) + .when() + .get("/header") + .then() + .statusCode(200) + .body("headerName", equalTo("John Doe")) + .body("user-agent", equalTo("rest assured")); + } + + @Test public void + can_send_headers_using_headers_class() { + given() + .headers(new Headers(new Header("headerName", "John Doe"), + new Header("user-agent", "rest assured"))) + .when() + .get("/header") + .then() + .statusCode(200) + .body("headerName", equalTo("John Doe")) + .body("user-agent", equalTo("rest assured")); + } + + @Test + public void canUseResponseAwareMatchersForHeaderValidation() { + given() + .standaloneSetup(new RedirectController()) + .when() + .get("/redirect") + .then() + .statusCode(301) + .header("Location", response -> endsWith("/redirect/" + response.path("id"))); + } +} + diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/LoggingIfValidationFailsTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/LoggingIfValidationFailsTest.java new file mode 100644 index 000000000..f955ae11b --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/LoggingIfValidationFailsTest.java @@ -0,0 +1,213 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.config.LogConfig; +import io.restassured.http.ContentType; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.setup.PostController; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecBuilder; +import org.apache.commons.io.output.WriterOutputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.web.util.UriUtils; + +import java.io.PrintStream; +import java.io.StringWriter; + +import static io.restassured.filter.log.LogDetail.HEADERS; +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.given; +import static io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig.config; +import static java.nio.charset.Charset.defaultCharset; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class LoggingIfValidationFailsTest { + + private StringWriter writer; + private PrintStream captor; + + @Before + public void + given_writer_and_captor_is_initialized() { + writer = new StringWriter(); + captor = new PrintStream(new WriterOutputStream(writer, defaultCharset()), true); + } + + @After + public void + reset_rest_assured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void logging_of_both_request_and_response_validation_works_when_test_fails() { + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true) + .enableLoggingOfRequestAndResponseIfValidationFails()); + + try { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), equalTo("Request method:\tPOST\nRequest URI:\thttp://localhost:8080/greetingPost\nProxy:\t\t\t\nRequest params:\tname=Johan\nQuery params:\t\nForm params:\t\nPath params:\t\nHeaders:\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + config().getEncoderConfig().defaultContentCharset() + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n\n" + "" + + "200\nContent-Type: application/json;charset=UTF-8\nContent-Length: 34\n\n{\n \"id\": 1,\n \"content\": \"Hello, Johan!\"\n}\n")); + } + } + + @Test + public void logging_of_both_request_with_uri_function_and_response_validation_works_when_test_fails() { + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true) + .enableLoggingOfRequestAndResponseIfValidationFails()); + + try { + given() + .standaloneSetup(new PostController()) + .contentType(ContentType.URLENC) + .when() + .post(uriBuilder -> uriBuilder.path("/greetingPost").queryParam("name", "Johan").build()) + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), containsString(UriUtils.encode("Request from uri function", defaultCharset()))); + assertThat(writer.toString(), containsString("Request method:\tPOST\n")); + assertThat(writer.toString(), containsString("Proxy:\t\t\t\nRequest params:\t\nQuery params:\t\nForm params:\t\nPath params:\t\nHeaders:\t\tContent-Type=application/x-www-form-urlencoded" + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n\n" + "" + + "200\nContent-Type: application/json;charset=UTF-8\nContent-Length: 34\n\n{\n \"id\": 1,\n \"content\": \"Hello, Johan!\"\n}\n")); + } + } + + @Test + public void logging_of_both_request_and_response_validation_works_when_test_fails_when_configured_with_log_detail() { + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true) + .enableLoggingOfRequestAndResponseIfValidationFails(HEADERS)); + + try { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), equalTo("Headers:\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + config().getEncoderConfig().defaultContentCharset() + "\n\n" + + "Content-Type: application/json;charset=UTF-8\nContent-Length: 34\n")); + } + } + + @Test + public void + logging_of_both_request_and_response_validation_works_when_test_fails_when_using_static_response_and_request_specs_declared_before_enable_logging() { + final StringWriter writer = new StringWriter(); + final PrintStream captor = new PrintStream(new WriterOutputStream(writer), true); + + RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder().expectStatusCode(200).build(); + RestAssuredWebTestClient.requestSpecification = new WebTestClientRequestSpecBuilder() + .setConfig(config().logConfig(new LogConfig(captor, true))) + .addHeader("Api-Key", "1234").build(); + + RestAssuredWebTestClient.enableLoggingOfRequestAndResponseIfValidationFails(HEADERS); + + try { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), + equalTo("Headers:\t\tApi-Key=1234\n\t\t\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + RestAssuredWebTestClientConfig.config().getEncoderConfig().defaultContentCharset() + + "\n\nContent-Type: application/json;charset=UTF-8\nContent-Length: 34\n")); + } + } + + @Test + public void + doesnt_log_if_request_or_response_when_validation_succeeds_when_request_and_response_logging_if_validation_fails_is_enabled() { + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true) + .enableLoggingOfRequestAndResponseIfValidationFails()); + + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), isEmptyString()); + } + + @Test + public void + logging_is_applied_when_using_non_static_response_specifications() { + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true) + .enableLoggingOfRequestAndResponseIfValidationFails()); + + try { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .spec(new ResponseSpecBuilder() + .expectBody("id", equalTo(2)) + .expectBody("content", equalTo("Hello, Johan2!")) + .build()); + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), not(isEmptyOrNullString())); + } + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ParserTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ParserTest.java new file mode 100644 index 000000000..ea1a69b1e --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ParserTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.module.webtestclient.setup.ParserController; +import io.restassured.parsing.Parser; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; + +public class ParserTest { + + @Before + public void + given_controller_is_assigned_to_rest_assured() { + RestAssuredWebTestClient.standaloneSetup(new ParserController()); + } + + @After + public void + rest_assured_is_reset() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + using_static_parser_its_possible_to_parse_unknown_content_types() { + RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder() + .registerParser("some/thing", Parser.JSON).build(); + + RestAssuredWebTestClient.given() + .param("param", "my param") + .when() + .get("/parserWithUnknownContentType") + .then() + .statusCode(200) + .contentType(equalTo("some/thing;charset=UTF-8")) + .body("param", equalTo("my param")); + } + + @Test + public void + using_non_static_parser_its_possible_to_parse_unknown_content_types() { + RestAssuredWebTestClient.given() + .param("param", "my param") + .when() + .get("/parserWithUnknownContentType") + .then() + .parser("some/thing", Parser.JSON) + .statusCode(200) + .contentType(equalTo("some/thing;charset=UTF-8")) + .body("param", equalTo("my param")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PostTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PostTest.java new file mode 100644 index 000000000..8bc76ecf3 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PostTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.http.ContentType; +import io.restassured.module.webtestclient.setup.PostController; +import io.restassured.module.webtestclient.setup.support.Greeting; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.hamcrest.Matchers.equalTo; + +public class PostTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RestAssuredWebTestClient.webTestClient(WebTestClient.bindToController(new PostController()).build()); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + automatically_adds_x_www_form_urlencoded_as_content_type_when_posting_params() { + RestAssuredWebTestClient.given() + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + can_supply_string_as_body_for_post() { + RestAssuredWebTestClient.given() + .body("a string") + .when() + .post("/stringBody") + .then() + .body(equalTo("a string")); + } + + @Test + public void + can_supply_object_as_body_and_serialize_as_json() { + Greeting greeting = new Greeting(); + greeting.setFirstName("John"); + greeting.setLastName("Doe"); + + RestAssuredWebTestClient.given() + .contentType(ContentType.JSON) + .body(greeting) + .when() + .post("/jsonReflect") + .then() + .statusCode(200) + .body("firstName", equalTo("John")) + .body("lastName", equalTo("Doe")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PutTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PutTest.java new file mode 100644 index 000000000..b6e69dab4 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/PutTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.config.LogConfig; +import io.restassured.module.webtestclient.setup.PutController; +import io.restassured.module.webtestclient.setup.support.Greeting; +import org.apache.commons.io.output.WriterOutputStream; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.test.web.reactive.server.WebTestClient; + +import java.io.PrintStream; +import java.io.StringWriter; + +import static io.restassured.http.ContentType.JSON; +import static io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig.newConfig; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +public class PutTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RestAssuredWebTestClient.webTestClient(WebTestClient.bindToController(new PutController()).build()); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + doesnt_automatically_add_x_www_form_urlencoded_as_content_type_when_putting_params() { + StringWriter writer = new StringWriter(); + PrintStream captor = new PrintStream(new WriterOutputStream(writer), true); + + RestAssuredWebTestClient.given() + .config(newConfig().logConfig(new LogConfig(captor, true))) + .param("name", "Johan") + .when() + .put("/greetingPut") + .then() + .log().all() + .statusCode(415); + + assertThat(writer.toString(), equalTo("415: Unsupported Media Type\n")); + } + + @Test + public void + automatically_adds_x_www_form_urlencoded_as_content_type_when_putting_form_params() { + RestAssuredWebTestClient.given() + .formParam("name", "Johan") + .when() + .put("/greetingPut") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + can_supply_string_as_body_for_put() { + RestAssuredWebTestClient.given() + .body("a string") + .when() + .put("/stringBody") + .then() + .body(equalTo("a string")); + } + + @Test + public void + can_supply_object_as_body_and_serialize_as_json() { + Greeting greeting = new Greeting(); + greeting.setFirstName("John"); + greeting.setLastName("Doe"); + + RestAssuredWebTestClient.given() + .contentType(JSON) + .body(greeting) + .when() + .put("/jsonReflect") + .then() + .statusCode(200) + .body("firstName", equalTo("John")) + .body("lastName", equalTo("Doe")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/QueryParamTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/QueryParamTest.java new file mode 100644 index 000000000..2fa974429 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/QueryParamTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.setup.QueryParamsProcessor; +import org.junit.Test; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; + +public class QueryParamTest { + + @Test + public void param_with_int() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .queryParam("name", "John") + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, John!")); + } + + @Test + public void query_param() { + RouterFunction queryParamsRoute = RouterFunctions.route(path("/queryParam") + .and(method(HttpMethod.GET)), new QueryParamsProcessor()::processQueryParams); + RestAssuredWebTestClient.given() + .standaloneSetup(queryParamsRoute) + .queryParam("name", "John") + .queryParam("message", "Good!") + .when() + .get("/queryParam") + .then().log().all() + .body("name", equalTo("Hello, John!")) + .body("message", equalTo("Good!")) + .body("_link", equalTo("/queryParam?name=John&message=Good!")); + } + +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RequestLoggingTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RequestLoggingTest.java new file mode 100644 index 000000000..f3be69a22 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RequestLoggingTest.java @@ -0,0 +1,200 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.RestAssured; +import io.restassured.config.LogConfig; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.setup.BasePathController; +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.setup.PostController; +import org.apache.commons.io.output.WriterOutputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; +import java.io.StringWriter; + +import static java.nio.charset.Charset.defaultCharset; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.isEmptyString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class RequestLoggingTest { + + private StringWriter writer; + + @Before + public void + given_config_is_stored_in_writer() { + writer = new StringWriter(); + PrintStream captor = new PrintStream(new WriterOutputStream(writer, defaultCharset()), true); + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true)); + } + + @After + public void + reset_rest_assured() { + RestAssured.reset(); + } + + @Test + public void + logging_param_works() { + RestAssuredWebTestClient.given() + .log().all() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), equalTo("Request method:\tPOST\nRequest URI:" + + "\thttp://localhost:8080/greetingPost\nProxy:\t\t\t\nRequest params:\tname=Johan\nQuery params:" + + "\t\nForm params:\t\nPath params:\t\nHeaders:\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + RestAssuredWebTestClientConfig.config().getEncoderConfig().defaultContentCharset() + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n")); + } + + @Test + public void + logging_query_param_works() { + RestAssuredWebTestClient.given() + .log().all() + .standaloneSetup(new GreetingController()) + .queryParam("name", "Johan") + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), equalTo("Request method:\tGET\nRequest URI:" + + "\thttp://localhost:8080/greeting?name=Johan\nProxy:\t\t\t\nRequest params:\t\nQuery params:" + + "\tname=Johan\nForm params:\t\nPath params:\t\nHeaders:\t\t\nCookies:\t\t" + + "\nMultiparts:\t\t\nBody:\t\t\t\n")); + } + + @Test + public void + logging_form_param_works() { + RestAssuredWebTestClient.given() + .log().all() + .standaloneSetup(new PostController()) + .formParam("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), equalTo("Request method:\tPOST\nRequest URI:" + + "\thttp://localhost:8080/greetingPost\nProxy:\t\t\t\nRequest params:\t\nQuery params:" + + "\t\nForm params:\tname=Johan\nPath params:\t\nHeaders:" + + "\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + RestAssuredWebTestClientConfig.config().getEncoderConfig().defaultContentCharset() + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n")); + } + + @Test + public void + can_supply_string_as_body_for_post() { + RestAssuredWebTestClient.given() + .standaloneSetup(new PostController()) + .log().all() + .body("a string") + .when() + .post("/stringBody") + .then() + .body(equalTo("a string")); + + assertThat(writer.toString(), equalTo("Request method:\tPOST\nRequest URI:" + + "\thttp://localhost:8080/stringBody\nProxy:\t\t\t\nRequest params:\t\nQuery params:" + + "\t\nForm params:\t\nPath params:\t\nHeaders:\t\t\nCookies:\t\t" + + "\nMultiparts:\t\t\nBody:\na string\n")); + } + + @Test + public void + base_path_is_prepended_to_path_when_logging() { + RestAssuredWebTestClient.basePath = "/my-path"; + + try { + RestAssuredWebTestClient.given() + .log().all() + .standaloneSetup(new BasePathController()) + .param("name", "Johan") + .when() + .get("/greetingPath") + .then() + .statusCode(200) + .body("content", equalTo("Hello, Johan!")); + } finally { + RestAssuredWebTestClient.reset(); + } + assertThat(writer.toString(), equalTo("Request method:\tGET\nRequest URI:" + + "\thttp://localhost:8080/my-path/greetingPath?name=Johan\nProxy:\t\t\t\nRequest params:" + + "\tname=Johan\nQuery params:\t\nForm params:\t\nPath params:\t\nHeaders:\t\t" + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n")); + } + + @Test + public void + logging_if_request_validation_fails_works() { + try { + RestAssuredWebTestClient.given() + .log().ifValidationFails() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), equalTo("Request method:\tPOST\nRequest URI:" + + "\thttp://localhost:8080/greetingPost\nProxy:\t\t\t\nRequest params:\tname=Johan" + + "\nQuery params:\t\nForm params:\t\nPath params:\t\nHeaders:" + + "\t\tContent-Type=application/x-www-form-urlencoded;charset=" + + RestAssuredWebTestClientConfig.config().getEncoderConfig().defaultContentCharset() + + "\nCookies:\t\t\nMultiparts:\t\t\nBody:\t\t\t\n")); + } + } + + @Test + public void + doesnt_log_if_request_validation_succeeds_when_request_logging_if_validation_fails_is_enabled() { + RestAssuredWebTestClient.given() + .log().ifValidationFails() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), isEmptyString()); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResponseLoggingTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResponseLoggingTest.java new file mode 100644 index 000000000..101f5b9ef --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResponseLoggingTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.RestAssured; +import io.restassured.config.LogConfig; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.setup.PostController; +import org.apache.commons.io.output.WriterOutputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintStream; +import java.io.StringWriter; + +import static java.nio.charset.Charset.defaultCharset; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.isEmptyString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class ResponseLoggingTest { + + private StringWriter writer; + + @Before + public void + given_config_is_stored_in_writer() { + writer = new StringWriter(); + PrintStream captor = new PrintStream(new WriterOutputStream(writer, defaultCharset()), true); + RestAssuredWebTestClient.config = new RestAssuredWebTestClientConfig() + .logConfig(new LogConfig(captor, true)); + } + + @After + public void + reset_rest_assured() { + RestAssured.reset(); + } + + @Test + public void + logging_if_response_validation_fails_works() { + try { + RestAssuredWebTestClient.given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .log().ifValidationFails() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan2!")); + + fail("Should throw AssertionError"); + } catch (AssertionError e) { + assertThat(writer.toString(), equalTo("200\nContent-Type: application/json;charset=UTF-8" + + "\nContent-Length: 34\n\n{\n \"id\": 1,\n \"content\": \"Hello, Johan!\"\n}\n")); + } + } + + @Test + public void + logging_if_response_validation_fails_doesnt_log_anything_if_validation_succeeds() { + RestAssuredWebTestClient.given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .log().ifValidationFails() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + assertThat(writer.toString(), isEmptyString()); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RestDocsTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RestDocsTest.java new file mode 100644 index 000000000..2fcc21813 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/RestDocsTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.restdocs.snippet.SnippetException; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document; +import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration; + +public class RestDocsTest { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets"); + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void path_parameters_are_automatically_supported() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController(), documentationConfiguration(restDocumentation)) + .queryParam("name", "John") + .when() + .consumeWith(document("greeting", + pathParameters( + parameterWithName("path").description("The path to greeting")), + responseFields( + fieldWithPath("id").description("The ID of the greeting"), + fieldWithPath("content").description("The content of the greeting")) + )) + .get("/{path}", "greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, John!")); + } + + @Test + public void document_generation_is_executed() { + exception.expect(SnippetException.class); + exception.expectMessage("Path parameters with the following names were not documented: [path]. " + + "Path parameters with the following names were not found in the request: [xxx]"); + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController(), documentationConfiguration(restDocumentation)) + .queryParam("name", "John") + .when() + .consumeWith(document("greeting", + pathParameters( + parameterWithName("xxx").description("The path to greeting")), + responseFields( + fieldWithPath("id").description("The ID of the greeting"), + fieldWithPath("content").description("The content of the greeting")) + )) + .get("/{path}", "greeting"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResultMatcherTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResultMatcherTest.java new file mode 100644 index 000000000..c7f436a52 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/ResultMatcherTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.setup.HeaderController; +import org.hamcrest.Matchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; + +public class ResultMatcherTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RestAssuredWebTestClient.standaloneSetup(new HeaderController()); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + unnamed_path_params_works() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting?name={name}", "Johan") + .then() + .header("Content-Type", APPLICATION_JSON_UTF8_VALUE) + .statusCode(HttpStatus.OK.value()) + .body("id", Matchers.equalTo(1)) + .body("content", Matchers.equalTo("Hello, Johan!")); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SecuredRequestTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SecuredRequestTest.java new file mode 100644 index 000000000..e38dcbd69 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SecuredRequestTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.SecuredProcessor; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.given; +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; + +public class SecuredRequestTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void + basic_authentication_filter_is_applied() { + RouterFunction routerFunction = RouterFunctions + .route(path("/securedGreeting").and(method(HttpMethod.GET)), + new SecuredProcessor()::processSecuredRequest); + RestAssuredWebTestClient.standaloneSetup(routerFunction, basicAuthentication("test", "pass")); + given() + .when() + .get("/securedGreeting") + .then() + .statusCode(200) + .body("auth", equalTo("Basic dGVzdDpwYXNz")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SetCookiesTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SetCookiesTest.java new file mode 100644 index 000000000..170fbec57 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/SetCookiesTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.CookieProcessor; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.http.HttpMethod; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.springframework.web.reactive.function.server.RequestPredicates.method; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; + +public class SetCookiesTest { + + @BeforeClass + public static void configureWebTestClientInstance() { + RouterFunction setAttributesRoute = RouterFunctions + .route(path("/setCookies").and(method(HttpMethod.GET)), + new CookieProcessor()::processCookies); + RestAssuredWebTestClient.standaloneSetup(setAttributesRoute); + } + + @AfterClass + public static void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + can_receive_cookies() { + RestAssuredWebTestClient.given() + .queryParam("name", "John Doe") + .queryParam("project", "rest assured") + .when() + .get("/setCookies") + .then() + .statusCode(200) + .cookie("name", "John Doe") + .cookie("project", "rest assured"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientNonStaticRequestAndResponseSpecTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientNonStaticRequestAndResponseSpecTest.java new file mode 100644 index 000000000..ae5b22c0e --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientNonStaticRequestAndResponseSpecTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.http.ContentType; +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecBuilder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientNonStaticRequestAndResponseSpecTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void + request_and_response_spec_can_be_defined_statically() { + RestAssuredWebTestClient.given() + .spec(new WebTestClientRequestSpecBuilder() + .setContentType(ContentType.JSON) + .addHeader("accept", ContentType.JSON.toString()) + .build()) + .standaloneSetup(new GreetingController()) + .formParam("name", "Johan") + .when() + .post("/greeting") + .then() + .statusCode(200) + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientParamConfigTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientParamConfigTest.java new file mode 100644 index 000000000..57e1375fd --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientParamConfigTest.java @@ -0,0 +1,174 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.MultiValueController; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static io.restassured.config.ParamConfig.UpdateStrategy.REPLACE; +import static io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig.config; +import static io.restassured.module.webtestclient.config.WebTestClientParamConfig.paramConfig; +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientParamConfigTest { + + @Before + public void configureWebTestClientInstance() { + RestAssuredWebTestClient.standaloneSetup(new MultiValueController()); + } + + @After + public void restRestAssured() { + RestAssuredWebTestClient.reset(); + } + + @Test + public void + merges_request_params_by_default() { + RestAssuredWebTestClient + .given() + .param("list", "value1") + .param("list", "value2") + .when() + .get("/multiValueParam") + .then() + .body("list", equalTo("value1,value2")); + } + + @Test + public void + merges_query_params_by_default() { + RestAssuredWebTestClient.given() + .queryParam("list", "value1") + .queryParam("list", "value2") + .when() + .get("/multiValueParam") + .then() + .body("list", equalTo("value1,value2")); + } + + @Test + public void + merges_form_params_by_default() { + RestAssuredWebTestClient.given() + .formParam("list", "value1") + .formParam("list", "value2") + .when() + .post("/multiValueParam") + .then() + .body("list", equalTo("value1,value2")); + } + + @Test + public void + replaces_request_params_when_configured_to_do_so() { + RestAssuredWebTestClient.given() + .config(config().paramConfig(paramConfig().requestParamsUpdateStrategy(REPLACE))) + .param("list", "value1") + .param("list", "value2") + .queryParam("list2", "value3") + .queryParam("list2", "value4") + .formParam("list3", "value5") + .formParam("list3", "value6") + .when() + .post("/threeMultiValueParam") + .then() + .body("list", equalTo("value2")) + .body("list2", equalTo("value3,value4")) + .body("list3", equalTo("value5,value6")); + } + + @Test + public void + replaces_query_params_when_configured_to_do_so() { + RestAssuredWebTestClient.given() + .config(config().paramConfig(paramConfig().queryParamsUpdateStrategy(REPLACE))) + .param("list", "value1") + .param("list", "value2") + .queryParam("list2", "value3") + .queryParam("list2", "value4") + .formParam("list3", "value5") + .formParam("list3", "value6") + .when() + .post("/threeMultiValueParam") + .then() + .body("list", equalTo("value1,value2")) + .body("list2", equalTo("value4")) + .body("list3", equalTo("value5,value6")); + } + + @Test + public void + replaces_form_params_when_configured_to_do_so() { + RestAssuredWebTestClient.given() + .config(config().paramConfig(paramConfig().formParamsUpdateStrategy(REPLACE))) + .param("list", "value1") + .param("list", "value2") + .queryParam("list2", "value3") + .queryParam("list2", "value4") + .formParam("list3", "value5") + .formParam("list3", "value6") + .when() + .post("/threeMultiValueParam") + .then() + .body("list", equalTo("value1,value2")) + .body("list2", equalTo("value3,value4")) + .body("list3", equalTo("value6")); + } + + @Test + public void + replaces_all_parameters_when_configured_to_do_so() { + RestAssuredWebTestClient.given() + .config(config().paramConfig(paramConfig().replaceAllParameters())) + .param("list", "value1") + .param("list", "value2") + .queryParam("list2", "value3") + .queryParam("list2", "value4") + .formParam("list3", "value5") + .formParam("list3", "value6") + .when() + .post("/threeMultiValueParam") + .then() + .body("list", equalTo("value2")) + .body("list2", equalTo("value4")) + .body("list3", equalTo("value6")); + } + + @Test + public void + merges_all_parameters_when_configured_to_do_so() { + RestAssuredWebTestClient.config = config().paramConfig(paramConfig().replaceAllParameters()); + + RestAssuredWebTestClient.given() + .config(config().paramConfig(paramConfig().mergeAllParameters())) + .param("list", "value1") + .param("list", "value2") + .queryParam("list2", "value3") + .queryParam("list2", "value4") + .formParam("list3", "value5") + .formParam("list3", "value6") + .when() + .post("/threeMultiValueParam") + .then() + .body("list", equalTo("value1,value2")) + .body("list2", equalTo("value3,value4")) + .body("list3", equalTo("value5,value6")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientPathParamTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientPathParamTest.java new file mode 100644 index 000000000..1b4b1fd38 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientPathParamTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientPathParamTest { + + @Test + public void unnamed_path_param_works() { + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .queryParam("name", "John") + .when() + .get("/{x}", "greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, John!")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientRequestMethodTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientRequestMethodTest.java new file mode 100644 index 000000000..a7524402c --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientRequestMethodTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.setup.PostController; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static io.restassured.http.Method.GET; +import static io.restassured.http.Method.POST; +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.given; +import static io.restassured.module.webtestclient.RestAssuredWebTestClient.request; +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientRequestMethodTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void + request_method_accepts_enum_verb() { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .request(POST, "/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + request_method_accepts_enum_verb_and_unnamed_path_params() { + given() + .standaloneSetup(new GreetingController()) + .queryParam("name", "John") + .when() + .request(GET, "/{x}", "greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, John!")); + } + + @Test + public void + request_method_accepts_string_verb() { + given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .request("post", "/greetingPost") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + } + + @Test + public void + request_method_accepts_string_verb_and_unnamed_path_params() { + given() + .standaloneSetup(new GreetingController()) + .queryParam("name", "John") + .when() + .request("GEt", "/{x}", "greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, John!")); + } + + @Test + public void + static_request_method_accepts_string_verb() { + RestAssuredWebTestClient.standaloneSetup(new GreetingController()); + + try { + request(" gEt ", "/greeting").then().body("id", equalTo(1)) + .body("content", equalTo("Hello, World!")); + } finally { + RestAssuredWebTestClient.reset(); + } + } + + @Test + public void + static_request_method_accepts_enum_verb_and_path_params() { + RestAssuredWebTestClient.standaloneSetup(new GreetingController()); + + try { + request(GET, "/{greeting}", "greeting").then().body("id", equalTo(1)) + .body("content", equalTo("Hello, World!")); + } finally { + RestAssuredWebTestClient.reset(); + } + } + + @Test + public void + throws_iae_when_http_verb_is_not_supported_by_web_test_client() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("HTTP method 'connect' is not supported by WebTestClient"); + + given().standaloneSetup(new GreetingController()).request("connect", "/greeting"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseAwareMatcherTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseAwareMatcherTest.java new file mode 100644 index 000000000..70eadf6b3 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseAwareMatcherTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.matcher.RestAssuredWebTestClientMatchers; +import io.restassured.module.webtestclient.setup.ResponseAwareMatcherController; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientResponseAwareMatcherTest { + + @Test + public void + can_use_predefined_matcher_for_response_aware_matching() { + RestAssuredWebTestClient.given() + .standaloneSetup(new ResponseAwareMatcherController()) + .when() + .get("/responseAware") + .then() + .statusCode(200) + .body("_links.self.href", RestAssuredWebTestClientMatchers.endsWithPath("id")) + .body("status", equalTo("ongoing")); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseTimeTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseTimeTest.java new file mode 100644 index 000000000..b82c4fc39 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientResponseTimeTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.module.webtestclient.setup.PostController; +import org.junit.Test; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; + +public class WebTestClientResponseTimeTest { + + @Test + public void + can_use_response_time_validation_in_web_test_client_extension() { + RestAssuredWebTestClient.given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .time(lessThan(3L), SECONDS) + .statusCode(is(200)); + } + + @Test + public void + can_extract_response_time_in_web_test_client_extension() { + long time = + RestAssuredWebTestClient.given() + .standaloneSetup(new PostController()) + .param("name", "Johan") + .when() + .post("/greetingPost") + .then() + .extract().time(); + + assertThat(time).isGreaterThan(-1).isLessThan(3000L); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientSpecificationMergingTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientSpecificationMergingTest.java new file mode 100644 index 000000000..9342100c9 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientSpecificationMergingTest.java @@ -0,0 +1,450 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.config.LogConfig; +import io.restassured.config.RestAssuredConfig; +import io.restassured.filter.log.LogDetail; +import io.restassured.http.ContentType; +import io.restassured.http.Cookie; +import io.restassured.http.Header; +import io.restassured.module.webtestclient.config.RestAssuredWebTestClientConfig; +import io.restassured.module.webtestclient.internal.WebTestClientRequestSpecificationImpl; +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.setup.PostController; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecBuilder; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification; +import io.restassured.path.json.config.JsonPathConfig; +import org.apache.commons.io.output.WriterOutputStream; +import org.assertj.core.api.Assertions; +import org.junit.Test; +import org.powermock.reflect.Whitebox; +import org.springframework.test.web.reactive.server.WebTestClient; + +import java.io.PrintStream; +import java.io.StringWriter; + +import static io.restassured.config.JsonConfig.jsonConfig; +import static io.restassured.config.SessionConfig.sessionConfig; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientSpecificationMergingTest { + + @Test + public void + query_params_are_merged() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .queryParam("param2", "value2").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getQueryParams()) + .containsOnly(entry("param1", "value1"), entry("param2", "value2")); + } + + private WebTestClientRequestSpecificationImpl implementation(WebTestClientRequestSpecification spec) { + return (WebTestClientRequestSpecificationImpl) spec; + } + + @Test + public void + form_params_are_merged() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addFormParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .formParam("param2", "value2").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getFormParams()) + .containsOnly(entry("param1", "value1"), entry("param2", "value2")); + } + + @Test + public void + params_are_merged() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .param("param2", "value2").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getParams()) + .containsOnly(entry("param1", "value1"), entry("param2", "value2")); + } + + @Test + public void + attributes_are_merged() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addAttribute("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .attribute("param2", "value2").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getAttributes()) + .containsOnly(entry("param1", "value1"), entry("param2", "value2")); + } + + @Test + public void + multi_parts_are_merged() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addMultiPart("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .multiPart("param2", "value2").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getMultiParts()).hasSize(2); + } + + @Test + public void + request_body_is_overwritten_when_defined_in_specification() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder().setBody("body2").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().body("body1").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestBody()).isEqualTo("body2"); + } + + @Test + public void + request_body_is_not_overwritten_when_not_defined_in_specification() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().body("body1").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestBody()).isEqualTo("body1"); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + base_path_is_overwritten_when_defined_in_specification() { + // Given + RestAssuredWebTestClient.basePath = "/something"; + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setBasePath("basePath").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().body("body1").spec(specToMerge); + + // Then + RestAssuredWebTestClient.reset(); + Assertions.assertThat(implementation(spec).getBasePath()).isEqualTo("basePath"); + } + + @Test + public void + base_path_is_not_overwritten_when_not_defined_in_specification() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().body("body1").spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getBasePath()).isEqualTo(RestAssuredWebTestClient.basePath); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + web_test_client_instance_is_overwritten_when_defined_in_specification() { + // Given + WebTestClient otherWebTestClientInstance = WebTestClient.bindToController(new PostController()).build(); + WebTestClient thisWebTestClientInstance = WebTestClient.bindToController(new GreetingController()).build(); + + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setWebTestClient(otherWebTestClientInstance).build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given() + .webTestClient(thisWebTestClientInstance).spec(specToMerge); + + // Then + WebTestClient webTestClient = Whitebox.getInternalState(implementation(spec) + .getWebTestClientFactory(), "webTestClient"); + assertThat(webTestClient).isSameAs(otherWebTestClientInstance); + } + + @Test + public void + web_test_client_factory_is_not_overwritten_when_not_defined_in_specification() { + // Given + WebTestClient webTestClientInstance = WebTestClient.bindToController(new GreetingController()).build(); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder().addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().webTestClient(webTestClientInstance).spec(specToMerge); + + // Then + WebTestClient webTestClient = Whitebox.getInternalState(implementation(spec).getWebTestClientFactory(), + "webTestClient"); + assertThat(webTestClient).isSameAs(webTestClientInstance); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + cookies_are_merged_when_defined_in_specification() { + // Given + Cookie otherCookie = new Cookie.Builder("cookie1", "value1").build(); + Cookie thisCookie = new Cookie.Builder("cookie2", "value2").build(); + + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder().addCookie(otherCookie).build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().cookie(thisCookie).spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getCookies()).containsOnly(thisCookie, otherCookie); + } + + @Test + public void + cookies_are_not_overwritten_when_not_defined_in_specification() { + // Given + Cookie thisCookie = new Cookie.Builder("cookie2", "value2").build(); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().cookie(thisCookie).spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getCookies()).containsOnly(thisCookie); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + content_type_is_overwritten_when_defined_in_specification() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setContentType(ContentType.JSON).build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().contentType(ContentType.XML) + .spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestContentType()).isEqualTo(ContentType.JSON.toString()); + } + + @Test + public void + content_type_is_not_overwritten_when_not_defined_in_specification() { + // Given + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().contentType(ContentType.XML) + .spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestContentType()).isEqualTo(ContentType.XML.toString()); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + headers_are_merged_when_defined_in_specification() { + // Given + Header otherHeader = new Header("header1", "value1"); + Header thisHeader = new Header("header2", "value2"); + + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder().addHeader(otherHeader) + .build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().header(thisHeader).spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestHeaders()).containsOnly(thisHeader, otherHeader); + } + + @Test + public void + headers_are_not_overwritten_when_not_defined_in_specification() { + // Given + Header thisHeader = new Header("cookie2", "value2"); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().header(thisHeader).spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getRequestHeaders()).containsOnly(thisHeader); + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + } + + @Test + public void + configs_of_same_type_are_overwritten_when_defined_in_specification() { + // Given + RestAssuredWebTestClientConfig otherConfig = new RestAssuredWebTestClientConfig() + .with().jsonConfig(jsonConfig() + .with().numberReturnType(JsonPathConfig.NumberReturnType.BIG_DECIMAL)); + RestAssuredWebTestClientConfig thisConfig = new RestAssuredWebTestClientConfig() + .with().jsonConfig(jsonConfig() + .with().numberReturnType(JsonPathConfig.NumberReturnType.FLOAT_AND_DOUBLE)); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setConfig(otherConfig).build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().config(thisConfig).spec(specToMerge); + + // Then + assertThat(implementation(spec).getRestAssuredWebTestClientConfig().getJsonConfig().numberReturnType()) + .isEqualTo(JsonPathConfig.NumberReturnType.BIG_DECIMAL); + } + + @Test + public void + config_is_not_overwritten_when_not_defined_in_specification() { + // Given + RestAssuredWebTestClientConfig thisConfig = new RestAssuredWebTestClientConfig() + .with().jsonConfig(jsonConfig() + .with().numberReturnType(JsonPathConfig.NumberReturnType.FLOAT_AND_DOUBLE)); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .addQueryParam("param1", "value1").build(); + + // When + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().config(thisConfig).spec(specToMerge); + + // Then + Assertions.assertThat(implementation(spec).getQueryParams()).containsOnly(entry("param1", "value1")); + assertThat(implementation(spec).getRestAssuredWebTestClientConfig() + .getJsonConfig().numberReturnType()).isEqualTo(JsonPathConfig.NumberReturnType.FLOAT_AND_DOUBLE); + } + + @Test + public void + logging_is_overwritten_when_defined_in_specification() { + // Given + StringWriter writer = new StringWriter(); + PrintStream captor = new PrintStream(new WriterOutputStream(writer), true); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setConfig(RestAssuredWebTestClientConfig.newConfig() + .logConfig(LogConfig.logConfig().defaultStream(captor))).and().log(LogDetail.ALL).build(); + + // When + RestAssuredWebTestClient.given() + .log().params() + .spec(specToMerge) + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting?name={name}", "Johan") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + // Then + assertThat(writer.toString()).isEqualTo("Request method:\tGET\n" + + "Request URI:\thttp://localhost:8080/greeting?name=Johan\n" + + "Proxy:\t\t\t\n" + + "Request params:\t\n" + + "Query params:\t\n" + + "Form params:\t\n" + + "Path params:\t\n" + + "Headers:\t\t\n" + + "Cookies:\t\t\n" + + "Multiparts:\t\t\n" + + "Body:\t\t\t\n"); + } + + @Test + public void + logging_is_not_overwritten_when_not_defined_in_specification() { + // Given + StringWriter writer = new StringWriter(); + PrintStream captor = new PrintStream(new WriterOutputStream(writer), true); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder() + .setConfig(RestAssuredWebTestClientConfig.newConfig() + .logConfig(LogConfig.logConfig().defaultStream(captor))). + addQueryParam("name", "Johan").build(); + + // When + RestAssuredWebTestClient.given() + .spec(specToMerge) + .log().params() + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)) + .body("content", equalTo("Hello, Johan!")); + + // Then + assertThat(writer.toString()).isEqualTo("Request params:\t\n" + + "Query params:\tname=Johan\n" + + "Form params:\t\n" + + "Path params:\t\n" + + "Multiparts:\t\t\n" + ); + } + + @Test + public void + configurations_are_merged() { + // Given + RestAssuredWebTestClientConfig cfg1 = new RestAssuredWebTestClientConfig() + .with().jsonConfig(jsonConfig() + .with().numberReturnType(JsonPathConfig.NumberReturnType.FLOAT_AND_DOUBLE)); + WebTestClientRequestSpecification specToMerge = new WebTestClientRequestSpecBuilder().setConfig(cfg1).build(); + + // When + RestAssuredWebTestClientConfig cfg2 = new RestAssuredWebTestClientConfig() + .sessionConfig(sessionConfig().sessionIdName("php")); + WebTestClientRequestSpecification spec = RestAssuredWebTestClient.given().config(cfg2).spec(specToMerge); + + // Then + RestAssuredConfig mergedConfig = implementation(spec).getRestAssuredConfig(); + assertThat(mergedConfig.getSessionConfig().sessionIdName()).isEqualTo("php"); + assertThat(mergedConfig.getJsonConfig().numberReturnType()) + .isEqualTo(JsonPathConfig.NumberReturnType.FLOAT_AND_DOUBLE); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientStaticRequestAndResponseSpecTest.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientStaticRequestAndResponseSpecTest.java new file mode 100644 index 000000000..8a54f623e --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/WebTestClientStaticRequestAndResponseSpecTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.module.webtestclient.setup.GreetingController; +import io.restassured.module.webtestclient.specification.WebTestClientRequestSpecBuilder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.hamcrest.Matchers.equalTo; + +public class WebTestClientStaticRequestAndResponseSpecTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void + request_and_response_spec_can_be_defined_statically() { + RestAssuredWebTestClient.requestSpecification = new WebTestClientRequestSpecBuilder() + .addQueryParam("name", "Johan").build(); + RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder() + .expectStatusCode(200).expectBody("content", equalTo("Hello, Johan!")).build(); + + try { + // When + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)); + } finally { + RestAssuredWebTestClient.reset(); + } + } + + @Test + public void + response_validation_fails_if_any_property_in_the_response_is_not_valid() { + RestAssuredWebTestClient.requestSpecification = new WebTestClientRequestSpecBuilder() + .addQueryParam("name", "Johan").build(); + RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder() + .expectStatusCode(200).expectBody("content", equalTo("Hello, John!")).build(); + + exception.expect(AssertionError.class); + exception.expectMessage("1 expectation failed.\n" + + "JSON path content doesn't match.\n" + + "Expected: Hello, John!\n" + + " Actual: Hello, Johan!"); + + try { + // When + RestAssuredWebTestClient.given() + .standaloneSetup(new GreetingController()) + .when() + .get("/greeting") + .then() + .body("id", equalTo(1)); + } finally { + RestAssuredWebTestClient.reset(); + } + } + + @Test + public void + response_validation_kicks_in_even_when_no_then_clause_is_specified() { + RestAssuredWebTestClient.requestSpecification = new WebTestClientRequestSpecBuilder() + .addQueryParam("name", "Johan").build(); + RestAssuredWebTestClient.responseSpecification = new ResponseSpecBuilder() + .expectStatusCode(200).expectBody("content", equalTo("Hello, John!")).build(); + + exception.expect(AssertionError.class); + exception.expectMessage("1 expectation failed.\n" + + "JSON path content doesn't match.\n" + + "Expected: Hello, John!\n" + + " Actual: Hello, Johan!"); + + try { + // When + RestAssuredWebTestClient.given(). + standaloneSetup(new GreetingController()). + when(). + get("/greeting"); + } finally { + RestAssuredWebTestClient.reset(); + } + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/BasePathController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/BasePathController.java new file mode 100644 index 000000000..505a371aa --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/BasePathController.java @@ -0,0 +1,41 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +/** + * This controller has been copied from Spring Guides. + */ +@RestController +public class BasePathController { + + private static final String template = "Hello, %s!"; + + @GetMapping("/my-path/greetingPath") + public Mono greeting(@RequestParam(value = "name", required = false, defaultValue = "World") String name) { + return Mono.just(new Greeting(0, String.format(template, name))); + } + + @GetMapping(value = "/") + public Mono greetingOnBaseEndpoint(@RequestParam(value = "name", required = false, defaultValue = "World") String name) { + return Mono.just(new Greeting(1, String.format(template, name))); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ContentTypeProcessor.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ContentTypeProcessor.java new file mode 100644 index 000000000..d11aaa9d3 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ContentTypeProcessor.java @@ -0,0 +1,41 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; + +public class ContentTypeProcessor { + + public Mono processContentType(ServerRequest request) { + return ServerResponse.ok() + .body(fromObject(new RequestContentTypeWrapper(request.headers().contentType().orElse(MediaType.ALL) + .toString()))); + } +} + +class RequestContentTypeWrapper { + + public String requestContentType; + + public RequestContentTypeWrapper(String requestContentType) { + this.requestContentType = requestContentType; + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieController.java new file mode 100644 index 000000000..74e2c0d7f --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieController.java @@ -0,0 +1,33 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +public class CookieController { + + @RequestMapping(value = "/cookie", produces = APPLICATION_JSON_VALUE) + public Mono cookie(@CookieValue("cookieName1") String cookieValue1, @CookieValue(value = "cookieName2", required = false) String cookieValue2) { + return Mono.just("{\"cookieValue1\" : \"" + cookieValue1 + "\", \"cookieValue2\" : \"" + cookieValue2 + "\"}"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieProcessor.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieProcessor.java new file mode 100644 index 000000000..935d862bf --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/CookieProcessor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseCookie; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class CookieProcessor { + + public Mono processCookies(ServerRequest request) { + MultiValueMap processedResponseCookies = new LinkedMultiValueMap(); + request.queryParams().keySet() + .stream() + .map(queryParamName -> request.queryParams().get(queryParamName).stream() + .map(queryParam -> ResponseCookie.from(queryParamName, queryParam).build()) + .collect(Collectors.toList())) + .flatMap(Collection::stream) + .forEach(processedCookie -> processedResponseCookies.add(processedCookie.getName(), processedCookie)); + + return ServerResponse.ok().cookies( + cookies -> cookies.addAll(processedResponseCookies)).contentType(MediaType.APPLICATION_JSON).build(); + + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/Greeting.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/Greeting.java new file mode 100644 index 000000000..143bc9c9a --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/Greeting.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +/** + * This DTO has been copied from Spring Guides. + */ +public class Greeting { + + private final long id; + private final String content; + + public Greeting(long id, String content) { + this.id = id; + this.content = content; + } + + public long getId() { + return id; + } + + public String getContent() { + return content; + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/GreetingController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/GreetingController.java new file mode 100644 index 000000000..5b553de65 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/GreetingController.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * This controller has been copied from Spring Guides. + */ +@RestController +public class GreetingController { + + private static final String template = "Hello, %s!"; + private final AtomicLong counter = new AtomicLong(); + + @GetMapping(produces = "application/json") + public Mono simpleGreeting() { + ResponseEntity responseEntity = ResponseEntity.ok(new Greeting(counter.incrementAndGet(), + String.format(template, "World"))); + return Mono.justOrEmpty(responseEntity); + } + + @PostMapping(value = "/greeting", consumes = "application/json", produces = "application/json") + public Mono greetingWithRequiredContentType( + @RequestParam(value="name", required=false, defaultValue="World") String name) { + return greeting(name); + } + + @GetMapping(value = "/greeting") + public Mono greeting( + @RequestParam(value="name", required=false, defaultValue="World") String name) { + return Mono.just(new Greeting(counter.incrementAndGet(), String.format(template, name))); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/HeaderController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/HeaderController.java new file mode 100644 index 000000000..2cda6dcd7 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/HeaderController.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +public class HeaderController { + + @GetMapping(value = "/header", produces = APPLICATION_JSON_VALUE) + public Mono header(@RequestHeader("headerName") String headerValue, + @RequestHeader(value = "User-Agent", required = false) String userAgent) { + return Mono.just("{\"headerName\" : \"" + headerValue + "\", \"user-agent\" : \"" + userAgent + "\"}"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/MultiValueController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/MultiValueController.java new file mode 100644 index 000000000..10402519e --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/MultiValueController.java @@ -0,0 +1,46 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import java.util.List; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@RestController +public class MultiValueController { + + @RequestMapping(value = "/multiValueParam", method = {POST, GET}, produces = MediaType.APPLICATION_JSON_VALUE) + public Mono multiValueParam(@RequestParam("list") List listValues) { + return Mono.just("{ \"list\" : \"" + String.join(",", listValues) + "\" }"); + } + + @PostMapping(value = "/threeMultiValueParam", produces = MediaType.APPLICATION_JSON_VALUE) + public Mono threeMultiValueParam(@RequestParam("list") List list1Values, + @RequestParam("list2") List list2Values, + @RequestParam("list3") List list3Values) { + return Mono.just("{ \"list\" : \"" + String.join(",", list1Values) + "\"," + + " \"list2\" : \"" + String.join(",", list2Values) + "\", " + + " \"list3\" : \"" + String.join(",", list3Values) + "\" }"); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ParserController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ParserController.java new file mode 100644 index 000000000..8244f80f3 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ParserController.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class ParserController { + + @GetMapping(value = "/parserWithUnknownContentType", produces = "some/thing") + public Mono parserWithUnknownContentType(@RequestParam(value = "param") String param) { + return Mono.just("{ \"param\" : \"" + param + "\" }"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PostController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PostController.java new file mode 100644 index 000000000..d768eda52 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PostController.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import java.util.concurrent.atomic.AtomicLong; + +import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +public class PostController { + + private static final String template = "Hello, %s!"; + private final AtomicLong counter = new AtomicLong(); + + @PostMapping(value = "/greetingPost", consumes = APPLICATION_FORM_URLENCODED_VALUE) + public Mono greeting(@RequestParam("name") String name) { + return Mono.just(new Greeting(counter.incrementAndGet(), String.format(template, name))); + } + + @PostMapping("/stringBody") + public Mono stringBody(@RequestBody String body) { + return Mono.just(body); + } + + @PostMapping(value = "/jsonReflect", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public Mono jsonReflect(@RequestBody String body) { + return Mono.just(body); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PutController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PutController.java new file mode 100644 index 000000000..dbe75da6c --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/PutController.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import java.util.concurrent.atomic.AtomicLong; + +import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +public class PutController { + + private static final String template = "Hello, %s!"; + private final AtomicLong counter = new AtomicLong(); + + @PutMapping(value = "/greetingPut", consumes = APPLICATION_FORM_URLENCODED_VALUE) + public Mono greeting(@RequestParam("name") String name) { + return Mono.just(new Greeting(counter.incrementAndGet(), String.format(template, name))); + } + + @PutMapping("/stringBody") + public Mono stringBody(@RequestBody String body) { + return Mono.just(body); + } + + @PutMapping(value = "/jsonReflect", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public Mono jsonReflect(@RequestBody String body) { + return Mono.just(body); + } +} \ No newline at end of file diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/QueryParamsProcessor.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/QueryParamsProcessor.java new file mode 100644 index 000000000..7b4c955dd --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/QueryParamsProcessor.java @@ -0,0 +1,35 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +public class QueryParamsProcessor { + + private static final String template = "Hello, %s!"; + + public Mono processQueryParams(ServerRequest serverRequest) { + return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON) + .header("test", "test") + .syncBody("{ \"name\" : \"" + String.format(template, + serverRequest.queryParams().getFirst("name")) + "\"," + + " \"message\" : \"" + serverRequest.queryParams().getFirst("message") + "\", " + + " \"_link\" : \"" + serverRequest.uri() + "\" }"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/RedirectController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/RedirectController.java new file mode 100644 index 000000000..4ffb557fc --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/RedirectController.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@RestController +public class RedirectController { + + @RequestMapping(value = "/redirect", method = GET, produces = APPLICATION_JSON_VALUE) + public ResponseEntity redirect() { + return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY) + .header("Location", "http://localhost:8080/redirect/1") + .body("{ \"id\" : 1 }"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ResponseAwareMatcherController.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ResponseAwareMatcherController.java new file mode 100644 index 000000000..d141d31dc --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/ResponseAwareMatcherController.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@RestController +public class ResponseAwareMatcherController { + + @GetMapping(value = "/responseAware", produces = APPLICATION_JSON_VALUE) + public Mono parserWithUnknownContentType() { + return Mono.just("{\n" + + " \"playerOneId\":\"a084a81a-6bc9-418d-b107-5cb5ce249b77\",\n" + + " \"playerTwoId\":\"88867e23-0b38-4c43-ad8e-161ba5062c7d\",\n" + + " \"status\":\"ongoing\",\n" + + " \"rounds\":[\n" + + "\n" + + " ],\n" + + " \"_links\":{\n" + + " \"self\":{\n" + + " \"href\":\"http://localhost:8080/2dd68f2d-37df-4eed-9fce-5d9ce23a6745\"\n" + + " },\n" + + " \"make-move\":{\n" + + " \"href\":\"http://localhost:8080/2dd68f2d-37df-4eed-9fce-5d9ce23a6745/make-move\"\n" + + " }\n" + + " },\n" + + " \"id\":\"2dd68f2d-37df-4eed-9fce-5d9ce23a6745\"\n" + + " }"); + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/SecuredProcessor.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/SecuredProcessor.java new file mode 100644 index 000000000..a57a18450 --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/SecuredProcessor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018 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 + * + * 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 io.restassured.module.webtestclient.setup; + +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +public class SecuredProcessor { + + public Mono processSecuredRequest(ServerRequest serverRequest) { + String auth = serverRequest.headers().header("Authorization").get(0); + return ServerResponse.ok().syncBody(new AuthWrapper(auth)); + } +} + +class AuthWrapper { + + public String auth; + + public AuthWrapper(String auth) { + this.auth = auth; + } +} diff --git a/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/support/Greeting.java b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/support/Greeting.java new file mode 100644 index 000000000..5ccf117db --- /dev/null +++ b/modules/spring-web-test-client/src/test/java/io/restassured/module/webtestclient/setup/support/Greeting.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.module.webtestclient.setup.support; + +import org.junit.Ignore; + +@Ignore +public class Greeting { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Greeting greeting = (Greeting) o; + + if (firstName != null ? !firstName.equals(greeting.firstName) : greeting.firstName != null) return false; + if (lastName != null ? !lastName.equals(greeting.lastName) : greeting.lastName != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = firstName != null ? firstName.hashCode() : 0; + result = 31 * result + (lastName != null ? lastName.hashCode() : 0); + return result; + } +} + diff --git a/rest-assured/src/main/groovy/io/restassured/internal/multipart/MultiPartInternal.groovy b/rest-assured/src/main/groovy/io/restassured/internal/multipart/MultiPartInternal.groovy index aa13cdaef..bb8be1af7 100644 --- a/rest-assured/src/main/groovy/io/restassured/internal/multipart/MultiPartInternal.groovy +++ b/rest-assured/src/main/groovy/io/restassured/internal/multipart/MultiPartInternal.groovy @@ -15,15 +15,18 @@ */ package io.restassured.internal.multipart +import java.nio.charset.Charset + +import groovy.transform.Canonical import io.restassured.internal.NoParameterValue import org.apache.http.entity.mime.content.FileBody import org.apache.http.entity.mime.content.InputStreamBody import org.apache.http.entity.mime.content.StringBody -import java.nio.charset.Charset - +@Canonical class MultiPartInternal { - private static final String OCTET_STREAM = "application/octet-stream" + + public static final String OCTET_STREAM = "application/octet-stream" private static final String TEXT_PLAIN = "text/plain" def content diff --git a/rest-assured/src/main/java/io/restassured/filter/log/RequestLoggingFilter.java b/rest-assured/src/main/java/io/restassured/filter/log/RequestLoggingFilter.java index 73f896856..039ec6c9d 100644 --- a/rest-assured/src/main/java/io/restassured/filter/log/RequestLoggingFilter.java +++ b/rest-assured/src/main/java/io/restassured/filter/log/RequestLoggingFilter.java @@ -25,8 +25,6 @@ import org.apache.commons.lang3.Validate; import java.io.PrintStream; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; import java.nio.charset.Charset; import static io.restassured.filter.log.LogDetail.ALL; @@ -117,7 +115,7 @@ public RequestLoggingFilter(LogDetail logDetail, boolean shouldPrettyPrint, Prin public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, FilterContext ctx) { String uri = requestSpec.getURI(); if (!showUrlEncodedUri) { - uri = urlDecode(uri, Charset.forName(requestSpec.getConfig().getEncoderConfig().defaultQueryParameterCharset()), true); + uri = UrlDecoder.urlDecode(uri, Charset.forName(requestSpec.getConfig().getEncoderConfig().defaultQueryParameterCharset()), true); } RequestPrinter.print(requestSpec, requestSpec.getMethod(), uri, logDetail, stream, shouldPrettyPrint); @@ -134,44 +132,4 @@ public static RequestLoggingFilter logRequestTo(PrintStream stream) { return new RequestLoggingFilter(stream); } - // Copy of the private method in URLEncodedUtils - - /** - * Decode/unescape a portion of a URL, to use with the query part ensure {@code plusAsBlank} is true. - * - * @param content the portion to decode - * @param charset the charset to use - * @param plusAsBlank if {@code true}, then convert '+' to space (e.g. for www-url-form-encoded content), otherwise leave as is. - * @return encoded string - */ - private static String urlDecode(final String content, final Charset charset, final boolean plusAsBlank) { - if (content == null) { - return null; - } - final ByteBuffer bb = ByteBuffer.allocate(content.length()); - final CharBuffer cb = CharBuffer.wrap(content); - while (cb.hasRemaining()) { - final char c = cb.get(); - if (c == '%' && cb.remaining() >= 2) { - final char uc = cb.get(); - final char lc = cb.get(); - final int u = Character.digit(uc, 16); - final int l = Character.digit(lc, 16); - if (u != -1 && l != -1) { - bb.put((byte) ((u << 4) + l)); - } else { - bb.put((byte) '%'); - bb.put((byte) uc); - bb.put((byte) lc); - } - } else if (plusAsBlank && c == '+') { - bb.put((byte) ' '); - } else { - bb.put((byte) c); - } - } - bb.flip(); - return charset.decode(bb).toString(); - } - } diff --git a/rest-assured/src/main/java/io/restassured/filter/log/UrlDecoder.java b/rest-assured/src/main/java/io/restassured/filter/log/UrlDecoder.java new file mode 100644 index 000000000..f0a227553 --- /dev/null +++ b/rest-assured/src/main/java/io/restassured/filter/log/UrlDecoder.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016-2018 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 + * + * 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 io.restassured.filter.log; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; + +public class UrlDecoder { + + private UrlDecoder() { + } + + // Copy of the private method in URLEncodedUtils + + /** + * Decode/unescape a portion of a URL, to use with the query part ensure {@code plusAsBlank} is true. + * + * @param content the portion to decode + * @param charset the charset to use + * @param plusAsBlank if {@code true}, then convert '+' to space (e.g. for www-url-form-encoded content), otherwise leave as is. + * @return encoded string + */ + public static String urlDecode(final String content, final Charset charset, final boolean plusAsBlank) { + if (content == null) { + return null; + } + final ByteBuffer bb = ByteBuffer.allocate(content.length()); + final CharBuffer cb = CharBuffer.wrap(content); + while (cb.hasRemaining()) { + final char c = cb.get(); + if (c == '%' && cb.remaining() >= 2) { + final char uc = cb.get(); + final char lc = cb.get(); + final int u = Character.digit(uc, 16); + final int l = Character.digit(lc, 16); + if (u != -1 && l != -1) { + bb.put((byte) ((u << 4) + l)); + } else { + bb.put((byte) '%'); + bb.put((byte) uc); + bb.put((byte) lc); + } + } else if (plusAsBlank && c == '+') { + bb.put((byte) ' '); + } else { + bb.put((byte) c); + } + } + bb.flip(); + return charset.decode(bb).toString(); + } + +}