Add support for documenting request part payload fields
See gh-270
This commit is contained in:
committed by
Andy Wilkinson
parent
4f19294220
commit
13e745a9a9
@@ -148,6 +148,56 @@ public abstract class PayloadDocumentation {
|
||||
return new RequestFieldsSnippet(descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code Snippet} that will document the fields of the specified {@code part}
|
||||
* of the API operations's request payload. The fields will be documented using the
|
||||
* given {@code descriptors}.
|
||||
* <p>
|
||||
* If a field is present in the request payload, but is not documented by one of the
|
||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||
* field is documented, is not marked as optional, and is not present in the request,
|
||||
* a failure will also occur. For payloads with a hierarchical structure, documenting
|
||||
* a field is sufficient for all of its descendants to also be treated as having been
|
||||
* documented.
|
||||
* <p>
|
||||
* If you do not want to document a field, a field descriptor can be marked as
|
||||
* {@link FieldDescriptor#ignored}. This will prevent it from appearing in the
|
||||
* generated snippet while avoiding the failure described above.
|
||||
*
|
||||
* @param part the part name
|
||||
* @param descriptors the descriptions of the request payload's fields
|
||||
* @return the snippet that will document the fields
|
||||
* @see #fieldWithPath(String)
|
||||
*/
|
||||
public static RequestPartFieldsSnippet requestPartFields(String part, FieldDescriptor... descriptors) {
|
||||
return requestPartFields(part, Arrays.asList(descriptors));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code Snippet} that will document the fields of the specified {@code part}
|
||||
* of the API operations's request payload. The fields will be documented using the given
|
||||
* {@code descriptors}.
|
||||
* <p>
|
||||
* If a field is present in the request payload, but is not documented by one of the
|
||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||
* field is documented, is not marked as optional, and is not present in the request,
|
||||
* a failure will also occur. For payloads with a hierarchical structure, documenting
|
||||
* a field is sufficient for all of its descendants to also be treated as having been
|
||||
* documented.
|
||||
* <p>
|
||||
* If you do not want to document a field, a field descriptor can be marked as
|
||||
* {@link FieldDescriptor#ignored}. This will prevent it from appearing in the
|
||||
* generated snippet while avoiding the failure described above.
|
||||
*
|
||||
* @param part the part name
|
||||
* @param descriptors the descriptions of the request payload's fields
|
||||
* @return the snippet that will document the fields
|
||||
* @see #fieldWithPath(String)
|
||||
*/
|
||||
public static RequestPartFieldsSnippet requestPartFields(String part, List<FieldDescriptor> descriptors) {
|
||||
return new RequestPartFieldsSnippet(part, descriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code Snippet} that will document the fields of the API operations's
|
||||
* request payload. The fields will be documented using the given {@code descriptors}.
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
|
||||
/**
|
||||
* A {@link Snippet} that documents the fields in a request.
|
||||
*
|
||||
* @author Mathieu Pousse
|
||||
* @see PayloadDocumentation#requestPartFields(String, FieldDescriptor...)
|
||||
*/
|
||||
public class RequestPartFieldsSnippet extends AbstractFieldsSnippet {
|
||||
|
||||
private final String partName;
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestPartFieldsSnippet} that will document the fields in the
|
||||
* request part using the given {@code descriptors}. Undocumented fields will trigger a
|
||||
* failure.
|
||||
*
|
||||
* @param partName the part name
|
||||
* @param descriptors the descriptors
|
||||
*/
|
||||
protected RequestPartFieldsSnippet(String partName, List<FieldDescriptor> descriptors) {
|
||||
this(partName, descriptors, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestPartFieldsSnippet} that will document the fields in the
|
||||
* request part using the given {@code descriptors}. If {@code ignoreUndocumentedFields} is
|
||||
* {@code true}, undocumented fields will be ignored and will not trigger a failure.
|
||||
*
|
||||
* @param partName the part name
|
||||
* @param descriptors the descriptors
|
||||
* @param ignoreUndocumentedFields whether undocumented fields should be ignored
|
||||
*/
|
||||
protected RequestPartFieldsSnippet(String partName, List<FieldDescriptor> descriptors,
|
||||
boolean ignoreUndocumentedFields) {
|
||||
this(partName, descriptors, null, ignoreUndocumentedFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestFieldsSnippet} that will document the fields in the
|
||||
* request using the given {@code descriptors}. The given {@code attributes} will be
|
||||
* included in the model during template rendering. Undocumented fields will trigger a
|
||||
* failure.
|
||||
*
|
||||
* @param partName the part name
|
||||
* @param descriptors the descriptors
|
||||
* @param attributes the additional attributes
|
||||
*/
|
||||
protected RequestPartFieldsSnippet(String partName, List<FieldDescriptor> descriptors,
|
||||
Map<String, Object> attributes) {
|
||||
this(partName, descriptors, attributes, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestFieldsSnippet} that will document the fields in the
|
||||
* request using the given {@code descriptors}. The given {@code attributes} will be
|
||||
* included in the model during template rendering. If
|
||||
* {@code ignoreUndocumentedFields} is {@code true}, undocumented fields will be
|
||||
* ignored and will not trigger a failure.
|
||||
*
|
||||
* @param partName the part name
|
||||
* @param descriptors the descriptors
|
||||
* @param attributes the additional attributes
|
||||
* @param ignoreUndocumentedFields whether undocumented fields should be ignored
|
||||
*/
|
||||
protected RequestPartFieldsSnippet(String partName, List<FieldDescriptor> descriptors,
|
||||
Map<String, Object> attributes, boolean ignoreUndocumentedFields) {
|
||||
super("request", descriptors, attributes, ignoreUndocumentedFields);
|
||||
this.partName = partName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MediaType getContentType(Operation operation) {
|
||||
for (OperationRequestPart candidate : operation.getRequest().getParts()) {
|
||||
if (candidate.getName().equals(this.partName)) {
|
||||
return candidate.getHeaders().getContentType();
|
||||
}
|
||||
}
|
||||
throw new SnippetException(missingPartErrorMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getContent(Operation operation) throws IOException {
|
||||
for (OperationRequestPart candidate : operation.getRequest().getParts()) {
|
||||
if (candidate.getName().equals(this.partName)) {
|
||||
return candidate.getContent();
|
||||
}
|
||||
}
|
||||
throw new SnippetException(missingPartErrorMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the error message because the requested part was not found.
|
||||
*
|
||||
* @return see description
|
||||
*/
|
||||
protected String missingPartErrorMessage() {
|
||||
return "Request parts with the following names were not found in the request: " + this.partName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestPartFieldsSnippet} configured with this snippet's
|
||||
* attributes and its descriptors combined with the given
|
||||
* {@code additionalDescriptors}.
|
||||
*
|
||||
* @param additionalDescriptors the additional descriptors
|
||||
* @return the new snippet
|
||||
*/
|
||||
public final RequestPartFieldsSnippet and(FieldDescriptor... additionalDescriptors) {
|
||||
return andWithPrefix("", additionalDescriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestPartFieldsSnippet} configured with this snippet's
|
||||
* attributes and its descriptors combined with the given
|
||||
* {@code additionalDescriptors}.
|
||||
*
|
||||
* @param additionalDescriptors the additional descriptors
|
||||
* @return the new snippet
|
||||
*/
|
||||
public final RequestPartFieldsSnippet and(List<FieldDescriptor> additionalDescriptors) {
|
||||
return andWithPrefix("", additionalDescriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestFieldsSnippet} configured with this snippet's
|
||||
* attributes and its descriptors combined with the given
|
||||
* {@code additionalDescriptors}. The given {@code pathPrefix} is applied to the path
|
||||
* of each additional descriptor.
|
||||
*
|
||||
* @param pathPrefix the prefix to apply to the additional descriptors
|
||||
* @param additionalDescriptors the additional descriptors
|
||||
* @return the new snippet
|
||||
*/
|
||||
public final RequestPartFieldsSnippet andWithPrefix(String pathPrefix,
|
||||
FieldDescriptor... additionalDescriptors) {
|
||||
List<FieldDescriptor> combinedDescriptors = new ArrayList<>();
|
||||
combinedDescriptors.addAll(getFieldDescriptors());
|
||||
combinedDescriptors.addAll(
|
||||
PayloadDocumentation.applyPathPrefix(pathPrefix, Arrays.asList(additionalDescriptors)));
|
||||
return new RequestPartFieldsSnippet(this.partName, combinedDescriptors, this.getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestFieldsSnippet} configured with this snippet's
|
||||
* attributes and its descriptors combined with the given
|
||||
* {@code additionalDescriptors}. The given {@code pathPrefix} is applied to the path
|
||||
* of each additional descriptor.
|
||||
*
|
||||
* @param pathPrefix the prefix to apply to the additional descriptors
|
||||
* @param additionalDescriptors the additional descriptors
|
||||
* @return the new snippet
|
||||
*/
|
||||
public final RequestPartFieldsSnippet andWithPrefix(String pathPrefix,
|
||||
List<FieldDescriptor> additionalDescriptors) {
|
||||
List<FieldDescriptor> combinedDescriptors = new ArrayList<>(
|
||||
getFieldDescriptors());
|
||||
combinedDescriptors.addAll(
|
||||
PayloadDocumentation.applyPathPrefix(pathPrefix, additionalDescriptors));
|
||||
return new RequestPartFieldsSnippet(this.partName, combinedDescriptors, this.getAttributes());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user