diff --git a/build.gradle b/build.gradle index b18f28f6..b675c6c2 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7' classpath 'io.spring.gradle:spring-io-plugin:0.0.6.RELEASE' - classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:1.2' + classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.2.1' } configurations.classpath.resolutionStrategy.eachDependency { if (it.requested.name == 'dependency-management-plugin') { @@ -71,6 +71,7 @@ subprojects { dependency 'javax.servlet:javax.servlet-api:3.1.0' dependency 'javax.validation:validation-api:1.1.0.Final' dependency 'junit:junit:4.12' + dependency 'io.rest-assured:rest-assured:3.0.2' dependency 'org.asciidoctor:asciidoctorj:1.5.3.1' dependency 'org.hamcrest:hamcrest-core:1.3' dependency 'org.hamcrest:hamcrest-library:1.3' diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 061bb501..2809588f 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -73,7 +73,7 @@ + value="com.jayway.restassured.RestAssured.*, io.restassured.RestAssured.*, org.junit.Assert.*, org.junit.Assume.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.springframework.restdocs.cli.CliDocumentation.*, org.springframework.restdocs.headers.HeaderDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.IterableEnumeration.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*, org.springframework.restdocs.payload.PayloadDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.restassured.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.snippet.Attributes.*, org.springframework.restdocs.templates.TemplateFormats.*, org.springframework.restdocs.test.SnippetMatchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*" /> diff --git a/docs/build.gradle b/docs/build.gradle index a8c7706c..ce165dba 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -5,6 +5,7 @@ plugins { dependencies { testCompile project(':spring-restdocs-mockmvc') testCompile project(':spring-restdocs-restassured') + testCompile 'io.rest-assured:rest-assured' testCompile 'javax.validation:validation-api' testCompile 'junit:junit' testCompile 'org.testng:testng:6.9.10' diff --git a/docs/src/docs/asciidoc/getting-started.adoc b/docs/src/docs/asciidoc/getting-started.adoc index 1b72d5f0..a0413453 100644 --- a/docs/src/docs/asciidoc/getting-started.adoc +++ b/docs/src/docs/asciidoc/getting-started.adoc @@ -73,7 +73,8 @@ Spring REST Docs has the following minimum requirements: Additionally, the `spring-restdocs-restassured` module has the following minimum requirements: -- REST Assured 2.8 +- REST Assured 2.8 (`com.jayway.restassured:restassured`) or REST Assured 3.0 + (`io.rest-assured:rest-assured`) [[getting-started-build-configuration]] === Build configuration @@ -135,7 +136,8 @@ the configuration are described below. ---- <1> Add a dependency on `spring-restdocs-mockmvc` in the `test` scope. If you want to use REST Assured rather than MockMvc, add a dependency on `spring-restdocs-restassured` - instead. + and `com.jayway.restassured:restassured` (REST Assured 2) or + `io.rest-assured:rest-assured` (REST Assured 3) instead. <2> Add the SureFire plugin and configure it to include files whose names end with `Documentation.java`. <3> Add the Asciidoctor plugin. @@ -178,7 +180,8 @@ the configuration are described below. `operation` block macro. <3> Add a dependency on `spring-restdocs-mockmvc` in the `testCompile` configuration. If you want to use REST Assured rather than MockMvc, add a dependency on - `spring-restdocs-restassured` instead. + `spring-restdocs-restassured` and `com.jayway.restassured:restassured` (REST Assured + 2) or `io.rest-assured:rest-assured` (REST Assured 3) instead. <4> Configure a property to define the output location for generated snippets. <5> Configure the `test` task to add the snippets directory as an output. <6> Configure the `asciidoctor` task @@ -326,8 +329,9 @@ include::{examples-dir}/com/example/restassured/ExampleApplicationTests.java[tag ---- <1> REST Assured is configured by adding a `RestAssuredRestDocumentationConfigurer` as a `Filter`. An instance of this class can be obtained from the static -`documentationConfiguration()` method on -`org.springframework.restdocs.restassured.RestAssuredRestDocumentation`. +`documentationConfiguration()` method on `RestAssuredRestDocumentation` in the +`org.springframework.restdocs.restassured` or `org.springframework.restdocs.restassured3` +package depending on the version of REST Assured that you are using. The configurer applies sensible defaults and also provides an API for customizing the configuration. Refer to the <> for more information. @@ -403,8 +407,9 @@ include::{examples-dir}/com/example/restassured/InvokeService.java[tags=invoke-s <3> Document the call to the service, writing the snippets into a directory named `index` that will be located beneath the configured output directory. The snippets are written by a `RestDocumentationFilter`. An instance of this class can be obtained from the -static `document` method on -`org.springframework.restdocs.restassured.RestAssuredRestDocumentation`. +static `document` method on `RestAssuredRestDocumentation` in the +`org.springframework.restdocs.restassured` or `org.springframework.restdocs.restassured3` +package depending on the version of REST Assured that you are using. <4> Invoke the root (`/`) of the service. <5> Assert that the service produce the expected response. diff --git a/docs/src/docs/asciidoc/introduction.adoc b/docs/src/docs/asciidoc/introduction.adoc index 7a6fde22..c1d36bb0 100644 --- a/docs/src/docs/asciidoc/introduction.adoc +++ b/docs/src/docs/asciidoc/introduction.adoc @@ -12,9 +12,9 @@ can also be configured to use Markdown. Spring REST Docs makes use of snippets produced by tests written with {spring-framework-docs}/#spring-mvc-test-framework[Spring MVC Test] or -http://www.rest-assured.io[REST Assured]. This test-driven approach helps to guarantee the -accuracy of your service's documentation. If a snippet is incorrect the test that produces -it will fail. +http://www.rest-assured.io[REST Assured] 2 and 3. This test-driven approach helps to +guarantee the accuracy of your service's documentation. If a snippet is incorrect the +test that produces it will fail. Documenting a RESTful service is largely about describing its resources. Two key parts of each resource's description are the details of the HTTP requests that it consumes diff --git a/docs/src/test/java/com/example/restassured/CustomDefaultSnippets.java b/docs/src/test/java/com/example/restassured/CustomDefaultSnippets.java index 39544db0..75180675 100644 --- a/docs/src/test/java/com/example/restassured/CustomDefaultSnippets.java +++ b/docs/src/test/java/com/example/restassured/CustomDefaultSnippets.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,15 +16,15 @@ package com.example.restassured; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; import org.springframework.restdocs.JUnitRestDocumentation; import static org.springframework.restdocs.cli.CliDocumentation.curlRequest; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class CustomDefaultSnippets { diff --git a/docs/src/test/java/com/example/restassured/CustomEncoding.java b/docs/src/test/java/com/example/restassured/CustomEncoding.java index caa2d623..58f9feea 100644 --- a/docs/src/test/java/com/example/restassured/CustomEncoding.java +++ b/docs/src/test/java/com/example/restassured/CustomEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,14 +16,14 @@ package com.example.restassured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; + import org.springframework.restdocs.JUnitRestDocumentation; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; - -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class CustomEncoding { diff --git a/docs/src/test/java/com/example/restassured/CustomFormat.java b/docs/src/test/java/com/example/restassured/CustomFormat.java index 8f6cf4ab..db7ccce3 100644 --- a/docs/src/test/java/com/example/restassured/CustomFormat.java +++ b/docs/src/test/java/com/example/restassured/CustomFormat.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,21 +16,21 @@ package com.example.restassured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; + import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.restdocs.templates.TemplateFormats; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; - -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class CustomFormat { @Rule public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); - + @SuppressWarnings("unused") private RequestSpecification spec; diff --git a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java index c31cf228..e280fe45 100644 --- a/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java +++ b/docs/src/test/java/com/example/restassured/EveryTestPreprocessing.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,14 +16,14 @@ package com.example.restassured; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; -import org.springframework.restdocs.JUnitRestDocumentation; -import org.springframework.restdocs.restassured.RestDocumentationFilter; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.restdocs.restassured3.RestDocumentationFilter; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; @@ -32,8 +32,8 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.pr import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class EveryTestPreprocessing { diff --git a/docs/src/test/java/com/example/restassured/ExampleApplicationTestNgTests.java b/docs/src/test/java/com/example/restassured/ExampleApplicationTestNgTests.java index aa91cd4e..741c6b36 100644 --- a/docs/src/test/java/com/example/restassured/ExampleApplicationTestNgTests.java +++ b/docs/src/test/java/com/example/restassured/ExampleApplicationTestNgTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -18,14 +18,14 @@ package com.example.restassured; import java.lang.reflect.Method; -import org.springframework.restdocs.ManualRestDocumentation; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; +import org.springframework.restdocs.ManualRestDocumentation; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class ExampleApplicationTestNgTests { diff --git a/docs/src/test/java/com/example/restassured/ExampleApplicationTests.java b/docs/src/test/java/com/example/restassured/ExampleApplicationTests.java index 7133906c..86d2576b 100644 --- a/docs/src/test/java/com/example/restassured/ExampleApplicationTests.java +++ b/docs/src/test/java/com/example/restassured/ExampleApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,14 +16,14 @@ package com.example.restassured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; + import org.springframework.restdocs.JUnitRestDocumentation; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; - -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class ExampleApplicationTests { diff --git a/docs/src/test/java/com/example/restassured/HttpHeaders.java b/docs/src/test/java/com/example/restassured/HttpHeaders.java index 2556be02..91c56b2d 100644 --- a/docs/src/test/java/com/example/restassured/HttpHeaders.java +++ b/docs/src/test/java/com/example/restassured/HttpHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,14 +16,14 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class HttpHeaders { diff --git a/docs/src/test/java/com/example/restassured/Hypermedia.java b/docs/src/test/java/com/example/restassured/Hypermedia.java index 2922377d..de1face1 100644 --- a/docs/src/test/java/com/example/restassured/Hypermedia.java +++ b/docs/src/test/java/com/example/restassured/Hypermedia.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,14 +16,14 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.halLinks; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class Hypermedia { diff --git a/docs/src/test/java/com/example/restassured/InvokeService.java b/docs/src/test/java/com/example/restassured/InvokeService.java index 347c368e..ebb0073d 100644 --- a/docs/src/test/java/com/example/restassured/InvokeService.java +++ b/docs/src/test/java/com/example/restassured/InvokeService.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,11 +16,11 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class InvokeService { diff --git a/docs/src/test/java/com/example/restassured/ParameterizedOutput.java b/docs/src/test/java/com/example/restassured/ParameterizedOutput.java index e5f2ce47..d0f85503 100644 --- a/docs/src/test/java/com/example/restassured/ParameterizedOutput.java +++ b/docs/src/test/java/com/example/restassured/ParameterizedOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,15 +16,15 @@ package com.example.restassured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.Rule; + import org.springframework.restdocs.JUnitRestDocumentation; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; - -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; public class ParameterizedOutput { diff --git a/docs/src/test/java/com/example/restassured/PathParameters.java b/docs/src/test/java/com/example/restassured/PathParameters.java index 81c7cc3e..18b36965 100644 --- a/docs/src/test/java/com/example/restassured/PathParameters.java +++ b/docs/src/test/java/com/example/restassured/PathParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,13 +16,13 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class PathParameters { diff --git a/docs/src/test/java/com/example/restassured/Payload.java b/docs/src/test/java/com/example/restassured/Payload.java index b538acbb..35e8d58b 100644 --- a/docs/src/test/java/com/example/restassured/Payload.java +++ b/docs/src/test/java/com/example/restassured/Payload.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,12 +16,12 @@ package com.example.restassured; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; + import org.springframework.restdocs.payload.FieldDescriptor; import org.springframework.restdocs.payload.JsonFieldType; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; - import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -29,7 +29,7 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.requestF import static org.springframework.restdocs.payload.PayloadDocumentation.responseBody; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; import static org.springframework.restdocs.snippet.Attributes.attributes; import static org.springframework.restdocs.snippet.Attributes.key; diff --git a/docs/src/test/java/com/example/restassured/PerTestPreprocessing.java b/docs/src/test/java/com/example/restassured/PerTestPreprocessing.java index 69f4936e..dcb7c91a 100644 --- a/docs/src/test/java/com/example/restassured/PerTestPreprocessing.java +++ b/docs/src/test/java/com/example/restassured/PerTestPreprocessing.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,16 +16,15 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; - import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class PerTestPreprocessing { @@ -38,7 +37,7 @@ public class PerTestPreprocessing { preprocessResponse(prettyPrint()))) // <2> .when().get("/") .then().assertThat().statusCode(is(200)); - // end::preprocessing[] + // end::preprocessing[] } } diff --git a/docs/src/test/java/com/example/restassured/RequestParameters.java b/docs/src/test/java/com/example/restassured/RequestParameters.java index 86f40c4b..19333fb9 100644 --- a/docs/src/test/java/com/example/restassured/RequestParameters.java +++ b/docs/src/test/java/com/example/restassured/RequestParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,13 +16,13 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class RequestParameters { diff --git a/docs/src/test/java/com/example/restassured/RequestPartPayload.java b/docs/src/test/java/com/example/restassured/RequestPartPayload.java index ec83908e..d3e3db60 100644 --- a/docs/src/test/java/com/example/restassured/RequestPartPayload.java +++ b/docs/src/test/java/com/example/restassured/RequestPartPayload.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -20,14 +20,14 @@ import java.io.File; import java.util.HashMap; import java.util.Map; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.requestPartBody; import static org.springframework.restdocs.payload.PayloadDocumentation.requestPartFields; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class RequestPartPayload { diff --git a/docs/src/test/java/com/example/restassured/RequestParts.java b/docs/src/test/java/com/example/restassured/RequestParts.java index c6a3f8c1..37808103 100644 --- a/docs/src/test/java/com/example/restassured/RequestParts.java +++ b/docs/src/test/java/com/example/restassured/RequestParts.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,13 +16,13 @@ package com.example.restassured; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.request.RequestDocumentation.partWithName; import static org.springframework.restdocs.request.RequestDocumentation.requestParts; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class RequestParts { diff --git a/docs/src/test/java/com/example/restassured/RestAssuredSnippetReuse.java b/docs/src/test/java/com/example/restassured/RestAssuredSnippetReuse.java index 770ed482..3ba16b19 100644 --- a/docs/src/test/java/com/example/restassured/RestAssuredSnippetReuse.java +++ b/docs/src/test/java/com/example/restassured/RestAssuredSnippetReuse.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -17,13 +17,12 @@ package com.example.restassured; import com.example.SnippetReuse; -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.specification.RequestSpecification; - +import io.restassured.RestAssured; +import io.restassured.specification.RequestSpecification; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; public class RestAssuredSnippetReuse extends SnippetReuse { diff --git a/samples/rest-assured/build.gradle b/samples/rest-assured/build.gradle index a55dd6b1..73041777 100644 --- a/samples/rest-assured/build.gradle +++ b/samples/rest-assured/build.gradle @@ -34,6 +34,7 @@ ext['spring-restdocs.version'] = '1.2.0.BUILD-SNAPSHOT' dependencies { compile 'org.springframework.boot:spring-boot-starter-web' + testCompile 'io.rest-assured:rest-assured:3.0.2' testCompile 'org.springframework.boot:spring-boot-starter-test' testCompile 'org.springframework.restdocs:spring-restdocs-restassured' asciidoctor "org.springframework.restdocs:spring-restdocs-asciidoctor:${project.ext['spring-restdocs.version']}" diff --git a/samples/rest-assured/src/test/java/com/example/restassured/SampleRestAssuredApplicationTests.java b/samples/rest-assured/src/test/java/com/example/restassured/SampleRestAssuredApplicationTests.java index c1c4de79..654ab82b 100644 --- a/samples/rest-assured/src/test/java/com/example/restassured/SampleRestAssuredApplicationTests.java +++ b/samples/rest-assured/src/test/java/com/example/restassured/SampleRestAssuredApplicationTests.java @@ -16,12 +16,12 @@ package com.example.restassured; -import static com.jayway.restassured.RestAssured.given; +import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; -import static org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.modifyUris; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris; import org.junit.Before; import org.junit.Rule; @@ -33,8 +33,8 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.jayway.restassured.builder.RequestSpecBuilder; -import com.jayway.restassured.specification.RequestSpecification; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) @RunWith(SpringJUnit4ClassRunner.class) diff --git a/samples/rest-notes-grails/build.gradle b/samples/rest-notes-grails/build.gradle index c0bce855..fc3d95ec 100644 --- a/samples/rest-notes-grails/build.gradle +++ b/samples/rest-notes-grails/build.gradle @@ -73,6 +73,7 @@ dependencies { runtime "com.h2database:h2" + testCompile "io.rest-assured:rest-assured:3.0.2" testCompile "org.grails:grails-plugin-testing" testCompile "org.grails.plugins:geb" testCompile "org.grails:grails-datastore-rest-client" diff --git a/samples/rest-notes-grails/src/integration-test/groovy/com/example/ApiDocumentationSpec.groovy b/samples/rest-notes-grails/src/integration-test/groovy/com/example/ApiDocumentationSpec.groovy index 2e15d73b..b29d51b3 100644 --- a/samples/rest-notes-grails/src/integration-test/groovy/com/example/ApiDocumentationSpec.groovy +++ b/samples/rest-notes-grails/src/integration-test/groovy/com/example/ApiDocumentationSpec.groovy @@ -18,7 +18,7 @@ package com.example import org.springframework.restdocs.payload.JsonFieldType -import static com.jayway.restassured.RestAssured.given +import static io.restassured.RestAssured.given import static org.hamcrest.CoreMatchers.is import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse @@ -27,12 +27,12 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath -import static org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.modifyUris -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration +import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration -import com.jayway.restassured.builder.RequestSpecBuilder -import com.jayway.restassured.specification.RequestSpecification +import io.restassured.builder.RequestSpecBuilder +import io.restassured.specification.RequestSpecification import grails.test.mixin.integration.Integration import grails.transaction.Rollback import org.junit.Rule diff --git a/spring-restdocs-restassured/build.gradle b/spring-restdocs-restassured/build.gradle index 558bdb21..68beb38f 100644 --- a/spring-restdocs-restassured/build.gradle +++ b/spring-restdocs-restassured/build.gradle @@ -2,8 +2,11 @@ description = 'Spring REST Docs REST Assured' dependencies { compile project(':spring-restdocs-core') - compile 'com.jayway.restassured:rest-assured' + compileOnly 'com.jayway.restassured:rest-assured' + compileOnly 'io.rest-assured:rest-assured' + testCompile 'com.jayway.restassured:rest-assured' + testCompile 'io.rest-assured:rest-assured' testCompile 'org.apache.tomcat.embed:tomcat-embed-core:8.5.11' testCompile 'org.mockito:mockito-core' testCompile 'org.hamcrest:hamcrest-library' diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentation.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentation.java index 2cb6b4fa..f9c62eb6 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentation.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentation.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -27,7 +27,10 @@ import org.springframework.restdocs.snippet.Snippet; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated Since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.RestAssuredRestDocumentation} */ +@Deprecated public abstract class RestAssuredRestDocumentation { private static final RestAssuredRequestConverter REQUEST_CONVERTER = new RestAssuredRequestConverter(); diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurer.java index 6e64aa6f..bd14e394 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurer.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -34,7 +34,10 @@ import org.springframework.restdocs.config.RestDocumentationConfigurer; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.RestAssuredRestDocumentationConfigurer} */ +@Deprecated public final class RestAssuredRestDocumentationConfigurer extends RestDocumentationConfigurer implements Filter { diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredSnippetConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredSnippetConfigurer.java index 3e1f5dee..ed850bd9 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredSnippetConfigurer.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredSnippetConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -30,7 +30,10 @@ import org.springframework.restdocs.config.SnippetConfigurer; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.RestAssuredSnippetConfigurer} */ +@Deprecated public final class RestAssuredSnippetConfigurer extends SnippetConfigurer implements Filter { diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestDocumentationFilter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestDocumentationFilter.java index 97387058..f46f76de 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestDocumentationFilter.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestDocumentationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -35,7 +35,10 @@ import org.springframework.util.Assert; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.RestDocumentationFilter} */ +@Deprecated public class RestDocumentationFilter implements Filter { static final String CONTEXT_KEY_CONFIGURATION = "org.springframework.restdocs.configuration"; diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/RestAssuredPreprocessors.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/RestAssuredPreprocessors.java index b124544c..6689333c 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/RestAssuredPreprocessors.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/RestAssuredPreprocessors.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -29,7 +29,10 @@ import org.springframework.restdocs.operation.OperationResponse; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors} */ +@Deprecated public abstract class RestAssuredPreprocessors { private RestAssuredPreprocessors() { diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessor.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessor.java index 60972943..6819fcf8 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessor.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -55,7 +55,10 @@ import org.springframework.web.util.UriComponentsBuilder; * * @author Andy Wilkinson * @since 1.1.0 + * @deprecated since 1.2.0 in favor of + * {@link org.springframework.restdocs.restassured3.operation.preprocess.UriModifyingOperationPreprocessor} */ +@Deprecated public final class UriModifyingOperationPreprocessor implements OperationPreprocessor { private final UriModifyingContentModifier contentModifier = new UriModifyingContentModifier(); diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverter.java new file mode 100644 index 00000000..f44dabbf --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverter.java @@ -0,0 +1,161 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; + +import io.restassured.http.Cookie; +import io.restassured.http.Header; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.MultiPartSpecification; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; +import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.OperationRequestPartFactory; +import org.springframework.restdocs.operation.Parameters; +import org.springframework.restdocs.operation.RequestConverter; +import org.springframework.restdocs.operation.RequestCookie; +import org.springframework.util.FileCopyUtils; +import org.springframework.util.StreamUtils; + +/** + * A converter for creating an {@link OperationRequest} from a REST Assured + * {@link FilterableRequestSpecification}. + * + * @author Andy Wilkinson + */ +class RestAssuredRequestConverter + implements RequestConverter { + + @Override + public OperationRequest convert(FilterableRequestSpecification requestSpec) { + return new OperationRequestFactory().create(URI.create(requestSpec.getURI()), + HttpMethod.valueOf(requestSpec.getMethod()), extractContent(requestSpec), + extractHeaders(requestSpec), extractParameters(requestSpec), + extractParts(requestSpec), extractCookies(requestSpec)); + } + + private Collection extractCookies( + FilterableRequestSpecification requestSpec) { + Collection cookies = new ArrayList<>(); + for (Cookie cookie : requestSpec.getCookies()) { + cookies.add(new RequestCookie(cookie.getName(), cookie.getValue())); + } + return cookies; + } + + private byte[] extractContent(FilterableRequestSpecification requestSpec) { + return convertContent(requestSpec.getBody()); + } + + private byte[] convertContent(Object content) { + if (content instanceof String) { + return ((String) content).getBytes(); + } + else if (content instanceof byte[]) { + return (byte[]) content; + } + else if (content instanceof File) { + return copyToByteArray((File) content); + } + else if (content instanceof InputStream) { + return copyToByteArray((InputStream) content); + } + else if (content == null) { + return new byte[0]; + } + else { + throw new IllegalStateException( + "Unsupported request content: " + content.getClass().getName()); + } + } + + private byte[] copyToByteArray(File file) { + try { + return FileCopyUtils.copyToByteArray(file); + } + catch (IOException ex) { + throw new IllegalStateException("Failed to read content from file " + file, + ex); + } + } + + private byte[] copyToByteArray(InputStream inputStream) { + try { + inputStream.reset(); + } + catch (IOException ex) { + throw new IllegalStateException("Cannot read content from input stream " + + inputStream + " due to reset() failure"); + } + try { + return StreamUtils.copyToByteArray(inputStream); + } + catch (IOException ex) { + throw new IllegalStateException( + "Failed to read content from input stream " + inputStream, ex); + } + } + + private HttpHeaders extractHeaders(FilterableRequestSpecification requestSpec) { + HttpHeaders httpHeaders = new HttpHeaders(); + for (Header header : requestSpec.getHeaders()) { + httpHeaders.add(header.getName(), header.getValue()); + } + return httpHeaders; + } + + private Parameters extractParameters(FilterableRequestSpecification requestSpec) { + Parameters parameters = new Parameters(); + for (Entry entry : requestSpec.getQueryParams().entrySet()) { + parameters.add(entry.getKey(), entry.getValue().toString()); + } + for (Entry entry : requestSpec.getRequestParams().entrySet()) { + parameters.add(entry.getKey(), entry.getValue().toString()); + } + for (Entry entry : requestSpec.getFormParams().entrySet()) { + parameters.add(entry.getKey(), entry.getValue().toString()); + } + return parameters; + } + + private Collection extractParts( + FilterableRequestSpecification requestSpec) { + List parts = new ArrayList<>(); + for (MultiPartSpecification multiPartSpec : requestSpec.getMultiPartParams()) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType( + multiPartSpec.getMimeType() == null ? MediaType.TEXT_PLAIN + : MediaType.parseMediaType(multiPartSpec.getMimeType())); + parts.add(new OperationRequestPartFactory().create( + multiPartSpec.getControlName(), multiPartSpec.getFileName(), + convertContent(multiPartSpec.getContent()), headers)); + } + return parts; + } +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredResponseConverter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredResponseConverter.java new file mode 100644 index 00000000..e93263d9 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredResponseConverter.java @@ -0,0 +1,55 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import io.restassured.http.Header; +import io.restassured.response.Response; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; +import org.springframework.restdocs.operation.ResponseConverter; + +/** + * A converter for creating an {@link OperationResponse} from a REST Assured + * {@link Response}. + * + * @author Andy Wilkinson + */ +class RestAssuredResponseConverter implements ResponseConverter { + + @Override + public OperationResponse convert(Response response) { + return new OperationResponseFactory().create( + HttpStatus.valueOf(response.getStatusCode()), extractHeaders(response), + extractContent(response)); + } + + private HttpHeaders extractHeaders(Response response) { + HttpHeaders httpHeaders = new HttpHeaders(); + for (Header header : response.getHeaders()) { + httpHeaders.add(header.getName(), header.getValue()); + } + return httpHeaders; + } + + private byte[] extractContent(Response response) { + return response.getBody().asByteArray(); + } + +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentation.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentation.java new file mode 100644 index 00000000..65beb5a4 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentation.java @@ -0,0 +1,119 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.generate.RestDocumentationGenerator; +import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor; +import org.springframework.restdocs.snippet.Snippet; + +/** + * Static factory methods for documenting RESTful APIs using REST Assured 3. + * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public abstract class RestAssuredRestDocumentation { + + private static final RestAssuredRequestConverter REQUEST_CONVERTER = new RestAssuredRequestConverter(); + + private static final RestAssuredResponseConverter RESPONSE_CONVERTER = new RestAssuredResponseConverter(); + + private RestAssuredRestDocumentation() { + + } + + /** + * Documents the API call with the given {@code identifier} using the given + * {@code snippets}. + * + * @param identifier an identifier for the API call that is being documented + * @param snippets the snippets that will document the API call + * @return a {@link RestDocumentationFilter} that will produce the documentation + */ + public static RestDocumentationFilter document(String identifier, + Snippet... snippets) { + return new RestDocumentationFilter(new RestDocumentationGenerator<>(identifier, + REQUEST_CONVERTER, RESPONSE_CONVERTER, snippets)); + } + + /** + * Documents the API call with the given {@code identifier} using the given + * {@code snippets} in addition to any default snippets. The given + * {@code requestPreprocessor} is applied to the request before it is documented. + * + * @param identifier an identifier for the API call that is being documented + * @param requestPreprocessor the request preprocessor + * @param snippets the snippets + * @return a {@link RestDocumentationFilter} that will produce the documentation + */ + public static RestDocumentationFilter document(String identifier, + OperationRequestPreprocessor requestPreprocessor, Snippet... snippets) { + return new RestDocumentationFilter(new RestDocumentationGenerator<>(identifier, + REQUEST_CONVERTER, RESPONSE_CONVERTER, requestPreprocessor, snippets)); + } + + /** + * Documents the API call with the given {@code identifier} using the given + * {@code snippets} in addition to any default snippets. The given + * {@code responsePreprocessor} is applied to the request before it is documented. + * + * @param identifier an identifier for the API call that is being documented + * @param responsePreprocessor the response preprocessor + * @param snippets the snippets + * @return a {@link RestDocumentationFilter} that will produce the documentation + */ + public static RestDocumentationFilter document(String identifier, + OperationResponsePreprocessor responsePreprocessor, Snippet... snippets) { + return new RestDocumentationFilter(new RestDocumentationGenerator<>(identifier, + REQUEST_CONVERTER, RESPONSE_CONVERTER, responsePreprocessor, snippets)); + } + + /** + * Documents the API call with the given {@code identifier} using the given + * {@code snippets} in addition to any default snippets. The given + * {@code requestPreprocessor} and {@code responsePreprocessor} are applied to the + * request and response respectively before they are documented. + * + * @param identifier an identifier for the API call that is being documented + * @param requestPreprocessor the request preprocessor + * @param responsePreprocessor the response preprocessor + * @param snippets the snippets + * @return a {@link RestDocumentationFilter} that will produce the documentation + */ + public static RestDocumentationFilter document(String identifier, + OperationRequestPreprocessor requestPreprocessor, + OperationResponsePreprocessor responsePreprocessor, Snippet... snippets) { + return new RestDocumentationFilter(new RestDocumentationGenerator<>(identifier, + REQUEST_CONVERTER, RESPONSE_CONVERTER, requestPreprocessor, + responsePreprocessor, snippets)); + } + + /** + * Provides access to a {@link RestAssuredRestDocumentationConfigurer} that can be + * used to configure Spring REST Docs using the given {@code contextProvider}. + * + * @param contextProvider the context provider + * @return the configurer + */ + public static RestAssuredRestDocumentationConfigurer documentationConfiguration( + RestDocumentationContextProvider contextProvider) { + return new RestAssuredRestDocumentationConfigurer(contextProvider); + } + +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java new file mode 100644 index 00000000..66713b64 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurer.java @@ -0,0 +1,68 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.util.HashMap; +import java.util.Map; + +import io.restassured.filter.Filter; +import io.restassured.filter.FilterContext; +import io.restassured.response.Response; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.FilterableResponseSpecification; + +import org.springframework.restdocs.RestDocumentationContext; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.config.RestDocumentationConfigurer; + +/** + * A REST Assured 3-specific {@link RestDocumentationConfigurer}. + * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public final class RestAssuredRestDocumentationConfigurer extends + RestDocumentationConfigurer + implements Filter { + + private final RestAssuredSnippetConfigurer snippetConfigurer = new RestAssuredSnippetConfigurer( + this); + + private final RestDocumentationContextProvider contextProvider; + + RestAssuredRestDocumentationConfigurer( + RestDocumentationContextProvider contextProvider) { + this.contextProvider = contextProvider; + } + + @Override + public RestAssuredSnippetConfigurer snippets() { + return this.snippetConfigurer; + } + + @Override + public Response filter(FilterableRequestSpecification requestSpec, + FilterableResponseSpecification responseSpec, FilterContext filterContext) { + RestDocumentationContext context = this.contextProvider.beforeOperation(); + filterContext.setValue(RestDocumentationContext.class.getName(), context); + Map configuration = new HashMap<>(); + filterContext.setValue(RestDocumentationFilter.CONTEXT_KEY_CONFIGURATION, + configuration); + apply(configuration, context); + return filterContext.next(requestSpec, responseSpec); + } +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredSnippetConfigurer.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredSnippetConfigurer.java new file mode 100644 index 00000000..a4b12b3e --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestAssuredSnippetConfigurer.java @@ -0,0 +1,48 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import io.restassured.filter.Filter; +import io.restassured.filter.FilterContext; +import io.restassured.response.Response; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.FilterableResponseSpecification; + +import org.springframework.restdocs.config.SnippetConfigurer; + +/** + * A configurer that can be used to configure the generated documentation snippets when + * using REST Assured 3. + * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public final class RestAssuredSnippetConfigurer extends + SnippetConfigurer + implements Filter { + + RestAssuredSnippetConfigurer(RestAssuredRestDocumentationConfigurer parent) { + super(parent); + } + + @Override + public Response filter(FilterableRequestSpecification requestSpec, + FilterableResponseSpecification responseSpec, FilterContext context) { + return and().filter(requestSpec, responseSpec, context); + } + +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java new file mode 100644 index 00000000..b91b06f0 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/RestDocumentationFilter.java @@ -0,0 +1,120 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.util.HashMap; +import java.util.Map; + +import io.restassured.filter.Filter; +import io.restassured.filter.FilterContext; +import io.restassured.response.Response; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.FilterableResponseSpecification; + +import org.springframework.restdocs.RestDocumentationContext; +import org.springframework.restdocs.generate.RestDocumentationGenerator; +import org.springframework.restdocs.snippet.Snippet; +import org.springframework.util.Assert; + +/** + * A REST Assured 3 {@link Filter} for documenting RESTful APIs. + * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public class RestDocumentationFilter implements Filter { + + static final String CONTEXT_KEY_CONFIGURATION = "org.springframework.restdocs.configuration"; + + private final RestDocumentationGenerator delegate; + + RestDocumentationFilter( + RestDocumentationGenerator delegate) { + Assert.notNull(delegate, "delegate must be non-null"); + this.delegate = delegate; + } + + @Override + public final Response filter(FilterableRequestSpecification requestSpec, + FilterableResponseSpecification responseSpec, FilterContext context) { + Response response = context.next(requestSpec, responseSpec); + + Map configuration = getConfiguration(requestSpec, context); + + this.delegate.handle(requestSpec, response, configuration); + + return response; + } + + /** + * Returns the configuration that should be used when calling the delgate. The + * configuration is derived from the given {@code requestSpec} and {@code context}. + * + * @param requestSpec the request specification + * @param context the filter context + * @return the configuration + */ + protected Map getConfiguration( + FilterableRequestSpecification requestSpec, FilterContext context) { + Map configuration = new HashMap<>( + context.>getValue(CONTEXT_KEY_CONFIGURATION)); + configuration.put(RestDocumentationContext.class.getName(), + context.getValue( + RestDocumentationContext.class.getName())); + configuration.put(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, + requestSpec.getUserDefinedPath()); + return configuration; + } + + /** + * Adds the given {@code snippets} such that they are documented when this result + * handler is called. + * + * @param snippets the snippets to add + * @return this {@code RestDocumentationFilter} + * @deprecated since 1.1 in favor of {@link #document(Snippet...)} + */ + @Deprecated + public final RestDocumentationFilter snippets(Snippet... snippets) { + this.delegate.addSnippets(snippets); + return this; + } + + /** + * Creates a new {@link RestDocumentationFilter} that will produce documentation using + * the given {@code snippets}. + * + * @param snippets the snippets + * @return the new result handler + */ + public final RestDocumentationFilter document(Snippet... snippets) { + return new RestDocumentationFilter(this.delegate.withSnippets(snippets)) { + + @Override + protected Map getConfiguration( + FilterableRequestSpecification requestSpec, FilterContext context) { + Map configuration = super.getConfiguration(requestSpec, + context); + configuration.remove( + RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS); + return configuration; + } + + }; + } + +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java new file mode 100644 index 00000000..2deb20cc --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/RestAssuredPreprocessors.java @@ -0,0 +1,49 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3.operation.preprocess; + +import org.springframework.restdocs.operation.Operation; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationResponse; + +/** + * Static factory methods for creating + * {@link org.springframework.restdocs.operation.preprocess.OperationPreprocessor + * OperationPreprocessors} for use with REST Assured 3. They can be applied to an + * {@link Operation Operation's} {@link OperationRequest request} or + * {@link OperationResponse response} before it is documented. + * + * @author Andy Wilkinson + * @since 1.1.0 + */ +public abstract class RestAssuredPreprocessors { + + private RestAssuredPreprocessors() { + + } + + /** + * Returns a {@code UriModifyingOperationPreprocessor} that will modify URIs in the + * request or response by changing one or more of their host, scheme, and port. + * + * @return the preprocessor + */ + public static UriModifyingOperationPreprocessor modifyUris() { + return new UriModifyingOperationPreprocessor(); + } + +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java new file mode 100644 index 00000000..b4b5e18f --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessor.java @@ -0,0 +1,253 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3.operation.preprocess; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; +import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.OperationRequestPartFactory; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; +import org.springframework.restdocs.operation.preprocess.ContentModifier; +import org.springframework.restdocs.operation.preprocess.ContentModifyingOperationPreprocessor; +import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; +import org.springframework.util.StringUtils; +import org.springframework.web.util.UriComponentsBuilder; + +/** + * An {@link OperationPreprocessor} that modifies URIs in the request and in the response + * by changing one or more of their host, scheme, and port. URIs in the following + * locations are modified: + *
    + *
  • {@link OperationRequest#getUri() Request URI} + *
  • {@link OperationRequest#getHeaders() Request headers} + *
  • {@link OperationRequest#getContent() Request content} + *
  • {@link OperationRequestPart#getHeaders() Request part headers} + *
  • {@link OperationRequestPart#getContent() Request part content} + *
  • {@link OperationResponse#getHeaders() Response headers} + *
  • {@link OperationResponse#getContent() Response content} + *
+ * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public final class UriModifyingOperationPreprocessor implements OperationPreprocessor { + + private final UriModifyingContentModifier contentModifier = new UriModifyingContentModifier(); + + private final OperationPreprocessor contentModifyingDelegate = new ContentModifyingOperationPreprocessor( + this.contentModifier); + + private String scheme; + + private String host; + + private String port; + + /** + * Modifies the URI to use the given {@code scheme}. {@code null}, the default, will + * leave the scheme unchanged. + * + * @param scheme the scheme + * @return {@code this} + */ + public UriModifyingOperationPreprocessor scheme(String scheme) { + this.scheme = scheme; + this.contentModifier.setScheme(scheme); + return this; + } + + /** + * Modifies the URI to use the given {@code host}. {@code null}, the default, will + * leave the host unchanged. + * + * @param host the host + * @return {@code this} + */ + public UriModifyingOperationPreprocessor host(String host) { + this.host = host; + this.contentModifier.setHost(host); + return this; + } + + /** + * Modifies the URI to use the given {@code port}. + * + * @param port the port + * @return {@code this} + */ + public UriModifyingOperationPreprocessor port(int port) { + return port(Integer.toString(port)); + } + + /** + * Removes the port from the URI. + * + * @return {@code this} + */ + public UriModifyingOperationPreprocessor removePort() { + return port(""); + } + + private UriModifyingOperationPreprocessor port(String port) { + this.port = port; + this.contentModifier.setPort(port); + return this; + } + + @Override + public OperationRequest preprocess(OperationRequest request) { + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUri(request.getUri()); + if (this.scheme != null) { + uriBuilder.scheme(this.scheme); + } + if (this.host != null) { + uriBuilder.host(this.host); + } + if (this.port != null) { + if (StringUtils.hasText(this.port)) { + uriBuilder.port(this.port); + } + else { + uriBuilder.port(null); + } + } + URI modifiedUri = uriBuilder.build(true).toUri(); + HttpHeaders modifiedHeaders = modify(request.getHeaders()); + modifiedHeaders.set(HttpHeaders.HOST, modifiedUri.getHost() + + (modifiedUri.getPort() == -1 ? "" : ":" + modifiedUri.getPort())); + return this.contentModifyingDelegate.preprocess( + new OperationRequestFactory().create(uriBuilder.build(true).toUri(), + request.getMethod(), request.getContent(), modifiedHeaders, + request.getParameters(), modify(request.getParts()))); + } + + @Override + public OperationResponse preprocess(OperationResponse response) { + return this.contentModifyingDelegate + .preprocess(new OperationResponseFactory().create(response.getStatus(), + modify(response.getHeaders()), response.getContent())); + } + + private HttpHeaders modify(HttpHeaders headers) { + HttpHeaders modified = new HttpHeaders(); + for (Entry> header : headers.entrySet()) { + for (String value : header.getValue()) { + modified.add(header.getKey(), this.contentModifier.modify(value)); + } + } + return modified; + } + + private Collection modify( + Collection parts) { + List modifiedParts = new ArrayList<>(); + OperationRequestPartFactory factory = new OperationRequestPartFactory(); + for (OperationRequestPart part : parts) { + modifiedParts.add(factory.create(part.getName(), part.getSubmittedFileName(), + this.contentModifier.modifyContent(part.getContent(), + part.getHeaders().getContentType()), + modify(part.getHeaders()))); + } + return modifiedParts; + } + + private static final class UriModifyingContentModifier implements ContentModifier { + + private static final Pattern SCHEME_HOST_PORT_PATTERN = Pattern + .compile("(http[s]?)://([^/:#?]+)(:[0-9]+)?"); + + private String scheme; + + private String host; + + private String port; + + private void setScheme(String scheme) { + this.scheme = scheme; + } + + private void setHost(String host) { + this.host = host; + } + + private void setPort(String port) { + this.port = port; + } + + @Override + public byte[] modifyContent(byte[] content, MediaType contentType) { + String input; + if (contentType != null && contentType.getCharset() != null) { + input = new String(content, contentType.getCharset()); + } + else { + input = new String(content); + } + + return modify(input).getBytes(); + } + + private String modify(String input) { + List replacements = Arrays.asList(this.scheme, this.host, + StringUtils.hasText(this.port) ? ":" + this.port : this.port); + + int previous = 0; + + Matcher matcher = SCHEME_HOST_PORT_PATTERN.matcher(input); + StringBuilder builder = new StringBuilder(); + while (matcher.find()) { + for (int i = 1; i <= matcher.groupCount(); i++) { + if (matcher.start(i) >= 0) { + builder.append(input.substring(previous, matcher.start(i))); + } + if (matcher.start(i) >= 0) { + previous = matcher.end(i); + } + builder.append( + getReplacement(matcher.group(i), replacements.get(i - 1))); + } + } + + if (previous < input.length()) { + builder.append(input.substring(previous)); + } + return builder.toString(); + } + + private String getReplacement(String original, String candidate) { + if (candidate != null) { + return candidate; + } + if (original != null) { + return original; + } + return ""; + } + } +} diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/package-info.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/package-info.java new file mode 100644 index 00000000..957a0491 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/operation/preprocess/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2014-2017 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. + */ + +/** + * REST Assured-specific support for preprocessing an operation prior to it being + * documented. + */ +package org.springframework.restdocs.restassured3.operation.preprocess; diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/package-info.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/package-info.java new file mode 100644 index 00000000..9689e686 --- /dev/null +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured3/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2014-2017 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. + */ + +/** + * Core classes for using Spring REST Docs with REST Assured 3. + */ +package org.springframework.restdocs.restassured3; diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurerTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurerTests.java index 00d88930..a783f1dc 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurerTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -44,6 +44,7 @@ import static org.mockito.Mockito.verify; * * @author Andy Wilkinson */ +@Deprecated public class RestAssuredRestDocumentationConfigurerTests { @Rule diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java index 6a4cafbd..68cceb17 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java @@ -72,6 +72,7 @@ import static org.springframework.restdocs.test.SnippetMatchers.snippet; * @author Andy Wilkinson * @author Tomasz Kopczynski */ +@Deprecated public class RestAssuredRestDocumentationIntegrationTests { @Rule diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessorTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessorTests.java index d8cffc40..3773b305 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessorTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/operation/preprocess/UriModifyingOperationPreprocessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -42,6 +42,7 @@ import static org.junit.Assert.assertThat; * * @author Andy Wilkinson */ +@Deprecated public class UriModifyingOperationPreprocessorTests { private final OperationRequestFactory requestFactory = new OperationRequestFactory(); diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverterTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverterTests.java new file mode 100644 index 00000000..36ba6de0 --- /dev/null +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRequestConverterTests.java @@ -0,0 +1,326 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.net.URI; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import io.restassured.RestAssured; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.RequestSpecification; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.RequestCookie; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link RestAssuredRequestConverter}. + * + * @author Andy Wilkinson + */ +public class RestAssuredRequestConverterTests { + + @ClassRule + public static TomcatServer tomcat = new TomcatServer(); + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + private final RestAssuredRequestConverter factory = new RestAssuredRequestConverter(); + + @Test + public void requestUri() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()); + requestSpec.get("/foo/bar"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getUri(), is(equalTo( + URI.create("http://localhost:" + tomcat.getPort() + "/foo/bar")))); + } + + @Test + public void requestMethod() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()); + requestSpec.head("/foo/bar"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getMethod(), is(equalTo(HttpMethod.HEAD))); + } + + @Test + public void queryStringParameters() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .queryParam("foo", "bar"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParameters().size(), is(1)); + assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar")))); + } + + @Test + public void queryStringFromUrlParameters() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()); + requestSpec.get("/?foo=bar"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParameters().size(), is(1)); + assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar")))); + } + + @Test + public void formParameters() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .formParam("foo", "bar"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParameters().size(), is(1)); + assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar")))); + } + + @Test + public void requestParameters() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .param("foo", "bar"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParameters().size(), is(1)); + assertThat(request.getParameters().get("foo"), is(equalTo(Arrays.asList("bar")))); + } + + @Test + public void headers() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .header("Foo", "bar"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getHeaders().toString(), request.getHeaders().size(), is(3)); + assertThat(request.getHeaders().get("Foo"), is(equalTo(Arrays.asList("bar")))); + assertThat(request.getHeaders().get("Accept"), is(equalTo(Arrays.asList("*/*")))); + assertThat(request.getHeaders().get("Host"), + is(equalTo(Arrays.asList("localhost:" + tomcat.getPort())))); + } + + @Test + public void cookies() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .cookie("cookie1", "cookieVal1").cookie("cookie2", "cookieVal2"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getCookies().size(), is(equalTo(2))); + + Iterator cookieIterator = request.getCookies().iterator(); + RequestCookie cookie1 = cookieIterator.next(); + + assertThat(cookie1.getName(), is(equalTo("cookie1"))); + assertThat(cookie1.getValue(), is(equalTo("cookieVal1"))); + + RequestCookie cookie2 = cookieIterator.next(); + assertThat(cookie2.getName(), is(equalTo("cookie2"))); + assertThat(cookie2.getValue(), is(equalTo("cookieVal2"))); + } + + @Test + public void multipart() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("a", "a.txt", "alpha", null) + .multiPart("b", new ObjectBody("bar"), "application/json"); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + Collection parts = request.getParts(); + assertThat(parts.size(), is(2)); + Iterator iterator = parts.iterator(); + OperationRequestPart part = iterator.next(); + assertThat(part.getName(), is(equalTo("a"))); + assertThat(part.getSubmittedFileName(), is(equalTo("a.txt"))); + assertThat(part.getContentAsString(), is(equalTo("alpha"))); + assertThat(part.getHeaders().getContentType(), is(equalTo(MediaType.TEXT_PLAIN))); + part = iterator.next(); + assertThat(part.getName(), is(equalTo("b"))); + assertThat(part.getSubmittedFileName(), is(equalTo("file"))); + assertThat(part.getContentAsString(), is(equalTo("{\"foo\":\"bar\"}"))); + assertThat(part.getHeaders().getContentType(), + is(equalTo(MediaType.APPLICATION_JSON))); + } + + @Test + public void byteArrayBody() { + RequestSpecification requestSpec = RestAssured.given().body("body".getBytes()) + .port(tomcat.getPort()); + requestSpec.post(); + this.factory.convert((FilterableRequestSpecification) requestSpec); + } + + @Test + public void stringBody() { + RequestSpecification requestSpec = RestAssured.given().body("body") + .port(tomcat.getPort()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContentAsString(), is(equalTo("body"))); + } + + @Test + public void objectBody() { + RequestSpecification requestSpec = RestAssured.given().body(new ObjectBody("bar")) + .port(tomcat.getPort()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContentAsString(), is(equalTo("{\"foo\":\"bar\"}"))); + } + + @Test + public void byteArrayInputStreamBody() { + RequestSpecification requestSpec = RestAssured.given() + .body(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 })) + .port(tomcat.getPort()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContent(), is(equalTo(new byte[] { 1, 2, 3, 4 }))); + } + + @Test + public void fileBody() { + RequestSpecification requestSpec = RestAssured.given() + .body(new File("src/test/resources/body.txt")).port(tomcat.getPort()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getContentAsString(), is(equalTo("file"))); + } + + @Test + public void fileInputStreamBody() throws FileNotFoundException { + FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt"); + RequestSpecification requestSpec = RestAssured.given().body(inputStream) + .port(tomcat.getPort()); + requestSpec.post(); + this.thrown.expect(IllegalStateException.class); + this.thrown.expectMessage("Cannot read content from input stream " + inputStream + + " due to reset() failure"); + this.factory.convert((FilterableRequestSpecification) requestSpec); + } + + @Test + public void multipartWithByteArrayInputStreamBody() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("foo", "foo.txt", new ByteArrayInputStream("foo".getBytes())); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithStringBody() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("control", "foo"); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithByteArrayBody() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("control", "file", "foo".getBytes()); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("foo"))); + } + + @Test + public void multipartWithFileBody() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart(new File("src/test/resources/body.txt")); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("file"))); + } + + @Test + public void multipartWithFileInputStreamBody() throws FileNotFoundException { + FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt"); + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("foo", "foo.txt", inputStream); + requestSpec.post(); + this.thrown.expect(IllegalStateException.class); + this.thrown.expectMessage("Cannot read content from input stream " + inputStream + + " due to reset() failure"); + this.factory.convert((FilterableRequestSpecification) requestSpec); + } + + @Test + public void multipartWithObjectBody() { + RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()) + .multiPart("control", new ObjectBody("bar")); + requestSpec.post(); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getParts().iterator().next().getContentAsString(), + is(equalTo("{\"foo\":\"bar\"}"))); + } + + /** + * Sample object body to verify JSON serialization. + */ + static class ObjectBody { + + private final String foo; + + ObjectBody(String foo) { + this.foo = foo; + } + + public String getFoo() { + return this.foo; + } + + } + +} diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java new file mode 100644 index 00000000..f77b004c --- /dev/null +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationConfigurerTests.java @@ -0,0 +1,88 @@ +/* + * Copyright 2014-2016 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 org.springframework.restdocs.restassured3; + +import java.util.List; +import java.util.Map; + +import io.restassured.filter.FilterContext; +import io.restassured.specification.FilterableRequestSpecification; +import io.restassured.specification.FilterableResponseSpecification; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.restdocs.generate.RestDocumentationGenerator; +import org.springframework.restdocs.snippet.WriterResolver; +import org.springframework.restdocs.templates.TemplateEngine; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.Matchers.hasEntry; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link RestAssuredRestDocumentationConfigurer}. + * + * @author Andy Wilkinson + */ +public class RestAssuredRestDocumentationConfigurerTests { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); + + private final FilterableRequestSpecification requestSpec = mock( + FilterableRequestSpecification.class); + + private final FilterableResponseSpecification responseSpec = mock( + FilterableResponseSpecification.class); + + private final FilterContext filterContext = mock(FilterContext.class); + + private final RestAssuredRestDocumentationConfigurer configurer = new RestAssuredRestDocumentationConfigurer( + this.restDocumentation); + + @Test + public void nextFilterIsCalled() { + this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext); + verify(this.filterContext).next(this.requestSpec, this.responseSpec); + } + + @Test + public void configurationIsAddedToTheContext() { + this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext); + @SuppressWarnings("rawtypes") + ArgumentCaptor configurationCaptor = ArgumentCaptor.forClass(Map.class); + verify(this.filterContext).setValue( + eq(RestDocumentationFilter.CONTEXT_KEY_CONFIGURATION), + configurationCaptor.capture()); + @SuppressWarnings("unchecked") + Map configuration = configurationCaptor.getValue(); + assertThat(configuration, hasEntry(equalTo(TemplateEngine.class.getName()), + instanceOf(TemplateEngine.class))); + assertThat(configuration, hasEntry(equalTo(WriterResolver.class.getName()), + instanceOf(WriterResolver.class))); + assertThat(configuration, + hasEntry( + equalTo(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS), + instanceOf(List.class))); + } +} diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java new file mode 100644 index 00000000..d7286ff6 --- /dev/null +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java @@ -0,0 +1,385 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.regex.Pattern; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.web.bind.annotation.RequestMethod; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.maskLinks; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.removeHeaders; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.replacePattern; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.partWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParts; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris; +import static org.springframework.restdocs.templates.TemplateFormats.asciidoctor; +import static org.springframework.restdocs.test.SnippetMatchers.codeBlock; +import static org.springframework.restdocs.test.SnippetMatchers.httpRequest; +import static org.springframework.restdocs.test.SnippetMatchers.httpResponse; +import static org.springframework.restdocs.test.SnippetMatchers.snippet; + +/** + * Integration tests for using Spring REST Docs with REST Assured. + * + * @author Andy Wilkinson + * @author Tomasz Kopczynski + */ +public class RestAssuredRestDocumentationIntegrationTests { + + @Rule + public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); + + @ClassRule + public static TomcatServer tomcat = new TomcatServer(); + + @Test + public void defaultSnippetGeneration() { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("default")).get("/").then().statusCode(200); + assertExpectedSnippetFilesExist(new File("build/generated-snippets/default"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc"); + } + + @Test + public void curlSnippetWithContent() throws Exception { + String contentType = "text/plain; charset=UTF-8"; + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("curl-snippet-with-content")).accept("application/json") + .body("content").contentType(contentType).post("/").then() + .statusCode(200); + + assertThat( + new File( + "build/generated-snippets/curl-snippet-with-content/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), "bash") + .content(String.format("$ curl 'http://localhost:" + + tomcat.getPort() + "/' -i -X POST \\%n" + + " -H 'Accept: application/json' \\%n" + + " -H 'Content-Type: " + contentType + "' \\%n" + + " -d 'content'"))))); + } + + @Test + public void curlSnippetWithCookies() throws Exception { + String contentType = "text/plain; charset=UTF-8"; + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("curl-snippet-with-cookies")).accept("application/json") + .contentType(contentType).cookie("cookieName", "cookieVal").get("/") + .then().statusCode(200); + assertThat( + new File( + "build/generated-snippets/curl-snippet-with-cookies/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), + "bash").content(String.format("$ curl 'http://localhost:" + + tomcat.getPort() + "/' -i \\%n" + + " -H 'Accept: application/json' \\%n" + + " -H 'Content-Type: " + contentType + "' \\%n" + + " --cookie 'cookieName=cookieVal'"))))); + } + + @Test + public void curlSnippetWithQueryStringOnPost() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("curl-snippet-with-query-string")) + .accept("application/json").param("foo", "bar").param("a", "alpha") + .post("/?foo=bar").then().statusCode(200); + String contentType = "application/x-www-form-urlencoded; charset=ISO-8859-1"; + assertThat( + new File( + "build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), "bash") + .content(String.format("$ curl " + "'http://localhost:" + + tomcat.getPort() + "/?foo=bar' -i -X POST \\%n" + + " -H 'Accept: application/json' \\%n" + + " -H 'Content-Type: " + contentType + "' \\%n" + + " -d 'a=alpha'"))))); + } + + @Test + public void linksSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("links", + links(linkWithRel("rel").description("The description")))) + .accept("application/json").get("/").then().statusCode(200); + assertExpectedSnippetFilesExist(new File("build/generated-snippets/links"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc", + "links.adoc"); + } + + @Test + public void pathParametersSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("path-parameters", + pathParameters( + parameterWithName("foo").description("The description")))) + .accept("application/json").get("/{foo}", "").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/path-parameters"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc", "path-parameters.adoc"); + } + + @Test + public void requestParametersSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("request-parameters", + requestParameters( + parameterWithName("foo").description("The description")))) + .accept("application/json").param("foo", "bar").get("/").then() + .statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/request-parameters"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc", + "request-parameters.adoc"); + } + + @Test + public void requestFieldsSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("request-fields", + requestFields(fieldWithPath("a").description("The description")))) + .accept("application/json").body("{\"a\":\"alpha\"}").post("/").then() + .statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/request-fields"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc", "request-fields.adoc"); + } + + @Test + public void requestPartsSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("request-parts", + requestParts(partWithName("a").description("The description")))) + .multiPart("a", "foo").post("/upload").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/request-parts"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc", "request-parts.adoc"); + } + + @Test + public void responseFieldsSnippet() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("response-fields", + responseFields(fieldWithPath("a").description("The description"), + subsectionWithPath("links") + .description("Links to other resources")))) + .accept("application/json").get("/").then().statusCode(200); + + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/response-fields"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc", "response-fields.adoc"); + } + + @Test + public void parameterizedOutputDirectory() throws Exception { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("{method-name}")).get("/").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/parameterized-output-directory"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc"); + } + + @Test + public void multiStep() throws Exception { + RequestSpecification spec = new RequestSpecBuilder().setPort(tomcat.getPort()) + .addFilter(documentationConfiguration(this.restDocumentation)) + .addFilter(document("{method-name}-{step}")).build(); + given(spec).get("/").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/multi-step-1/"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc"); + given(spec).get("/").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/multi-step-2/"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc"); + given(spec).get("/").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/multi-step-3/"), "http-request.adoc", + "http-response.adoc", "curl-request.adoc"); + } + + @Test + public void additionalSnippets() throws Exception { + RestDocumentationFilter documentation = document("{method-name}-{step}"); + RequestSpecification spec = new RequestSpecBuilder().setPort(tomcat.getPort()) + .addFilter(documentationConfiguration(this.restDocumentation)) + .addFilter(documentation).build(); + given(spec) + .filter(documentation + .document(responseHeaders(headerWithName("a").description("one"), + headerWithName("Foo").description("two")))) + .get("/").then().statusCode(200); + assertExpectedSnippetFilesExist( + new File("build/generated-snippets/additional-snippets-1/"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc", + "response-headers.adoc"); + } + + @Test + public void responseWithCookie() { + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("set-cookie", + preprocessResponse(removeHeaders(HttpHeaders.DATE, + HttpHeaders.CONTENT_TYPE)))) + .get("/set-cookie").then().statusCode(200); + assertExpectedSnippetFilesExist(new File("build/generated-snippets/set-cookie"), + "http-request.adoc", "http-response.adoc", "curl-request.adoc"); + + assertThat(new File("build/generated-snippets/set-cookie/http-response.adoc"), + is(snippet(asciidoctor()) + .withContents(httpResponse(asciidoctor(), HttpStatus.OK).header( + HttpHeaders.SET_COOKIE, + "name=value;domain=localhost;HttpOnly")))); + } + + @Test + public void preprocessedRequest() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .header("a", "alpha").header("b", "bravo").contentType("application/json") + .accept("application/json").body("{\"a\":\"alpha\"}") + .filter(document("original-request")) + .filter(document("preprocessed-request", + preprocessRequest(prettyPrint(), + replacePattern(pattern, "\"<>\""), + modifyUris().removePort(), + removeHeaders("a", HttpHeaders.CONTENT_LENGTH)))) + .get("/").then().statusCode(200); + assertThat( + new File("build/generated-snippets/original-request/http-request.adoc"), + is(snippet(asciidoctor()) + .withContents(httpRequest(asciidoctor(), RequestMethod.GET, "/") + .header("a", "alpha").header("b", "bravo") + .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .header("Content-Type", "application/json; charset=UTF-8") + .header("Host", "localhost:" + tomcat.getPort()) + .header("Content-Length", "13") + .content("{\"a\":\"alpha\"}")))); + String prettyPrinted = String.format("{%n \"a\" : \"<>\"%n}"); + assertThat( + new File( + "build/generated-snippets/preprocessed-request/http-request.adoc"), + is(snippet(asciidoctor()) + .withContents(httpRequest(asciidoctor(), RequestMethod.GET, "/") + .header("b", "bravo") + .header("Accept", MediaType.APPLICATION_JSON_VALUE) + .header("Content-Type", "application/json; charset=UTF-8") + .header("Host", "localhost").content(prettyPrinted)))); + } + + @Test + public void preprocessedResponse() throws Exception { + Pattern pattern = Pattern.compile("(\"alpha\")"); + given().port(tomcat.getPort()) + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("original-response")) + .filter(document("preprocessed-response", preprocessResponse( + prettyPrint(), maskLinks(), + removeHeaders("a", "Transfer-Encoding", "Date", "Server"), + replacePattern(pattern, "\"<>\""), modifyUris() + .scheme("https").host("api.example.com").removePort()))) + .get("/").then().statusCode(200); + String prettyPrinted = String.format("{%n \"a\" : \"<>\",%n \"links\" : " + + "[ {%n \"rel\" : \"rel\",%n \"href\" : \"...\"%n } ]%n}"); + assertThat( + new File( + "build/generated-snippets/preprocessed-response/http-response.adoc"), + is(snippet(asciidoctor()) + .withContents(httpResponse(asciidoctor(), HttpStatus.OK) + .header("Foo", "https://api.example.com/foo/bar") + .header("Content-Type", "application/json;charset=UTF-8") + .header(HttpHeaders.CONTENT_LENGTH, + prettyPrinted.getBytes().length) + .content(prettyPrinted)))); + } + + @Test + public void customSnippetTemplate() throws Exception { + ClassLoader classLoader = new URLClassLoader(new URL[] { + new File("src/test/resources/custom-snippet-templates").toURI().toURL() }, + getClass().getClassLoader()); + ClassLoader previous = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(classLoader); + try { + given().port(tomcat.getPort()).accept("application/json") + .filter(documentationConfiguration(this.restDocumentation)) + .filter(document("custom-snippet-template")).get("/").then() + .statusCode(200); + } + finally { + Thread.currentThread().setContextClassLoader(previous); + } + assertThat( + new File( + "build/generated-snippets/custom-snippet-template/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(equalTo("Custom curl request")))); + } + + private void assertExpectedSnippetFilesExist(File directory, String... snippets) { + for (String snippet : snippets) { + File snippetFile = new File(directory, snippet); + assertTrue("Snippet " + snippetFile + " not found", snippetFile.isFile()); + } + } + +} diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/TomcatServer.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/TomcatServer.java new file mode 100644 index 00000000..b45d9785 --- /dev/null +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/TomcatServer.java @@ -0,0 +1,126 @@ +/* + * Copyright 2014-2017 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 org.springframework.restdocs.restassured3; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.startup.Tomcat; +import org.junit.rules.ExternalResource; + +/** + * {@link ExternalResource} that starts and stops a Tomcat server. + * + * @author Andy Wilkinson + */ +class TomcatServer extends ExternalResource { + + private Tomcat tomcat; + + private int port; + + @Override + protected void before() throws LifecycleException { + this.tomcat = new Tomcat(); + this.tomcat.getConnector().setPort(0); + Context context = this.tomcat.addContext("/", null); + this.tomcat.addServlet("/", "test", new TestServlet()); + context.addServletMappingDecoded("/", "test"); + this.tomcat.addServlet("/", "set-cookie", new CookiesServlet()); + context.addServletMappingDecoded("/set-cookie", "set-cookie"); + this.tomcat.start(); + this.port = this.tomcat.getConnector().getLocalPort(); + } + + @Override + protected void after() { + try { + this.tomcat.stop(); + } + catch (LifecycleException ex) { + throw new RuntimeException(ex); + } + } + + int getPort() { + return this.port; + } + + /** + * {@link HttpServlet} used to handle requests in the tests. + */ + private static final class TestServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + respondWithJson(response); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + respondWithJson(response); + } + + private void respondWithJson(HttpServletResponse response) + throws IOException, JsonProcessingException { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + Map content = new HashMap<>(); + content.put("a", "alpha"); + Map link = new HashMap<>(); + link.put("rel", "rel"); + link.put("href", "href"); + content.put("links", Arrays.asList(link)); + response.getWriter().println(new ObjectMapper().writeValueAsString(content)); + response.setHeader("a", "alpha"); + response.setHeader("Foo", "http://localhost:12345/foo/bar"); + response.flushBuffer(); + } + + } + + /** + * {@link HttpServlet} used to handle cookies-related requests in the tests. + */ + private static final class CookiesServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + Cookie cookie = new Cookie("name", "value"); + cookie.setDomain("localhost"); + cookie.setHttpOnly(true); + + resp.addCookie(cookie); + } + } + +} diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java new file mode 100644 index 00000000..7f262e9f --- /dev/null +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/operation/preprocess/UriModifyingOperationPreprocessorTests.java @@ -0,0 +1,373 @@ +/* + * Copyright 2014-2016 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 org.springframework.restdocs.restassured3.operation.preprocess; + +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Test; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationRequestFactory; +import org.springframework.restdocs.operation.OperationRequestPart; +import org.springframework.restdocs.operation.OperationRequestPartFactory; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; +import org.springframework.restdocs.operation.Parameters; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link UriModifyingOperationPreprocessor}. + * + * @author Andy Wilkinson + */ +public class UriModifyingOperationPreprocessorTests { + + private final OperationRequestFactory requestFactory = new OperationRequestFactory(); + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + + private final UriModifyingOperationPreprocessor preprocessor = new UriModifyingOperationPreprocessor(); + + @Test + public void requestUriSchemeCanBeModified() { + this.preprocessor.scheme("https"); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://localhost:12345")); + assertThat(processed.getUri(), + is(equalTo(URI.create("https://localhost:12345")))); + } + + @Test + public void requestUriHostCanBeModified() { + this.preprocessor.host("api.example.com"); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.foo.com:12345")); + assertThat(processed.getUri(), + is(equalTo(URI.create("http://api.example.com:12345")))); + assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST), + is(equalTo("api.example.com:12345"))); + } + + @Test + public void requestUriPortCanBeModified() { + this.preprocessor.port(23456); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.example.com:12345")); + assertThat(processed.getUri(), + is(equalTo(URI.create("http://api.example.com:23456")))); + assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST), + is(equalTo("api.example.com:23456"))); + } + + @Test + public void requestUriPortCanBeRemoved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.example.com:12345")); + assertThat(processed.getUri(), is(equalTo(URI.create("http://api.example.com")))); + assertThat(processed.getHeaders().getFirst(HttpHeaders.HOST), + is(equalTo("api.example.com"))); + } + + @Test + public void requestUriPathIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.example.com:12345/foo/bar")); + assertThat(processed.getUri(), + is(equalTo(URI.create("http://api.example.com/foo/bar")))); + } + + @Test + public void requestUriQueryIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.example.com:12345?foo=bar")); + assertThat(processed.getUri(), + is(equalTo(URI.create("http://api.example.com?foo=bar")))); + } + + @Test + public void requestUriAnchorIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://api.example.com:12345#foo")); + assertThat(processed.getUri(), + is(equalTo(URI.create("http://api.example.com#foo")))); + } + + @Test + public void requestContentUriSchemeCanBeModified() { + this.preprocessor.scheme("https"); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'https://localhost:12345' should be used"))); + } + + @Test + public void requestContentUriHostCanBeModified() { + this.preprocessor.host("api.example.com"); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://api.example.com:12345' should be used"))); + } + + @Test + public void requestContentUriPortCanBeModified() { + this.preprocessor.port(23456); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost:23456' should be used"))); + } + + @Test + public void requestContentUriPortCanBeRemoved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost' should be used"))); + } + + @Test + public void multipleRequestContentUrisCanBeModified() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "Use 'http://localhost:12345' or 'https://localhost:23456' to access the service")); + assertThat(new String(processed.getContent()), is(equalTo( + "Use 'http://localhost' or 'https://localhost' to access the service"))); + } + + @Test + public void requestContentUriPathIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345/foo/bar' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost/foo/bar' should be used"))); + } + + @Test + public void requestContentUriQueryIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345?foo=bar' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost?foo=bar' should be used"))); + } + + @Test + public void requestContentUriAnchorIsPreserved() { + this.preprocessor.removePort(); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithContent( + "The uri 'http://localhost:12345#foo' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost#foo' should be used"))); + } + + @Test + public void responseContentUriSchemeCanBeModified() { + this.preprocessor.scheme("https"); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'https://localhost:12345' should be used"))); + } + + @Test + public void responseContentUriHostCanBeModified() { + this.preprocessor.host("api.example.com"); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://api.example.com:12345' should be used"))); + } + + @Test + public void responseContentUriPortCanBeModified() { + this.preprocessor.port(23456); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost:23456' should be used"))); + } + + @Test + public void responseContentUriPortCanBeRemoved() { + this.preprocessor.removePort(); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost' should be used"))); + } + + @Test + public void multipleResponseContentUrisCanBeModified() { + this.preprocessor.removePort(); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "Use 'http://localhost:12345' or 'https://localhost:23456' to access the service")); + assertThat(new String(processed.getContent()), is(equalTo( + "Use 'http://localhost' or 'https://localhost' to access the service"))); + } + + @Test + public void responseContentUriPathIsPreserved() { + this.preprocessor.removePort(); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345/foo/bar' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost/foo/bar' should be used"))); + } + + @Test + public void responseContentUriQueryIsPreserved() { + this.preprocessor.removePort(); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345?foo=bar' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost?foo=bar' should be used"))); + } + + @Test + public void responseContentUriAnchorIsPreserved() { + this.preprocessor.removePort(); + OperationResponse processed = this.preprocessor + .preprocess(createResponseWithContent( + "The uri 'http://localhost:12345#foo' should be used")); + assertThat(new String(processed.getContent()), + is(equalTo("The uri 'http://localhost#foo' should be used"))); + } + + @Test + public void urisInRequestHeadersCanBeModified() { + OperationRequest processed = this.preprocessor.host("api.example.com") + .preprocess(createRequestWithHeader("Foo", "http://locahost:12345")); + assertThat(processed.getHeaders().getFirst("Foo"), + is(equalTo("http://api.example.com:12345"))); + assertThat(processed.getHeaders().getFirst("Host"), + is(equalTo("api.example.com"))); + } + + @Test + public void urisInResponseHeadersCanBeModified() { + OperationResponse processed = this.preprocessor.host("api.example.com") + .preprocess(createResponseWithHeader("Foo", "http://locahost:12345")); + assertThat(processed.getHeaders().getFirst("Foo"), + is(equalTo("http://api.example.com:12345"))); + } + + @Test + public void urisInRequestPartHeadersCanBeModified() { + OperationRequest processed = this.preprocessor.host("api.example.com").preprocess( + createRequestWithPartWithHeader("Foo", "http://locahost:12345")); + assertThat(processed.getParts().iterator().next().getHeaders().getFirst("Foo"), + is(equalTo("http://api.example.com:12345"))); + } + + @Test + public void urisInRequestPartContentCanBeModified() { + OperationRequest processed = this.preprocessor.host("api.example.com") + .preprocess(createRequestWithPartWithContent( + "The uri 'http://localhost:12345' should be used")); + assertThat(new String(processed.getParts().iterator().next().getContent()), + is(equalTo("The uri 'http://api.example.com:12345' should be used"))); + } + + @Test + public void modifiedUriDoesNotGetDoubleEncoded() { + this.preprocessor.scheme("https"); + OperationRequest processed = this.preprocessor + .preprocess(createRequestWithUri("http://localhost:12345?foo=%7B%7D")); + assertThat(processed.getUri(), + is(equalTo(URI.create("https://localhost:12345?foo=%7B%7D")))); + + } + + private OperationRequest createRequestWithUri(String uri) { + return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0], + new HttpHeaders(), new Parameters(), + Collections.emptyList()); + } + + private OperationRequest createRequestWithContent(String content) { + return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, + content.getBytes(), new HttpHeaders(), new Parameters(), + Collections.emptyList()); + } + + private OperationRequest createRequestWithHeader(String name, String value) { + HttpHeaders headers = new HttpHeaders(); + headers.add(name, value); + return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, + new byte[0], headers, new Parameters(), + Collections.emptyList()); + } + + private OperationRequest createRequestWithPartWithHeader(String name, String value) { + HttpHeaders headers = new HttpHeaders(); + headers.add(name, value); + return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, + new byte[0], new HttpHeaders(), new Parameters(), + Arrays.asList(new OperationRequestPartFactory().create("part", "fileName", + new byte[0], headers))); + } + + private OperationRequest createRequestWithPartWithContent(String content) { + return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, + new byte[0], new HttpHeaders(), new Parameters(), + Arrays.asList(new OperationRequestPartFactory().create("part", "fileName", + content.getBytes(), new HttpHeaders()))); + } + + private OperationResponse createResponseWithContent(String content) { + return this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), + content.getBytes()); + } + + private OperationResponse createResponseWithHeader(String name, String value) { + HttpHeaders headers = new HttpHeaders(); + headers.add(name, value); + return this.responseFactory.create(HttpStatus.OK, headers, new byte[0]); + } + +}