Handle form and query parameters separately

Previously, form and query parameters were handled together as
request parameters. Howeer, request parameters are a server-side
construct that's specific to the servlet specification. As such
they're not appropriate for the client-side documentation that
Spring REST Docs aims to produce.

This commit replaces support for documenting request parameters
with support for documenting query paramters found in the query
string of the request's URI and for documenting form parameters
found in the form URL encoded body of the request.

Closes gh-832
This commit is contained in:
Andy Wilkinson
2022-10-10 15:28:30 +01:00
parent b4be34bf8e
commit f5a629af34
63 changed files with 1730 additions and 1356 deletions

View File

@@ -57,14 +57,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET"));
}
@Test
public void getRequestWithParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo").param("a", "alpha").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X GET"));
}
@Test
public void nonGetRequest() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
@@ -89,30 +81,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
}
@Test
public void getRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo?param=value").param("param", "value").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
}
@Test
public void getRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo?a=alpha").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X GET"));
}
@Test
public void getRequestWithDisjointQueryStringAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X GET"));
}
@Test
public void getRequestWithQueryStringWithNoValue() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
@@ -140,7 +108,16 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithOneParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "v1").build());
this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=v1").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
}
@Test
public void postRequestWithOneParameterAndExplicitContentType() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE).method("POST")
.content("k1=v1").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
}
@@ -148,7 +125,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithOneParameterWithNoValue() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("k1").build());
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1='"));
}
@@ -156,7 +133,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithMultipleParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").param("k1", "v1", "v1-bis").param("k2", "v2").build());
.method("POST").content("k1=v1&k1=v1-bis&k2=v2").build());
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
.withContent("$ curl 'http://localhost/foo' -i -X POST" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
}
@@ -164,52 +141,24 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithUrlEncodedParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "a&b").build());
this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=a%26b").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
}
@Test
public void postRequestWithDisjointQueryStringAndParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo?a=alpha").method("POST").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
}
@Test
public void postRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("POST")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X POST"));
}
@Test
public void postRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST "
+ "-H 'Content-Type: application/x-www-form-urlencoded' " + "-d 'a=alpha&b=bravo'"));
public void postRequestWithJsonData() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.content("{\"a\":\"alpha\"}").build());
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(
"$ curl 'http://localhost/foo' -i -X POST -H 'Content-Type: application/json' -d '{\"a\":\"alpha\"}'"));
}
@Test
public void putRequestWithOneParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "v1").build());
new CurlRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=v1").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
}
@@ -217,7 +166,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void putRequestWithMultipleParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("PUT").param("k1", "v1").param("k1", "v1-bis").param("k2", "v2").build());
.method("PUT").content("k1=v1&k1=v1-bis&k2=v2").build());
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
.withContent("$ curl 'http://localhost/foo' -i -X PUT" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
}
@@ -225,7 +174,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
@Test
public void putRequestWithUrlEncodedParameter() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "a&b").build());
this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=a%26b").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
}
@@ -287,29 +236,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void multipartPostWithParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
.param("a", "apple", "avocado").param("b", "banana").build());
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
+ "'Content-Type: multipart/form-data' -F "
+ "'image=@documents/images/example.png' -F 'a=apple' -F 'a=avocado' " + "-F 'b=banana'";
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
.part("a", "apple".getBytes()).and().param("a", "apple").build());
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
+ "'Content-Type: multipart/form-data' -F 'image=@documents/images/example.png' -F 'a=apple'";
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void basicAuthCredentialsAreSuppliedUsingUserOption() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
@@ -329,22 +255,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
}
@Test
public void postWithContentAndParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.param("a", "alpha").method("POST").param("b", "bravo").content("Some content").build());
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
.withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X POST -d 'Some content'"));
}
@Test
public void deleteWithParameters() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("DELETE").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.curlRequest())
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X DELETE"));
}
@Test
public void deleteWithQueryString() throws IOException {
new CurlRequestSnippet(this.commandFormatter).document(

View File

@@ -58,14 +58,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo'"));
}
@Test
public void getRequestWithParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo").param("a", "alpha").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha'"));
}
@Test
public void nonGetRequest() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
@@ -90,30 +82,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
}
@Test
public void getRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo?param=value").param("param", "value").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
}
@Test
public void getRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo?a=alpha").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha&b=bravo'"));
}
@Test
public void getRequestWithDisjointQueryStringAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha&b=bravo'"));
}
@Test
public void getRequestWithQueryStringWithNoValue() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
@@ -140,16 +108,18 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithOneParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "v1").build());
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=v1").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1'"));
}
@Test
public void postRequestWithOneParameterWithNoValue() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("k1").build());
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1='"));
}
@@ -157,60 +127,26 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
@Test
public void postRequestWithMultipleParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").param("k1", "v1", "v1-bis").param("k2", "v2").build());
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
.withContent("$ http --form POST 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=v1&k1=v1-bis&k2=v2").build());
assertThat(this.generatedSnippets.httpieRequest()).is(
codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
}
@Test
public void postRequestWithUrlEncodedParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "a&b").build());
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=a%26b").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=a&b'"));
}
@Test
public void postRequestWithDisjointQueryStringAndParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo?a=alpha").method("POST").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo?a=alpha' 'b=bravo'"));
}
@Test
public void postRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("POST")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http POST 'http://localhost/foo?a=alpha&b=bravo'"));
}
@Test
public void postRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo?a=alpha' 'b=bravo'"));
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ echo 'a=alpha&b=bravo' | http POST 'http://localhost/foo' "
+ "'Content-Type:application/x-www-form-urlencoded'"));
}
@Test
public void putRequestWithOneParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "v1").build());
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=v1").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=v1'"));
}
@@ -218,15 +154,17 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
@Test
public void putRequestWithMultipleParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("PUT").param("k1", "v1").param("k1", "v1-bis").param("k2", "v2").build());
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=v1&k1=v1-bis&k2=v2").build());
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
.withContent("$ http --form PUT 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
}
@Test
public void putRequestWithUrlEncodedParameter() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "a&b").build());
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.content("k1=a%26b").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=a&b'"));
}
@@ -291,30 +229,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void multipartPostWithParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/upload").method("POST")
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
.param("a", "apple", "avocado").param("b", "banana").build());
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
+ " 'image'@'documents/images/example.png' 'a=apple' 'a=avocado'" + " 'b=banana'";
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter)
.document(this.operationBuilder.request("http://localhost/upload").method("POST")
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
.part("a", "apple".getBytes()).and().param("a", "apple").build());
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
+ " 'image'@'documents/images/example.png' 'a'='apple'";
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
}
@Test
public void basicAuthCredentialsAreSuppliedUsingAuthOption() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
@@ -334,22 +248,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
+ " 'Content-Type:application/json' 'a:alpha'"));
}
@Test
public void postWithContentAndParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("POST").param("a", "alpha").param("b", "bravo").content("Some content").build());
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
.withContent("$ echo 'Some content' | http POST " + "'http://localhost/foo?a=alpha&b=bravo'"));
}
@Test
public void deleteWithParameters() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
.method("DELETE").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpieRequest())
.is(codeBlock("bash").withContent("$ http DELETE 'http://localhost/foo?a=alpha&b=bravo'"));
}
@Test
public void deleteWithQueryString() throws IOException {
new HttpieRequestSnippet(this.commandFormatter).document(

View File

@@ -58,9 +58,9 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
}
@Test
public void getRequestWithParameters() throws IOException {
new HttpRequestSnippet().document(
this.operationBuilder.request("http://localhost/foo").header("Alpha", "a").param("b", "bravo").build());
public void getRequestWithQueryParameters() throws IOException {
new HttpRequestSnippet()
.document(this.operationBuilder.request("http://localhost/foo?b=bravo").header("Alpha", "a").build());
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.GET, "/foo?b=bravo")
.header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
}
@@ -96,22 +96,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
.is(httpRequest(RequestMethod.GET, "/foo?bar").header(HttpHeaders.HOST, "localhost"));
}
@Test
public void getWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.GET, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
}
@Test
public void getWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.GET, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
}
@Test
public void postRequestWithContent() throws IOException {
String content = "Hello, world";
@@ -123,59 +107,16 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
}
@Test
public void postRequestWithContentAndParameters() throws IOException {
public void postRequestWithContentAndQueryParameters() throws IOException {
String content = "Hello, world";
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("POST")
.param("a", "alpha").content(content).build());
new HttpRequestSnippet().document(
this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST").content(content).build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo?a=alpha").header(HttpHeaders.HOST, "localhost")
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void postRequestWithContentAndDisjointQueryStringAndParameters() throws IOException {
String content = "Hello, world";
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo").method("POST")
.param("a", "alpha").content(content).build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void postRequestWithContentAndPartiallyOverlappingQueryStringAndParameters() throws IOException {
String content = "Hello, world";
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo").method("POST")
.param("a", "alpha").param("b", "bravo").content(content).build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void postRequestWithContentAndTotallyOverlappingQueryStringAndParameters() throws IOException {
String content = "Hello, world";
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo&a=alpha")
.method("POST").param("a", "alpha").param("b", "bravo").content(content).build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
String content = "a=alpha&b=bravo";
new HttpRequestSnippet().document(
this.operationBuilder.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/foo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.header(HttpHeaders.HOST, "localhost").content(content)
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void postRequestWithCharset() throws IOException {
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
@@ -187,24 +128,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length).content(japaneseContent));
}
@Test
public void postRequestWithParameter() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("POST")
.param("b&r", "baz").param("a", "alpha").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo").header(HttpHeaders.HOST, "localhost")
.header("Content-Type", "application/x-www-form-urlencoded").content("b%26r=baz&a=alpha"));
}
@Test
public void postRequestWithParameterWithNoValue() throws IOException {
new HttpRequestSnippet()
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("bar").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.POST, "/foo").header(HttpHeaders.HOST, "localhost")
.header("Content-Type", "application/x-www-form-urlencoded").content("bar="));
}
@Test
public void putRequestWithContent() throws IOException {
String content = "Hello, world";
@@ -215,23 +138,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
}
@Test
public void putRequestWithParameter() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("PUT")
.param("b&r", "baz").param("a", "alpha").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.PUT, "/foo").header(HttpHeaders.HOST, "localhost")
.header("Content-Type", "application/x-www-form-urlencoded").content("b%26r=baz&a=alpha"));
}
@Test
public void putRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo")
.method("PUT").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.PUT, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
}
@Test
public void multipartPost() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
@@ -256,47 +162,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
}
@Test
public void multipartPostWithParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a", "apple", "avocado")
.param("b", "banana").part("image", "<< data >>".getBytes()).build());
String param1Part = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%napple"), false);
String param2Part = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%navocado"), false);
String param3Part = createPart(String.format("Content-Disposition: form-data; " + "name=b%n%nbanana"), false);
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
String expectedContent = param1Part + param2Part + param3Part + filePart;
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
}
@Test
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a", "apple")
.part("a", "apple".getBytes()).and().part("image", "<< data >>".getBytes()).build());
String paramPart = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%napple"), false);
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
String expectedContent = paramPart + filePart;
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
}
@Test
public void multipartPostWithParameterWithNoValue() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a")
.part("image", "<< data >>".getBytes()).build());
String paramPart = createPart(String.format("Content-Disposition: form-data; " + "name=a%n"), false);
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
String expectedContent = paramPart + filePart;
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
}
@Test
public void multipartPostWithContentType() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
@@ -328,14 +193,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
assertThat(this.generatedSnippets.httpRequest()).contains("Title for the request");
}
@Test
public void deleteWithParameters() throws IOException {
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("DELETE")
.param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.httpRequest())
.is(httpRequest(RequestMethod.DELETE, "/foo?a=alpha&b=bravo").header("Host", "localhost"));
}
@Test
public void deleteWithQueryString() throws IOException {
new HttpRequestSnippet().document(

View File

@@ -1,75 +0,0 @@
/*
* Copyright 2014-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs.operation;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link Parameters}.
*
* @author Andy Wilkinson
*/
public class ParametersTests {
private final Parameters parameters = new Parameters();
@Test
public void queryStringForNoParameters() {
assertThat(this.parameters.toQueryString()).isEqualTo("");
}
@Test
public void queryStringForSingleParameter() {
this.parameters.add("a", "b");
assertThat(this.parameters.toQueryString()).isEqualTo("a=b");
}
@Test
public void queryStringForSingleParameterWithMultipleValues() {
this.parameters.add("a", "b");
this.parameters.add("a", "c");
assertThat(this.parameters.toQueryString()).isEqualTo("a=b&a=c");
}
@Test
public void queryStringForMutipleParameters() {
this.parameters.add("a", "alpha");
this.parameters.add("b", "bravo");
assertThat(this.parameters.toQueryString()).isEqualTo("a=alpha&b=bravo");
}
@Test
public void queryStringForParameterWithEmptyValue() {
this.parameters.add("a", "");
assertThat(this.parameters.toQueryString()).isEqualTo("a=");
}
@Test
public void queryStringForParameterWithNullValue() {
this.parameters.add("a", null);
assertThat(this.parameters.toQueryString()).isEqualTo("a=");
}
@Test
public void queryStringForParameterThatRequiresEncoding() {
this.parameters.add("a", "alpha&bravo");
assertThat(this.parameters.toQueryString()).isEqualTo("a=alpha%26bravo");
}
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs.operation;
import java.net.URI;
import java.util.Arrays;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link QueryStringParser}.
*
* @author Andy Wilkinson
*/
public class QueryStringParserTests {
private final QueryStringParser queryStringParser = new QueryStringParser();
@Test
public void noParameters() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost"));
assertThat(parameters.size()).isEqualTo(0);
}
@Test
public void singleParameter() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=alpha"));
assertThat(parameters.size()).isEqualTo(1);
assertThat(parameters).containsEntry("a", Arrays.asList("alpha"));
}
@Test
public void multipleParameters() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=alpha&b=bravo&c=charlie"));
assertThat(parameters.size()).isEqualTo(3);
assertThat(parameters).containsEntry("a", Arrays.asList("alpha"));
assertThat(parameters).containsEntry("b", Arrays.asList("bravo"));
assertThat(parameters).containsEntry("c", Arrays.asList("charlie"));
}
@Test
public void multipleParametersWithSameKey() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=apple&a=avocado"));
assertThat(parameters.size()).isEqualTo(1);
assertThat(parameters).containsEntry("a", Arrays.asList("apple", "avocado"));
}
@Test
public void encoded() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=al%26%3Dpha"));
assertThat(parameters.size()).isEqualTo(1);
assertThat(parameters).containsEntry("a", Arrays.asList("al&=pha"));
}
@Test
public void malformedParameter() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.queryStringParser.parse(URI.create("http://localhost?a=apple=avocado")))
.withMessage("The parameter 'a=apple=avocado' is malformed");
}
@Test
public void emptyParameter() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a="));
assertThat(parameters.size()).isEqualTo(1);
assertThat(parameters).containsEntry("a", Arrays.asList(""));
}
@Test
public void emptyAndNotEmptyParameter() {
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=&a=alpha"));
assertThat(parameters.size()).isEqualTo(1);
assertThat(parameters).containsEntry("a", Arrays.asList("", "alpha"));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2022 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,6 @@ import org.springframework.restdocs.operation.OperationRequestFactory;
import org.springframework.restdocs.operation.OperationRequestPart;
import org.springframework.restdocs.operation.OperationResponse;
import org.springframework.restdocs.operation.OperationResponseFactory;
import org.springframework.restdocs.operation.Parameters;
import static org.assertj.core.api.Assertions.assertThat;
@@ -59,8 +58,7 @@ public class ContentModifyingOperationPreprocessorTests {
@Test
public void modifyRequestContent() {
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
"content".getBytes(), new HttpHeaders(), new Parameters(),
Collections.<OperationRequestPart>emptyList());
"content".getBytes(), new HttpHeaders(), Collections.<OperationRequestPart>emptyList());
OperationRequest preprocessed = this.preprocessor.preprocess(request);
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());
}
@@ -78,7 +76,7 @@ public class ContentModifyingOperationPreprocessorTests {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentLength(7);
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
"content".getBytes(), httpHeaders, new Parameters(), Collections.<OperationRequestPart>emptyList());
"content".getBytes(), httpHeaders, Collections.<OperationRequestPart>emptyList());
OperationRequest preprocessed = this.preprocessor.preprocess(request);
assertThat(preprocessed.getHeaders().getContentLength()).isEqualTo(8L);
}

View File

@@ -31,7 +31,6 @@ import org.springframework.restdocs.operation.OperationRequest;
import org.springframework.restdocs.operation.OperationRequestFactory;
import org.springframework.restdocs.operation.OperationResponse;
import org.springframework.restdocs.operation.OperationResponseFactory;
import org.springframework.restdocs.operation.Parameters;
import static org.assertj.core.api.Assertions.assertThat;
@@ -149,7 +148,7 @@ public class HeadersModifyingOperationPreprocessorTests {
headersCustomizer.accept(headers);
}
return new OperationRequestFactory().create(URI.create("http://localhost:8080"), HttpMethod.GET, new byte[0],
headers, new Parameters(), Collections.emptyList());
headers, Collections.emptyList());
}
private OperationResponse createResponse() {

View File

@@ -32,7 +32,6 @@ 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 org.springframework.restdocs.operation.RequestCookie;
import static org.assertj.core.api.Assertions.assertThat;
@@ -304,41 +303,40 @@ public class UriModifyingOperationPreprocessorTests {
public void resultingRequestHasCookiesFromOriginalRequst() {
List<RequestCookie> cookies = Arrays.asList(new RequestCookie("a", "alpha"));
OperationRequest request = this.requestFactory.create(URI.create("http://localhost:12345"), HttpMethod.GET,
new byte[0], new HttpHeaders(), new Parameters(), Collections.<OperationRequestPart>emptyList(),
cookies);
new byte[0], new HttpHeaders(), Collections.<OperationRequestPart>emptyList(), cookies);
OperationRequest processed = this.preprocessor.preprocess(request);
assertThat(processed.getCookies().size()).isEqualTo(1);
}
private OperationRequest createRequestWithUri(String uri) {
return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0], new HttpHeaders(),
new Parameters(), Collections.<OperationRequestPart>emptyList());
Collections.<OperationRequestPart>emptyList());
}
private OperationRequest createRequestWithContent(String content) {
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, content.getBytes(),
new HttpHeaders(), new Parameters(), Collections.<OperationRequestPart>emptyList());
new HttpHeaders(), Collections.<OperationRequestPart>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.<OperationRequestPart>emptyList());
Collections.<OperationRequestPart>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(),
new HttpHeaders(),
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())));
new HttpHeaders(), Arrays.asList(new OperationRequestPartFactory().create("part", "fileName",
content.getBytes(), new HttpHeaders())));
}
private OperationResponse createResponseWithContent(String content) {

View File

@@ -30,12 +30,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
/**
* Tests for failures when rendering {@link RequestParametersSnippet} due to missing or
* undocumented request parameters.
* Tests for failures when rendering {@link FormParametersSnippet} due to missing or
* undocumented form parameters.
*
* @author Andy Wilkinson
*/
public class RequestParametersSnippetFailureTests {
public class FormParametersSnippetFailureTests {
@Rule
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
@@ -43,25 +43,25 @@ public class RequestParametersSnippetFailureTests {
@Test
public void undocumentedParameter() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new RequestParametersSnippet(Collections.<ParameterDescriptor>emptyList())
.document(this.operationBuilder.request("http://localhost").param("a", "alpha").build()))
.withMessage("Request parameters with the following names were not documented: [a]");
.isThrownBy(() -> new FormParametersSnippet(Collections.<ParameterDescriptor>emptyList())
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build()))
.withMessage("Form parameters with the following names were not documented: [a]");
}
@Test
public void missingParameter() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").build()))
.withMessage("Request parameters with the following names were not found in the request: [a]");
.withMessage("Form parameters with the following names were not found in the request: [a]");
}
@Test
public void undocumentedAndMissingParameters() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").param("b", "bravo").build()))
.withMessage("Request parameters with the following names were not documented: [b]. Request parameters"
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build()))
.withMessage("Form parameters with the following names were not documented: [b]. Form parameters"
+ " with the following names were not found in the request: [a]");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2022 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.
@@ -36,138 +36,134 @@ import static org.springframework.restdocs.snippet.Attributes.attributes;
import static org.springframework.restdocs.snippet.Attributes.key;
/**
* Tests for {@link RequestParametersSnippet}.
* Tests for {@link FormParametersSnippet}.
*
* @author Andy Wilkinson
*/
public class RequestParametersSnippetTests extends AbstractSnippetTests {
public class FormParametersSnippetTests extends AbstractSnippetTests {
public RequestParametersSnippetTests(String name, TemplateFormat templateFormat) {
public FormParametersSnippetTests(String name, TemplateFormat templateFormat) {
super(name, templateFormat);
}
@Test
public void requestParameters() throws IOException {
new RequestParametersSnippet(
public void formParameters() throws IOException {
new FormParametersSnippet(
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost").param("a", "bravo")
.param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void requestParameterWithNoValue() throws IOException {
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").param("a").build());
assertThat(this.generatedSnippets.requestParameters())
public void formParameterWithNoValue() throws IOException {
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").content("a=").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
}
@Test
public void ignoredRequestParameter() throws IOException {
new RequestParametersSnippet(
public void ignoredFormParameter() throws IOException {
new FormParametersSnippet(
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost").param("a", "bravo")
.param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
}
@Test
public void allUndocumentedRequestParametersCanBeIgnored() throws IOException {
new RequestParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true).document(
this.operationBuilder.request("http://localhost").param("a", "bravo").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
public void allUndocumentedFormParametersCanBeIgnored() throws IOException {
new FormParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
}
@Test
public void missingOptionalRequestParameter() throws IOException {
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
public void missingOptionalFormParameter() throws IOException {
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void presentOptionalRequestParameter() throws IOException {
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
.document(this.operationBuilder.request("http://localhost").param("a", "one").build());
assertThat(this.generatedSnippets.requestParameters())
public void presentOptionalFormParameter() throws IOException {
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
}
@Test
public void requestParametersWithCustomAttributes() throws IOException {
public void formParametersWithCustomAttributes() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("request-parameters"))
.willReturn(snippetResource("request-parameters-with-title"));
new RequestParametersSnippet(
given(resolver.resolveTemplateResource("form-parameters"))
.willReturn(snippetResource("form-parameters-with-title"));
new FormParametersSnippet(
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
attributes(key("title").value("The title")))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters()).contains("The title");
.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters()).contains("The title");
}
@Test
public void requestParametersWithCustomDescriptorAttributes() throws IOException {
public void formParametersWithCustomDescriptorAttributes() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("request-parameters"))
.willReturn(snippetResource("request-parameters-with-extra-column"));
new RequestParametersSnippet(
given(resolver.resolveTemplateResource("form-parameters"))
.willReturn(snippetResource("form-parameters-with-extra-column"));
new FormParametersSnippet(
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters()).is(
.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters()).is(
tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
}
@Test
public void requestParametersWithOptionalColumn() throws IOException {
public void formParametersWithOptionalColumn() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("request-parameters"))
.willReturn(snippetResource("request-parameters-with-optional-column"));
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
given(resolver.resolveTemplateResource("form-parameters"))
.willReturn(snippetResource("form-parameters-with-optional-column"));
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
parameterWithName("b").description("two")))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
.is(tableWithHeader("Parameter", "Optional", "Description").row("a", "true", "one").row("b", "false",
"two"));
.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters()).is(tableWithHeader("Parameter", "Optional", "Description")
.row("a", "true", "one").row("b", "false", "two"));
}
@Test
public void additionalDescriptors() throws IOException {
RequestDocumentation.requestParameters(parameterWithName("a").description("one"))
.and(parameterWithName("b").description("two")).document(this.operationBuilder
.request("http://localhost").param("a", "bravo").param("b", "bravo").build());
assertThat(this.generatedSnippets.requestParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void additionalDescriptorsWithRelaxedRequestParameters() throws IOException {
RequestDocumentation.relaxedRequestParameters(parameterWithName("a").description("one"))
RequestDocumentation.formParameters(parameterWithName("a").description("one"))
.and(parameterWithName("b").description("two"))
.document(this.operationBuilder.request("http://localhost").param("a", "bravo").param("b", "bravo")
.param("c", "undocumented").build());
assertThat(this.generatedSnippets.requestParameters())
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void requestParametersWithEscapedContent() throws IOException {
RequestDocumentation.requestParameters(parameterWithName("Foo|Bar").description("one|two"))
.document(this.operationBuilder.request("http://localhost").param("Foo|Bar", "baz").build());
assertThat(this.generatedSnippets.requestParameters()).is(tableWithHeader("Parameter", "Description")
public void additionalDescriptorsWithRelaxedFormParameters() throws IOException {
RequestDocumentation.relaxedFormParameters(parameterWithName("a").description("one"))
.and(parameterWithName("b").description("two")).document(this.operationBuilder
.request("http://localhost").content("a=alpha&b=bravo&c=undocumented").build());
assertThat(this.generatedSnippets.formParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void formParametersWithEscapedContent() throws IOException {
RequestDocumentation.formParameters(parameterWithName("Foo|Bar").description("one|two"))
.document(this.operationBuilder.request("http://localhost").content("Foo%7CBar=baz").build());
assertThat(this.generatedSnippets.formParameters()).is(tableWithHeader("Parameter", "Description")
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs.request;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.restdocs.snippet.SnippetException;
import org.springframework.restdocs.templates.TemplateFormats;
import org.springframework.restdocs.testfixtures.OperationBuilder;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
/**
* Tests for failures when rendering {@link QueryParametersSnippet} due to missing or
* undocumented query parameters.
*
* @author Andy Wilkinson
*/
public class QueryParametersSnippetFailureTests {
@Rule
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
@Test
public void undocumentedParameter() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new QueryParametersSnippet(Collections.<ParameterDescriptor>emptyList())
.document(this.operationBuilder.request("http://localhost?a=alpha").build()))
.withMessage("Query parameters with the following names were not documented: [a]");
}
@Test
public void missingParameter() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost").build()))
.withMessage("Query parameters with the following names were not found in the request: [a]");
}
@Test
public void undocumentedAndMissingParameters() {
assertThatExceptionOfType(SnippetException.class)
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost?b=bravo").build()))
.withMessage("Query parameters with the following names were not documented: [b]. Query parameters"
+ " with the following names were not found in the request: [a]");
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright 2014-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.restdocs.request;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.restdocs.AbstractSnippetTests;
import org.springframework.restdocs.templates.TemplateEngine;
import org.springframework.restdocs.templates.TemplateFormat;
import org.springframework.restdocs.templates.TemplateFormats;
import org.springframework.restdocs.templates.TemplateResourceResolver;
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.snippet.Attributes.attributes;
import static org.springframework.restdocs.snippet.Attributes.key;
/**
* Tests for {@link QueryParametersSnippet}.
*
* @author Andy Wilkinson
*/
public class QueryParametersSnippetTests extends AbstractSnippetTests {
public QueryParametersSnippetTests(String name, TemplateFormat templateFormat) {
super(name, templateFormat);
}
@Test
public void queryParameters() throws IOException {
new QueryParametersSnippet(
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void queryParameterWithNoValue() throws IOException {
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
.document(this.operationBuilder.request("http://localhost?a").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
}
@Test
public void ignoredQueryParameter() throws IOException {
new QueryParametersSnippet(
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
}
@Test
public void allUndocumentedQueryParametersCanBeIgnored() throws IOException {
new QueryParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
}
@Test
public void missingOptionalQueryParameter() throws IOException {
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
parameterWithName("b").description("two")))
.document(this.operationBuilder.request("http://localhost?b=bravo").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void presentOptionalQueryParameter() throws IOException {
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
.document(this.operationBuilder.request("http://localhost?a=alpha").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
}
@Test
public void queryParametersWithCustomAttributes() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("query-parameters"))
.willReturn(snippetResource("query-parameters-with-title"));
new QueryParametersSnippet(
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
attributes(key("title").value("The title")))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters()).contains("The title");
}
@Test
public void queryParametersWithCustomDescriptorAttributes() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("query-parameters"))
.willReturn(snippetResource("query-parameters-with-extra-column"));
new QueryParametersSnippet(
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters()).is(
tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
}
@Test
public void queryParametersWithOptionalColumn() throws IOException {
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
given(resolver.resolveTemplateResource("query-parameters"))
.willReturn(snippetResource("query-parameters-with-optional-column"));
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
parameterWithName("b").description("two")))
.document(this.operationBuilder
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters()).is(tableWithHeader("Parameter", "Optional", "Description")
.row("a", "true", "one").row("b", "false", "two"));
}
@Test
public void additionalDescriptors() throws IOException {
RequestDocumentation.queryParameters(parameterWithName("a").description("one"))
.and(parameterWithName("b").description("two"))
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void additionalDescriptorsWithRelaxedQueryParameters() throws IOException {
RequestDocumentation.relaxedQueryParameters(parameterWithName("a").description("one"))
.and(parameterWithName("b").description("two"))
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo&c=undocumented").build());
assertThat(this.generatedSnippets.queryParameters())
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
}
@Test
public void queryParametersWithEscapedContent() throws IOException {
RequestDocumentation.queryParameters(parameterWithName("Foo|Bar").description("one|two"))
.document(this.operationBuilder.request("http://localhost?Foo%7CBar=baz").build());
assertThat(this.generatedSnippets.queryParameters()).is(tableWithHeader("Parameter", "Description")
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
}
private String escapeIfNecessary(String input) {
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
return input;
}
return input.replace("|", "\\|");
}
}

View File

@@ -0,0 +1,10 @@
|===
|Parameter|Description|Foo
{{#parameters}}
|{{name}}
|{{description}}
|{{foo}}
{{/parameters}}
|===

View File

@@ -0,0 +1,10 @@
|===
|Parameter|Optional|Description
{{#parameters}}
|{{name}}
|{{optional}}
|{{description}}
{{/parameters}}
|===

View File

@@ -0,0 +1,10 @@
.{{title}}
|===
|Parameter|Description
{{#parameters}}
|{{name}}
|{{description}}
{{/parameters}}
|===

View File

@@ -0,0 +1,5 @@
Parameter | Description | Foo
--------- | ----------- | ---
{{#parameters}}
{{name}} | {{description}} | {{foo}}
{{/parameters}}

View File

@@ -0,0 +1,5 @@
Parameter | Optional | Description
--------- | -------- | -----------
{{#parameters}}
{{name}} | {{optional}} | {{description}}
{{/parameters}}

View File

@@ -0,0 +1,6 @@
{{title}}
Parameter | Description
--------- | -----------
{{#parameters}}
{{name}} | {{description}}
{{/parameters}}