Polish "Add support for documenting request part payload fields"

- Rebase on latest code, and make use of new support for the same
  TemplatedSnippet producing multiple snippets with different names
  from the same template
- Expand the documentation
- Apply code formatting
- Add support for relaxed documentation of a request part's fields

Closes gh-270
This commit is contained in:
Andy Wilkinson
2016-10-25 12:04:43 +01:00
parent 13e745a9a9
commit d2a5b38c83
12 changed files with 559 additions and 181 deletions

View File

@@ -26,7 +26,6 @@ import org.junit.rules.ExpectedException;
import org.springframework.restdocs.snippet.SnippetException;
import org.springframework.restdocs.templates.TemplateFormats;
import org.springframework.restdocs.test.ExpectedSnippet;
import org.springframework.restdocs.test.OperationBuilder;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -38,11 +37,13 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit
* undocumented fields.
*
* @author Mathieu Pousse
* @author Andy Wilkinson
*/
public class RequestPartsFieldsSnippetFailureTests {
public class RequestPartFieldsSnippetFailureTests {
@Rule
public ExpectedSnippet snippet = new ExpectedSnippet(TemplateFormats.asciidoctor());
public OperationBuilder operationBuilder = new OperationBuilder(
TemplateFormats.asciidoctor());
@Rule
public ExpectedException thrown = ExpectedException.none();
@@ -50,33 +51,33 @@ public class RequestPartsFieldsSnippetFailureTests {
@Test
public void undocumentedRequestPartField() throws IOException {
this.thrown.expect(SnippetException.class);
this.thrown.expectMessage(startsWith(
"The following parts of the payload were not" + " documented:"));
this.thrown.expectMessage(
startsWith("The following parts of the payload were not documented:"));
new RequestPartFieldsSnippet("part", Collections.<FieldDescriptor>emptyList())
.document(new OperationBuilder("undocumented-request-field",
this.snippet.getOutputDirectory()).request("http://localhost")
.part("part", "{\"a\": 5}".getBytes()).build());
.document(this.operationBuilder.request("http://localhost")
.part("part", "{\"a\": 5}".getBytes()).build());
}
@Test
public void missingRequestPartField() throws IOException {
this.thrown.expect(SnippetException.class);
this.thrown.expectMessage(startsWith(
"The following parts of the payload were not" + " documented:"));
new RequestPartFieldsSnippet("part", Arrays.asList(fieldWithPath("b").description("one")))
.document(new OperationBuilder("undocumented-request-field",
this.snippet.getOutputDirectory()).request("http://localhost")
.part("part", "{\"a\": 5}".getBytes()).build());
this.thrown.expectMessage(
startsWith("The following parts of the payload were not documented:"));
new RequestPartFieldsSnippet("part",
Arrays.asList(fieldWithPath("b").description("one")))
.document(this.operationBuilder.request("http://localhost")
.part("part", "{\"a\": 5}".getBytes()).build());
}
@Test
public void missingRequestPart() throws IOException {
this.thrown.expect(SnippetException.class);
this.thrown.expectMessage(equalTo("Request parts with the following names were not found in the request: another"));
new RequestPartFieldsSnippet("another", Arrays.asList(fieldWithPath("a.b").description("one")))
.document(new OperationBuilder("missing-request-fields",
this.snippet.getOutputDirectory()).request("http://localhost")
.part("part", "{\"a\": {\"b\": 5}}".getBytes()).build());
this.thrown.expectMessage(
equalTo("A request part named 'another' was not found in the request"));
new RequestPartFieldsSnippet("another",
Arrays.asList(fieldWithPath("a.b").description("one")))
.document(this.operationBuilder.request("http://localhost")
.part("part", "{\"a\": {\"b\": 5}}".getBytes()).build());
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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.payload;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.springframework.restdocs.AbstractSnippetTests;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.templates.TemplateFormat;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
/**
* Tests for {@link RequestPartFieldsSnippet}.
*
* @author Mathieu Pousse
* @author Andy Wilkinson
*/
public class RequestPartFieldsSnippetTests extends AbstractSnippetTests {
public RequestPartFieldsSnippetTests(String name, TemplateFormat templateFormat) {
super(name, templateFormat);
}
@Test
public void mapRequestPartFields() throws IOException {
this.snippets.expectRequestPartFields("one")
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a.b`", "`Number`", "one").row("`a.c`", "`String`", "two")
.row("`a`", "`Object`", "three"));
new RequestPartFieldsSnippet("one",
Arrays.asList(fieldWithPath("a.b").description("one"),
fieldWithPath("a.c").description("two"), fieldWithPath("a")
.description("three")))
.document(
this.operationBuilder
.request("http://localhost")
.part("one",
"{\"a\": {\"b\": 5, \"c\": \"charlie\"}}"
.getBytes())
.build());
}
@Test
public void multipleRequestParts() throws IOException {
this.snippets.expectRequestPartFields("one");
this.snippets.expectRequestPartFields("two");
Operation operation = this.operationBuilder.request("http://localhost")
.part("one", "{}".getBytes()).and().part("two", "{}".getBytes()).build();
new RequestPartFieldsSnippet("one", Collections.<FieldDescriptor>emptyList())
.document(operation);
new RequestPartFieldsSnippet("two", Collections.<FieldDescriptor>emptyList())
.document(operation);
}
@Test
public void allUndocumentedRequestPartFieldsCanBeIgnored() throws IOException {
this.snippets.expectRequestPartFields("one")
.withContents(tableWithHeader("Path", "Type", "Description").row("`b`",
"`Number`", "Field b"));
new RequestPartFieldsSnippet("one",
Arrays.asList(fieldWithPath("b").description("Field b")), true)
.document(this.operationBuilder.request("http://localhost")
.part("one", "{\"a\": 5, \"b\": 4}".getBytes()).build());
}
@Test
public void additionalDescriptors() throws IOException {
this.snippets.expectRequestPartFields("one")
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a.b`", "`Number`", "one").row("`a.c`", "`String`", "two")
.row("`a`", "`Object`", "three"));
PayloadDocumentation
.requestPartFields("one", fieldWithPath("a.b").description("one"),
fieldWithPath("a.c").description("two"))
.and(fieldWithPath("a").description("three"))
.document(this.operationBuilder.request("http://localhost")
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
.build());
}
@Test
public void prefixedAdditionalDescriptors() throws IOException {
this.snippets.expectRequestPartFields("one")
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a`", "`Object`", "one").row("`a.b`", "`Number`", "two")
.row("`a.c`", "`String`", "three"));
PayloadDocumentation
.requestPartFields("one", fieldWithPath("a").description("one"))
.andWithPrefix("a.", fieldWithPath("b").description("two"),
fieldWithPath("c").description("three"))
.document(this.operationBuilder.request("http://localhost")
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
.build());
}
}

View File

@@ -1,56 +0,0 @@
/*
* 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.payload;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.restdocs.AbstractSnippetTests;
import org.springframework.restdocs.templates.TemplateFormat;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
/**
* Tests for {@link RequestPartFieldsSnippet}.
*
* @author Mathieu Pousse
*/
public class RequestPartsFieldsSnippetTests extends AbstractSnippetTests {
public RequestPartsFieldsSnippetTests(String name, TemplateFormat templateFormat) {
super(name, templateFormat);
}
@Test
public void mapRequestWithFields() throws IOException {
this.snippet.expectRequestFields("map-request-parts-with-fields")
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a.b`", "`Number`", "one").row("`a.c`", "`String`", "two")
.row("`a`", "`Object`", "three"));
new RequestPartFieldsSnippet("part", Arrays.asList(fieldWithPath("a.b").description("one"),
fieldWithPath("a.c").description("two"),
fieldWithPath("a").description("three")))
.document(operationBuilder("map-request-parts-with-fields")
.request("http://localhost")
.part("part", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
.build());
}
}

View File

@@ -81,6 +81,10 @@ public class ExpectedSnippets extends OperationTestRule {
return expect("request-fields");
}
public ExpectedSnippet expectRequestPartFields(String partName) {
return expect("request-part-" + partName + "-fields");
}
public ExpectedSnippet expectResponseFields() {
return expect("response-fields");
}