Add support for generating snippets in Markdown
This commit introduces support for generating snippets formatted using Markdown. Asciidoctor remains the default. A new SnippetFormat abstraction has been introduced with Asciidoctor and Markdown implementations provided out of the box. Markdown-formatted templates are also provided for all of the default snippets. Please refer to the updated reference documentation for further details. Closes gh-150 Closes gh-19
This commit is contained in:
@@ -73,7 +73,7 @@
|
||||
<module name="AvoidStarImport" />
|
||||
<module name="AvoidStaticImport">
|
||||
<property name="excludes"
|
||||
value="com.jayway.restassured.RestAssured.*, org.junit.Assert.*, org.junit.Assume.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.springframework.restdocs.curl.CurlDocumentation.*, org.springframework.restdocs.headers.HeaderDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.IterableEnumeration.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*, org.springframework.restdocs.payload.PayloadDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.restassured.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.snippet.Attributes.*, org.springframework.restdocs.test.SnippetMatchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*" />
|
||||
value="com.jayway.restassured.RestAssured.*, org.junit.Assert.*, org.junit.Assume.*, org.hamcrest.CoreMatchers.*, org.hamcrest.Matchers.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.Matchers.*, org.springframework.restdocs.curl.CurlDocumentation.*, org.springframework.restdocs.headers.HeaderDocumentation.*, org.springframework.restdocs.hypermedia.HypermediaDocumentation.*, org.springframework.restdocs.mockmvc.IterableEnumeration.*, org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*, org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*, org.springframework.restdocs.payload.PayloadDocumentation.*, org.springframework.restdocs.operation.preprocess.Preprocessors.*, org.springframework.restdocs.request.RequestDocumentation.*, org.springframework.restdocs.restassured.RestAssuredRestDocumentation.*, org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.*, org.springframework.restdocs.snippet.Attributes.*, org.springframework.restdocs.snippet.SnippetFormats.*, org.springframework.restdocs.test.SnippetMatchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*" />
|
||||
</module>
|
||||
<module name="IllegalImport" />
|
||||
<module name="RedundantImport" />
|
||||
|
||||
@@ -42,8 +42,7 @@ TIP: To configure a request's context path, use the `contextPath` method on
|
||||
[[configuration-snippet-encoding]]
|
||||
=== Snippet encoding
|
||||
|
||||
The default encoding used by Asciidoctor is `UTF-8`. Spring REST Docs adopts the same
|
||||
default for the snippets that it generates. You can change the default snippet encoding
|
||||
The default snippet encoding is `UTF-8`. You can change the default snippet encoding
|
||||
using the `RestDocumentationConfigurer` API. For example, to use `ISO-8859-1`:
|
||||
|
||||
[source,java,indent=0,role="primary"]
|
||||
@@ -60,6 +59,26 @@ include::{examples-dir}/com/example/restassured/CustomEncoding.java[tags=custom-
|
||||
|
||||
|
||||
|
||||
[[configuration-snippet-format]]
|
||||
=== Snippet format
|
||||
|
||||
The default snippet format is Asciidoctor. Markdown is also supported out of the box. You
|
||||
can change the default format using the `RestDocumentationConfigurer` API:
|
||||
|
||||
[source,java,indent=0,role="primary"]
|
||||
.MockMvc
|
||||
----
|
||||
include::{examples-dir}/com/example/mockmvc/CustomFormat.java[tags=custom-format]
|
||||
----
|
||||
|
||||
[source,java,indent=0,role="secondary"]
|
||||
.REST Assured
|
||||
----
|
||||
include::{examples-dir}/com/example/restassured/CustomFormat.java[tags=custom-format]
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[configuration-default-snippets]]
|
||||
=== Default snippets
|
||||
|
||||
|
||||
@@ -26,4 +26,5 @@ include::documenting-your-api.adoc[]
|
||||
include::customizing-requests-and-responses.adoc[]
|
||||
include::configuration.adoc[]
|
||||
include::working-with-asciidoctor.adoc[]
|
||||
include::working-with-markdown.adoc[]
|
||||
include::contributing.adoc[]
|
||||
@@ -6,8 +6,9 @@ services that is accurate and readable.
|
||||
|
||||
Writing high-quality documentation is difficult. One way to ease that difficulty is to use
|
||||
tools that are well-suited to the job. To this end, Spring REST Docs uses
|
||||
http://asciidoctor.org[Asciidoctor]. Asciidoctor processes plain text and produces
|
||||
HTML, styled and layed out to suit your needs.
|
||||
http://asciidoctor.org[Asciidoctor] by default. Asciidoctor processes plain text and
|
||||
produces HTML, styled and layed out to suit your needs. If you prefer, Spring REST Docs
|
||||
can also be configured to use Markdown.
|
||||
|
||||
Spring REST Docs makes use of snippets produced by tests written with
|
||||
{spring-framework-docs}/#spring-mvc-test-framework[Spring MVC Test] or
|
||||
|
||||
28
docs/src/docs/asciidoc/working-with-markdown.adoc
Normal file
28
docs/src/docs/asciidoc/working-with-markdown.adoc
Normal file
@@ -0,0 +1,28 @@
|
||||
[[working-with-markdown]]
|
||||
== Working with Markdown
|
||||
|
||||
This section describes any aspects of working with Markdown that are particularly
|
||||
relevant to Spring REST Docs.
|
||||
|
||||
|
||||
|
||||
[[working-with-markdown-limitations]]
|
||||
=== Limitations
|
||||
|
||||
Markdown was originally designed for people writing for the web and, as such, isn't
|
||||
as well-suited to writing documentation as Asciidoctor. Typically, these limitations
|
||||
are overcome by using another tool that builds on top of Markdown.
|
||||
|
||||
Markdown has no official support for tables. Spring REST Docs' default Markdown snippet
|
||||
templates use https://michelf.ca/projects/php-markdown/extra/#table[Markdown Extra's table
|
||||
format].
|
||||
|
||||
|
||||
|
||||
[[working-with-markdown-including-snippets]]
|
||||
=== Including snippets
|
||||
|
||||
Markdown has no built-in support for including one Markdown file in another. To include
|
||||
the generated snippets of Markdown in your documentation, you should use an additional
|
||||
tool that supports this functionality. One example that's particularly well-suited to
|
||||
documenting APIs is https://github.com/tripit/slate[Slate].
|
||||
50
docs/src/test/java/com/example/mockmvc/CustomFormat.java
Normal file
50
docs/src/test/java/com/example/mockmvc/CustomFormat.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 com.example.mockmvc;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
public class CustomFormat {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// tag::custom-format[]
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withFormat(SnippetFormats.markdown()))
|
||||
.build();
|
||||
// end::custom-format[]
|
||||
}
|
||||
|
||||
}
|
||||
46
docs/src/test/java/com/example/restassured/CustomFormat.java
Normal file
46
docs/src/test/java/com/example/restassured/CustomFormat.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 com.example.restassured;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.restdocs.RestDocumentation;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
public class CustomFormat {
|
||||
|
||||
@Rule
|
||||
public final RestDocumentation restDocumentation = new RestDocumentation("build");
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// tag::custom-format[]
|
||||
this.spec = new RequestSpecBuilder()
|
||||
.addFilter(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withFormat(SnippetFormats.markdown()))
|
||||
.build();
|
||||
// end::custom-format[]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,13 +93,20 @@ public abstract class RestDocumentationConfigurer<S, T> {
|
||||
|
||||
private static final class TemplateEngineConfigurer extends AbstractConfigurer {
|
||||
|
||||
private TemplateEngine templateEngine = new MustacheTemplateEngine(
|
||||
new StandardTemplateResourceResolver());
|
||||
private TemplateEngine templateEngine;
|
||||
|
||||
@Override
|
||||
public void apply(Map<String, Object> configuration,
|
||||
RestDocumentationContext context) {
|
||||
configuration.put(TemplateEngine.class.getName(), this.templateEngine);
|
||||
TemplateEngine engineToUse = this.templateEngine;
|
||||
if (engineToUse == null) {
|
||||
SnippetConfiguration snippetConfiguration = (SnippetConfiguration) configuration
|
||||
.get(SnippetConfiguration.class.getName());
|
||||
engineToUse = new MustacheTemplateEngine(
|
||||
new StandardTemplateResourceResolver(
|
||||
snippetConfiguration.getFormat()));
|
||||
}
|
||||
configuration.put(TemplateEngine.class.getName(), engineToUse);
|
||||
}
|
||||
|
||||
private void setTemplateEngine(TemplateEngine templateEngine) {
|
||||
@@ -117,8 +124,12 @@ public abstract class RestDocumentationConfigurer<S, T> {
|
||||
RestDocumentationContext context) {
|
||||
WriterResolver resolverToUse = this.writerResolver;
|
||||
if (resolverToUse == null) {
|
||||
SnippetConfiguration snippetConfiguration = (SnippetConfiguration) configuration
|
||||
.get(SnippetConfiguration.class.getName());
|
||||
resolverToUse = new StandardWriterResolver(
|
||||
new RestDocumentationContextPlaceholderResolver(context));
|
||||
new RestDocumentationContextPlaceholderResolver(context),
|
||||
snippetConfiguration.getEncoding(),
|
||||
snippetConfiguration.getFormat());
|
||||
}
|
||||
configuration.put(WriterResolver.class.getName(), resolverToUse);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
|
||||
/**
|
||||
* An encapsulation of the configuration for documentation snippets.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class SnippetConfiguration {
|
||||
|
||||
private final String encoding;
|
||||
|
||||
private final SnippetFormat format;
|
||||
|
||||
SnippetConfiguration(String encoding, SnippetFormat format) {
|
||||
this.encoding = encoding;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
String getEncoding() {
|
||||
return this.encoding;
|
||||
}
|
||||
|
||||
SnippetFormat getFormat() {
|
||||
return this.format;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,8 @@ import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.curl.CurlDocumentation;
|
||||
import org.springframework.restdocs.http.HttpDocumentation;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
import org.springframework.restdocs.snippet.WriterResolver;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
|
||||
/**
|
||||
* A configurer that can be used to configure the generated documentation snippets.
|
||||
@@ -51,8 +52,18 @@ public abstract class SnippetConfigurer<P, T> extends AbstractNestedConfigurer<P
|
||||
*/
|
||||
public static final String DEFAULT_SNIPPET_ENCODING = "UTF-8";
|
||||
|
||||
/**
|
||||
* The default format for documentation snippets.
|
||||
*
|
||||
* @see #withFormat(SnippetFormat)
|
||||
*/
|
||||
public static final SnippetFormat DEFAULT_SNIPPET_FORMAT = SnippetFormats
|
||||
.asciidoctor();
|
||||
|
||||
private String snippetEncoding = DEFAULT_SNIPPET_ENCODING;
|
||||
|
||||
private SnippetFormat snippetFormat = DEFAULT_SNIPPET_FORMAT;
|
||||
|
||||
/**
|
||||
* Creates a new {@code SnippetConfigurer} with the given {@code parent}.
|
||||
*
|
||||
@@ -64,8 +75,8 @@ public abstract class SnippetConfigurer<P, T> extends AbstractNestedConfigurer<P
|
||||
|
||||
@Override
|
||||
public void apply(Map<String, Object> configuration, RestDocumentationContext context) {
|
||||
((WriterResolver) configuration.get(WriterResolver.class.getName()))
|
||||
.setEncoding(this.snippetEncoding);
|
||||
configuration.put(SnippetConfiguration.class.getName(), new SnippetConfiguration(
|
||||
this.snippetEncoding, this.snippetFormat));
|
||||
configuration.put(ATTRIBUTE_DEFAULT_SNIPPETS, this.defaultSnippets);
|
||||
}
|
||||
|
||||
@@ -93,4 +104,17 @@ public abstract class SnippetConfigurer<P, T> extends AbstractNestedConfigurer<P
|
||||
this.defaultSnippets = Arrays.asList(defaultSnippets);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the format of the documentation snippets.
|
||||
*
|
||||
* @param format the snippet format
|
||||
* @return {@code this}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withFormat(SnippetFormat format) {
|
||||
this.snippetFormat = format;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.snippet;
|
||||
|
||||
/**
|
||||
* A {@link SnippetFormat} provides information about a particular snippet format, such as
|
||||
* Asciidoctor or Markdown.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface SnippetFormat {
|
||||
|
||||
/**
|
||||
* Returns the snippet format's file extension.
|
||||
*
|
||||
* @return the file extension
|
||||
*/
|
||||
String getFileExtension();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.snippet;
|
||||
|
||||
/**
|
||||
* An enumeration of the built-in snippet formats.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class SnippetFormats {
|
||||
|
||||
private static final SnippetFormat ASCIIDOCTOR = new AsciidoctorSnippetFormat();
|
||||
|
||||
private static final SnippetFormat MARKDOWN = new MarkdownSnippetFormat();
|
||||
|
||||
private SnippetFormats() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Asciidoctor snippet format.
|
||||
*
|
||||
* @return the snippet format
|
||||
*/
|
||||
public static SnippetFormat asciidoctor() {
|
||||
return ASCIIDOCTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Markdown snippet format.
|
||||
*
|
||||
* @return the snippet format
|
||||
*/
|
||||
public static SnippetFormat markdown() {
|
||||
return MARKDOWN;
|
||||
}
|
||||
|
||||
private static final class AsciidoctorSnippetFormat implements SnippetFormat {
|
||||
|
||||
private static final String FILE_EXTENSION = "adoc";
|
||||
|
||||
@Override
|
||||
public String getFileExtension() {
|
||||
return FILE_EXTENSION;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class MarkdownSnippetFormat implements SnippetFormat {
|
||||
|
||||
private static final String FILE_EXTENSION = "md";
|
||||
|
||||
@Override
|
||||
public String getFileExtension() {
|
||||
return FILE_EXTENSION;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -33,29 +33,54 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
*/
|
||||
public final class StandardWriterResolver implements WriterResolver {
|
||||
|
||||
private String encoding = "UTF-8";
|
||||
|
||||
private final PlaceholderResolver placeholderResolver;
|
||||
|
||||
private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper(
|
||||
"{", "}");
|
||||
|
||||
private String encoding = "UTF-8";
|
||||
|
||||
private SnippetFormat snippetFormat;
|
||||
|
||||
/**
|
||||
* Creates a new {@code StandardWriterResolver} that will use the given
|
||||
* {@code placeholderResolver} to resolve any placeholders in the
|
||||
* {@code operationName}.
|
||||
* {@code operationName}. Writers will use {@code UTF-8} encoding and, when writing to
|
||||
* a file, will use a filename appropriate for Asciidoctor content.
|
||||
*
|
||||
* @param placeholderResolver the placeholder resolver
|
||||
* @deprecated since 1.1.0 in favor of
|
||||
* {@link #StandardWriterResolver(PropertyPlaceholderHelper.PlaceholderResolver, String, SnippetFormat)}
|
||||
*/
|
||||
@Deprecated
|
||||
public StandardWriterResolver(PlaceholderResolver placeholderResolver) {
|
||||
this(placeholderResolver, "UTF-8", SnippetFormats.asciidoctor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code StandardWriterResolver} that will use the given
|
||||
* {@code placeholderResolver} to resolve any placeholders in the
|
||||
* {@code operationName}. Writers will use the given {@code encoding} and, when
|
||||
* writing to a file, will use a filename appropriate for content in the given
|
||||
* {@code snippetFormat}.
|
||||
*
|
||||
* @param placeholderResolver the placeholder resolver
|
||||
* @param encoding the encoding
|
||||
* @param snippetFormat the snippet format
|
||||
*/
|
||||
public StandardWriterResolver(PlaceholderResolver placeholderResolver,
|
||||
String encoding, SnippetFormat snippetFormat) {
|
||||
this.placeholderResolver = placeholderResolver;
|
||||
this.encoding = encoding;
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer resolve(String operationName, String snippetName,
|
||||
RestDocumentationContext context) throws IOException {
|
||||
File outputFile = resolveFile(this.propertyPlaceholderHelper.replacePlaceholders(
|
||||
operationName, this.placeholderResolver), snippetName + ".adoc", context);
|
||||
operationName, this.placeholderResolver), snippetName + "."
|
||||
+ this.snippetFormat.getFileExtension(), context);
|
||||
|
||||
if (outputFile != null) {
|
||||
createDirectoriesIfNecessary(outputFile);
|
||||
@@ -95,4 +120,5 @@ public final class StandardWriterResolver implements WriterResolver {
|
||||
throw new IllegalStateException("Failed to create directory '" + parent + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -47,7 +47,10 @@ public interface WriterResolver {
|
||||
* resolver.
|
||||
*
|
||||
* @param encoding the encoding
|
||||
* @deprecated since 1.1.0 in favour of configuring the encoding when to resolver is
|
||||
* created
|
||||
*/
|
||||
@Deprecated
|
||||
void setEncoding(String encoding);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,27 +18,54 @@ package org.springframework.restdocs.templates;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
|
||||
/**
|
||||
* Standard implementation of {@link TemplateResourceResolver}.
|
||||
* <p>
|
||||
* Templates are resolved by first looking for a resource on the classpath named
|
||||
* Templates are resolved by looking for a resource on the classpath named
|
||||
* {@code org/springframework/restdocs/templates/{name}.snippet}. If no such
|
||||
* resource exists {@code default-} is prepended to the name and the classpath is checked
|
||||
* again. The built-in snippet templates are all named {@code default- name}, thereby
|
||||
* allowing them to be overridden.
|
||||
* resource exists an attempt is made to return a default resource that is appropriate for
|
||||
* the configured snippet format.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class StandardTemplateResourceResolver implements TemplateResourceResolver {
|
||||
|
||||
private final SnippetFormat snippetFormat;
|
||||
|
||||
/**
|
||||
* Creates a new {@code StandardTemplateResourceResolver} that will produce default
|
||||
* template resources formatted with Asciidoctor.
|
||||
*
|
||||
* @deprecated since 1.1.0 in favour of
|
||||
* {@link #StandardTemplateResourceResolver(SnippetFormat)}
|
||||
*/
|
||||
@Deprecated
|
||||
public StandardTemplateResourceResolver() {
|
||||
this(SnippetFormats.asciidoctor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code StandardTemplateResourceResolver} that will produce default
|
||||
* template resources formatted with the given {@code snippetFormat}.
|
||||
*
|
||||
* @param snippetFormat the format for the default snippet templates
|
||||
*/
|
||||
public StandardTemplateResourceResolver(SnippetFormat snippetFormat) {
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource resolveTemplateResource(String name) {
|
||||
ClassPathResource classPathResource = new ClassPathResource(
|
||||
"org/springframework/restdocs/templates/" + name + ".snippet");
|
||||
if (!classPathResource.exists()) {
|
||||
classPathResource = new ClassPathResource(
|
||||
"org/springframework/restdocs/templates/default-" + name + ".snippet");
|
||||
"org/springframework/restdocs/templates/"
|
||||
+ this.snippetFormat.getFileExtension() + "/" + name
|
||||
+ ".snippet");
|
||||
if (!classPathResource.exists()) {
|
||||
throw new IllegalStateException("Template named '" + name
|
||||
+ "' could not be resolved");
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
```bash
|
||||
$ curl {{url}} {{options}}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
```http
|
||||
{{method}} {{path}} HTTP/1.1
|
||||
{{#headers}}
|
||||
{{name}}: {{value}}
|
||||
{{/headers}}
|
||||
{{requestBody}}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
```http
|
||||
HTTP/1.1 {{statusCode}} {{statusReason}}
|
||||
{{#headers}}
|
||||
{{name}}: {{value}}
|
||||
{{/headers}}
|
||||
{{responseBody}}
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
Relation | Description
|
||||
-------- | -----------
|
||||
{{#links}}
|
||||
{{rel}} | {{description}}
|
||||
{{/links}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{path}}
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Path | Type | Description
|
||||
---- | ---- | -----------
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#headers}}
|
||||
{{name}} | {{description}}
|
||||
{{/headers}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Path | Type | Description
|
||||
---- | ---- | -----------
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#headers}}
|
||||
{{name}} | {{description}}
|
||||
{{/headers}}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012-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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
import org.springframework.restdocs.test.SnippetMatchers;
|
||||
import org.springframework.restdocs.test.SnippetMatchers.CodeBlockMatcher;
|
||||
import org.springframework.restdocs.test.SnippetMatchers.HttpRequestMatcher;
|
||||
import org.springframework.restdocs.test.SnippetMatchers.HttpResponseMatcher;
|
||||
import org.springframework.restdocs.test.SnippetMatchers.TableMatcher;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.markdown;
|
||||
|
||||
/**
|
||||
* Abstract base class for testing snippet generation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public abstract class AbstractSnippetTests {
|
||||
|
||||
protected final SnippetFormat snippetFormat;
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet;
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static List<Object[]> parameters() {
|
||||
return Arrays.asList(new Object[] { "Asciidoctor", asciidoctor() }, new Object[] {
|
||||
"Markdown", markdown() });
|
||||
}
|
||||
|
||||
public AbstractSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
this.snippet = new ExpectedSnippet(snippetFormat);
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
public CodeBlockMatcher<?> codeBlock(String language) {
|
||||
return SnippetMatchers.codeBlock(this.snippetFormat, language);
|
||||
}
|
||||
|
||||
public TableMatcher<?> tableWithHeader(String... headers) {
|
||||
return SnippetMatchers.tableWithHeader(this.snippetFormat, headers);
|
||||
}
|
||||
|
||||
public TableMatcher<?> tableWithTitleAndHeader(String title, String... headers) {
|
||||
return SnippetMatchers
|
||||
.tableWithTitleAndHeader(this.snippetFormat, title, headers);
|
||||
}
|
||||
|
||||
public HttpRequestMatcher httpRequest(RequestMethod method, String uri) {
|
||||
return SnippetMatchers.httpRequest(this.snippetFormat, method, uri);
|
||||
}
|
||||
|
||||
public HttpResponseMatcher httpResponse(HttpStatus responseStatus) {
|
||||
return SnippetMatchers.httpResponse(this.snippetFormat, responseStatus);
|
||||
}
|
||||
|
||||
public OperationBuilder operationBuilder(String name) {
|
||||
return new OperationBuilder(name, this.snippet.getOutputDirectory(),
|
||||
this.snippetFormat);
|
||||
}
|
||||
|
||||
protected FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ this.snippetFormat.getFileExtension() + "/" + name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,17 +18,16 @@ package org.springframework.restdocs.curl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
@@ -36,7 +35,6 @@ import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
|
||||
/**
|
||||
* Tests for {@link CurlRequestSnippet}.
|
||||
@@ -47,30 +45,27 @@ import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
* @author Jonathan Pearlin
|
||||
* @author Paul-Christian Volkmer
|
||||
*/
|
||||
public class CurlRequestSnippetTests {
|
||||
@RunWith(Parameterized.class)
|
||||
public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
public CurlRequestSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequest() throws IOException {
|
||||
this.snippet.expectCurlRequest("get-request").withContents(
|
||||
codeBlock("bash").content("$ curl 'http://localhost/foo' -i"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("get-request",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
.build());
|
||||
new CurlRequestSnippet().document(operationBuilder("get-request").request(
|
||||
"http://localhost/foo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonGetRequest() throws IOException {
|
||||
this.snippet.expectCurlRequest("non-get-request").withContents(
|
||||
codeBlock("bash").content("$ curl 'http://localhost/foo' -i -X POST"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("non-get-request",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
.method("POST").build());
|
||||
new CurlRequestSnippet().document(operationBuilder("non-get-request")
|
||||
.request("http://localhost/foo").method("POST").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -78,9 +73,8 @@ public class CurlRequestSnippetTests {
|
||||
this.snippet.expectCurlRequest("request-with-content").withContents(
|
||||
codeBlock("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -d 'content'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("request-with-content",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
.content("content").build());
|
||||
new CurlRequestSnippet().document(operationBuilder("request-with-content")
|
||||
.request("http://localhost/foo").content("content").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,8 +83,7 @@ public class CurlRequestSnippetTests {
|
||||
.withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo?param=value' -i"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"request-with-query-string", this.snippet.getOutputDirectory()).request(
|
||||
new CurlRequestSnippet().document(operationBuilder("request-with-query-string").request(
|
||||
"http://localhost/foo?param=value").build());
|
||||
}
|
||||
|
||||
@@ -99,8 +92,7 @@ public class CurlRequestSnippetTests {
|
||||
this.snippet.expectCurlRequest("post-request-with-query-string").withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo?param=value' -i -X POST"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-query-string", this.snippet.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("post-request-with-query-string")
|
||||
.request("http://localhost/foo?param=value").method("POST").build());
|
||||
}
|
||||
|
||||
@@ -110,8 +102,7 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||
new CurlRequestSnippet()
|
||||
.document(new OperationBuilder("post-request-with-one-parameter",
|
||||
this.snippet.getOutputDirectory())
|
||||
.document(operationBuilder("post-request-with-one-parameter")
|
||||
.request("http://localhost/foo").method("POST").param("k1", "v1")
|
||||
.build());
|
||||
}
|
||||
@@ -123,10 +114,10 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X POST"
|
||||
+ " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-multiple-parameters", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost/foo")
|
||||
.method("POST").param("k1", "v1", "v1-bis").param("k2", "v2").build());
|
||||
new CurlRequestSnippet()
|
||||
.document(operationBuilder("post-request-with-multiple-parameters")
|
||||
.request("http://localhost/foo").method("POST")
|
||||
.param("k1", "v1", "v1-bis").param("k2", "v2").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -136,10 +127,10 @@ public class CurlRequestSnippetTests {
|
||||
.withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-url-encoded-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost/foo")
|
||||
.method("POST").param("k1", "a&b").build());
|
||||
new CurlRequestSnippet().document(operationBuilder(
|
||||
"post-request-with-url-encoded-parameter")
|
||||
.request("http://localhost/foo").method("POST").param("k1", "a&b")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,10 +141,10 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash")
|
||||
.content(
|
||||
"$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-query-string-and-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost/foo?a=alpha")
|
||||
.method("POST").param("b", "bravo").build());
|
||||
new CurlRequestSnippet().document(operationBuilder(
|
||||
"post-request-with-query-string-and-parameter")
|
||||
.request("http://localhost/foo?a=alpha").method("POST")
|
||||
.param("b", "bravo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,10 +156,10 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash")
|
||||
.content(
|
||||
"$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-overlapping-query-string-and-parameters", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost/foo?a=alpha")
|
||||
.method("POST").param("a", "alpha").param("b", "bravo").build());
|
||||
new CurlRequestSnippet().document(operationBuilder(
|
||||
"post-request-with-overlapping-query-string-and-parameters")
|
||||
.request("http://localhost/foo?a=alpha").method("POST")
|
||||
.param("a", "alpha").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -176,8 +167,7 @@ public class CurlRequestSnippetTests {
|
||||
this.snippet.expectCurlRequest("put-request-with-one-parameter").withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"put-request-with-one-parameter", this.snippet.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("put-request-with-one-parameter")
|
||||
.request("http://localhost/foo").method("PUT").param("k1", "v1").build());
|
||||
}
|
||||
|
||||
@@ -188,11 +178,9 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X PUT"
|
||||
+ " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
new CurlRequestSnippet()
|
||||
.document(new OperationBuilder("put-request-with-multiple-parameters",
|
||||
this.snippet.getOutputDirectory())
|
||||
.request("http://localhost/foo").method("PUT").param("k1", "v1")
|
||||
.param("k1", "v1-bis").param("k2", "v2").build());
|
||||
new CurlRequestSnippet().document(operationBuilder("put-request-with-multiple-parameters")
|
||||
.request("http://localhost/foo").method("PUT").param("k1", "v1")
|
||||
.param("k1", "v1-bis").param("k2", "v2").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -201,9 +189,8 @@ public class CurlRequestSnippetTests {
|
||||
.withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"put-request-with-url-encoded-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost/foo")
|
||||
new CurlRequestSnippet().document(operationBuilder(
|
||||
"put-request-with-url-encoded-parameter").request("http://localhost/foo")
|
||||
.method("PUT").param("k1", "a&b").build());
|
||||
}
|
||||
|
||||
@@ -213,8 +200,8 @@ public class CurlRequestSnippetTests {
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i"
|
||||
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("request-with-headers",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
new CurlRequestSnippet().document(operationBuilder("request-with-headers")
|
||||
.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha").build());
|
||||
}
|
||||
@@ -226,8 +213,7 @@ public class CurlRequestSnippetTests {
|
||||
+ "'metadata={\"description\": \"foo\"}'";
|
||||
this.snippet.expectCurlRequest("multipart-post-no-original-filename")
|
||||
.withContents(codeBlock("bash").content(expectedContent));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"multipart-post-no-original-filename", this.snippet.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("multipart-post-no-original-filename")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("metadata", "{\"description\": \"foo\"}".getBytes()).build());
|
||||
@@ -240,8 +226,7 @@ public class CurlRequestSnippetTests {
|
||||
+ "'image=@documents/images/example.png;type=image/png'";
|
||||
this.snippet.expectCurlRequest("multipart-post-with-content-type").withContents(
|
||||
codeBlock("bash").content(expectedContent));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"multipart-post-with-content-type", this.snippet.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("multipart-post-with-content-type")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
@@ -256,9 +241,8 @@ public class CurlRequestSnippetTests {
|
||||
+ "'image=@documents/images/example.png'";
|
||||
this.snippet.expectCurlRequest("multipart-post").withContents(
|
||||
codeBlock("bash").content(expectedContent));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("multipart-post",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/upload")
|
||||
.method("POST")
|
||||
new CurlRequestSnippet().document(operationBuilder("multipart-post")
|
||||
.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").build());
|
||||
@@ -272,8 +256,7 @@ public class CurlRequestSnippetTests {
|
||||
+ "-F 'b=banana'";
|
||||
this.snippet.expectCurlRequest("multipart-post-with-parameters").withContents(
|
||||
codeBlock("bash").content(expectedContent));
|
||||
new CurlRequestSnippet().document(new OperationBuilder(
|
||||
"multipart-post-with-parameters", this.snippet.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("multipart-post-with-parameters")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
@@ -281,34 +264,30 @@ public class CurlRequestSnippetTests {
|
||||
.param("a", "apple", "avocado").param("b", "banana").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAttributes() throws IOException {
|
||||
this.snippet.expectCurlRequest("custom-attributes").withContents(
|
||||
containsString("curl request title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("curl-request"))
|
||||
.willReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/curl-request-with-title.snippet"));
|
||||
new CurlRequestSnippet(attributes(key("title").value("curl request title")))
|
||||
.document(new OperationBuilder("custom-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost/foo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthCredentialsAreSuppliedUsingUserOption() throws IOException {
|
||||
this.snippet.expectCurlRequest("basic-auth").withContents(
|
||||
codeBlock("bash").content(
|
||||
"$ curl 'http://localhost/foo' -i -u 'user:secret'"));
|
||||
new CurlRequestSnippet().document(new OperationBuilder("basic-auth", this.snippet
|
||||
.getOutputDirectory())
|
||||
new CurlRequestSnippet().document(operationBuilder("basic-auth")
|
||||
.request("http://localhost/foo")
|
||||
.header(HttpHeaders.AUTHORIZATION,
|
||||
"Basic " + Base64Utils.encodeToString("user:secret".getBytes()))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAttributes() throws IOException {
|
||||
this.snippet.expectCurlRequest("custom-attributes").withContents(
|
||||
containsString("curl request title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("curl-request")).willReturn(
|
||||
snippetResource("curl-request-with-title"));
|
||||
new CurlRequestSnippet(attributes(key("title").value("curl request title")))
|
||||
.document(operationBuilder("custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost/foo").build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-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.headers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestHeadersSnippet} due to missing or
|
||||
* undocumented headers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestHeadersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void missingRequestHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Headers with the following names were not found"
|
||||
+ " in the request: [Accept]"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description(
|
||||
"one"))).document(new OperationBuilder("missing-request-headers",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestHeaderAndMissingRequestHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Headers with the following names were not found"
|
||||
+ " in the request: [Accept]"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"undocumented-request-header-and-missing-request-header", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.header("X-Test", "test").build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,26 +19,20 @@ package org.springframework.restdocs.headers;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestHeadersSnippet}.
|
||||
@@ -46,13 +40,11 @@ import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
* @author Andreas Evers
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestHeadersSnippetTests {
|
||||
public class RequestHeadersSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public RequestHeadersSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() throws IOException {
|
||||
@@ -67,14 +59,13 @@ public class RequestHeadersSnippetTests {
|
||||
.description("three"), headerWithName("Accept-Language")
|
||||
.description("four"), headerWithName("Cache-Control")
|
||||
.description("five"),
|
||||
headerWithName("Connection").description("six")))
|
||||
.document(new OperationBuilder("request-with-headers", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.header("X-Test", "test").header("Accept", "*/*")
|
||||
.header("Accept-Encoding", "gzip, deflate")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Cache-Control", "max-age=0")
|
||||
.header("Connection", "keep-alive").build());
|
||||
headerWithName("Connection").description("six"))).document(operationBuilder(
|
||||
"request-with-headers").request("http://localhost")
|
||||
.header("X-Test", "test").header("Accept", "*/*")
|
||||
.header("Accept-Encoding", "gzip, deflate")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header("Cache-Control", "max-age=0").header("Connection", "keep-alive")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,8 +74,7 @@ public class RequestHeadersSnippetTests {
|
||||
.expectRequestHeaders("case-insensitive-request-headers")
|
||||
.withContents(tableWithHeader("Name", "Description").row("X-Test", "one"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"case-insensitive-request-headers", this.snippet.getOutputDirectory())
|
||||
"one"))).document(operationBuilder("case-insensitive-request-headers")
|
||||
.request("/").header("X-test", "test").build());
|
||||
}
|
||||
|
||||
@@ -97,37 +87,28 @@ public class RequestHeadersSnippetTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Headers with the following names were not found"
|
||||
+ " in the request: [Accept]"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description(
|
||||
"one"))).document(new OperationBuilder("missing-request-headers",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestHeaderAndMissingRequestHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Headers with the following names were not found"
|
||||
+ " in the request: [Accept]"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"undocumented-request-header-and-missing-request-header", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.header("X-Test", "test").build());
|
||||
public void requestHeadersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectRequestHeaders("request-headers-with-custom-attributes")
|
||||
.withContents(containsString("Custom title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-headers")).willReturn(
|
||||
snippetResource("request-headers-with-title"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one")), attributes(key("title").value("Custom title")))
|
||||
.document(operationBuilder("request-headers-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost").header("X-Test", "test").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHeadersWithCustomDescriptorAttributes() throws IOException {
|
||||
this.snippet.expectRequestHeaders("request-headers-with-custom-attributes")
|
||||
.withContents(//
|
||||
tableWithHeader("Name", "Description", "Foo")
|
||||
.row("X-Test", "one", "alpha")
|
||||
.row("Accept-Encoding", "two", "bravo")
|
||||
.row("Accept", "three", "charlie"));
|
||||
this.snippet.expectRequestHeaders(
|
||||
"request-headers-with-custom-descriptor-attributes").withContents(//
|
||||
tableWithHeader("Name", "Description", "Foo")
|
||||
.row("X-Test", "one", "alpha")
|
||||
.row("Accept-Encoding", "two", "bravo")
|
||||
.row("Accept", "three", "charlie"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-headers")).willReturn(
|
||||
snippetResource("request-headers-with-extra-column"));
|
||||
@@ -137,34 +118,12 @@ public class RequestHeadersSnippetTests {
|
||||
headerWithName("Accept-Encoding").description("two").attributes(
|
||||
key("foo").value("bravo")),
|
||||
headerWithName("Accept").description("three").attributes(
|
||||
key("foo").value("charlie")))).document(new OperationBuilder(
|
||||
"request-headers-with-custom-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
key("foo").value("charlie")))).document(operationBuilder(
|
||||
"request-headers-with-custom-descriptor-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.header("X-Test", "test").header("Accept-Encoding", "gzip, deflate")
|
||||
.header("Accept", "*/*").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHeadersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectRequestHeaders("request-headers-with-custom-attributes")
|
||||
.withContents(startsWith(".Custom title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-headers")).willReturn(
|
||||
snippetResource("request-headers-with-title"));
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one")), attributes(key("title").value("Custom title")))
|
||||
.document(new OperationBuilder("request-headers-with-custom-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost").header("X-Test", "test").build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012-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.headers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link ResponseHeadersSnippet} due to missing or
|
||||
* undocumented headers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseHeadersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void missingResponseHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Headers with the following names were not found"
|
||||
+ " in the response: [Content-Type]"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type")
|
||||
.description("one"))).document(new OperationBuilder(
|
||||
"missing-response-headers", this.snippet.getOutputDirectory()).response()
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeaderAndMissingResponseHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Headers with the following names were not found"
|
||||
+ " in the response: [Content-Type]"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type")
|
||||
.description("one"))).document(new OperationBuilder(
|
||||
"undocumented-response-header-and-missing-response-header", this.snippet
|
||||
.getOutputDirectory()).response().header("X-Test", "test")
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,26 +19,20 @@ package org.springframework.restdocs.headers;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link ResponseHeadersSnippet}.
|
||||
@@ -46,13 +40,11 @@ import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
* @author Andreas Evers
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseHeadersSnippetTests {
|
||||
public class ResponseHeadersSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public ResponseHeadersSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithHeaders() throws IOException {
|
||||
@@ -65,8 +57,7 @@ public class ResponseHeadersSnippetTests {
|
||||
headerWithName("Content-Type").description("two"), headerWithName("Etag")
|
||||
.description("three"), headerWithName("Cache-Control")
|
||||
.description("five"), headerWithName("Vary").description("six")))
|
||||
.document(new OperationBuilder("response-headers", this.snippet
|
||||
.getOutputDirectory()).response().header("X-Test", "test")
|
||||
.document(operationBuilder("response-headers").response().header("X-Test", "test")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Etag", "lskjadldj3ii32l2ij23")
|
||||
.header("Cache-Control", "max-age=0")
|
||||
@@ -79,9 +70,31 @@ public class ResponseHeadersSnippetTests {
|
||||
.expectResponseHeaders("case-insensitive-response-headers")
|
||||
.withContents(tableWithHeader("Name", "Description").row("X-Test", "one"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"case-insensitive-response-headers", this.snippet.getOutputDirectory())
|
||||
.response().header("X-test", "test").build());
|
||||
"one"))).document(operationBuilder("case-insensitive-response-headers").response()
|
||||
.header("X-test", "test").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeader() throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one"))).document(new OperationBuilder("undocumented-response-header",
|
||||
this.snippet.getOutputDirectory()).response().header("X-Test", "test")
|
||||
.header("Content-Type", "*/*").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseHeadersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectResponseHeaders("response-headers-with-custom-attributes")
|
||||
.withContents(containsString("Custom title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-headers")).willReturn(
|
||||
snippetResource("response-headers-with-title"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one")), attributes(key("title").value("Custom title")))
|
||||
.document(operationBuilder("response-headers-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.header("X-Test", "test").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -101,67 +114,12 @@ public class ResponseHeadersSnippetTests {
|
||||
headerWithName("Content-Type").description("two").attributes(
|
||||
key("foo").value("bravo")),
|
||||
headerWithName("Etag").description("three").attributes(
|
||||
key("foo").value("charlie")))).document(new OperationBuilder(
|
||||
"response-headers-with-custom-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
key("foo").value("charlie")))).document(operationBuilder(
|
||||
"response-headers-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.header("X-Test", "test").header("Content-Type", "application/json")
|
||||
.header("Etag", "lskjadldj3ii32l2ij23").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseHeadersWithCustomAttributes() throws IOException {
|
||||
this.snippet.expectResponseHeaders("response-headers-with-custom-attributes")
|
||||
.withContents(startsWith(".Custom title"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-headers")).willReturn(
|
||||
snippetResource("response-headers-with-title"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one")), attributes(key("title").value("Custom title")))
|
||||
.document(new OperationBuilder("response-headers-with-custom-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.header("X-Test", "test").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeader() throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description(
|
||||
"one"))).document(new OperationBuilder("undocumented-response-header",
|
||||
this.snippet.getOutputDirectory()).response().header("X-Test", "test")
|
||||
.header("Content-Type", "*/*").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingResponseHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Headers with the following names were not found"
|
||||
+ " in the response: [Content-Type]"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type")
|
||||
.description("one"))).document(new OperationBuilder(
|
||||
"missing-response-headers", this.snippet.getOutputDirectory()).response()
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeaderAndMissingResponseHeader() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Headers with the following names were not found"
|
||||
+ " in the response: [Content-Type]"));
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type")
|
||||
.description("one"))).document(new OperationBuilder(
|
||||
"undocumented-response-header-and-missing-response-header", this.snippet
|
||||
.getOutputDirectory()).response().header("X-Test", "test")
|
||||
.build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,16 +18,14 @@ package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
@@ -35,21 +33,20 @@ import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
|
||||
/**
|
||||
* Tests for {@link HttpRequestSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Jonathan Pearlin
|
||||
*
|
||||
*/
|
||||
public class HttpRequestSnippetTests {
|
||||
public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
private static final String BOUNDARY = "6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm";
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public HttpRequestSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequest() throws IOException {
|
||||
@@ -57,9 +54,8 @@ public class HttpRequestSnippetTests {
|
||||
httpRequest(RequestMethod.GET, "/foo").header("Alpha", "a").header(
|
||||
HttpHeaders.HOST, "localhost"));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder("get-request",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
.header("Alpha", "a").build());
|
||||
new HttpRequestSnippet().document(operationBuilder("get-request")
|
||||
.request("http://localhost/foo").header("Alpha", "a").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,8 +64,7 @@ public class HttpRequestSnippetTests {
|
||||
httpRequest(RequestMethod.GET, "/foo?bar=baz").header(HttpHeaders.HOST,
|
||||
"localhost"));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"get-request-with-query-string", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("get-request-with-query-string")
|
||||
.request("http://localhost/foo?bar=baz").build());
|
||||
}
|
||||
|
||||
@@ -81,8 +76,7 @@ public class HttpRequestSnippetTests {
|
||||
.header(HttpHeaders.HOST, "localhost").content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-content", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("post-request-with-content")
|
||||
.request("http://localhost/foo").method("POST").content(content).build());
|
||||
}
|
||||
|
||||
@@ -97,8 +91,7 @@ public class HttpRequestSnippetTests {
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length)
|
||||
.content(japaneseContent));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-charset", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("post-request-with-charset")
|
||||
.request("http://localhost/foo").method("POST")
|
||||
.header("Content-Type", "text/plain;charset=UTF-8").content(contentBytes)
|
||||
.build());
|
||||
@@ -112,8 +105,7 @@ public class HttpRequestSnippetTests {
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
.content("b%26r=baz&a=alpha"));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"post-request-with-parameter", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("post-request-with-parameter")
|
||||
.request("http://localhost/foo").method("POST").param("b&r", "baz")
|
||||
.param("a", "alpha").build());
|
||||
}
|
||||
@@ -126,8 +118,7 @@ public class HttpRequestSnippetTests {
|
||||
.header(HttpHeaders.HOST, "localhost").content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"put-request-with-content", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("put-request-with-content")
|
||||
.request("http://localhost/foo").method("PUT").content(content).build());
|
||||
}
|
||||
|
||||
@@ -139,8 +130,7 @@ public class HttpRequestSnippetTests {
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
.content("b%26r=baz&a=alpha"));
|
||||
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"put-request-with-parameter", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("put-request-with-parameter")
|
||||
.request("http://localhost/foo").method("PUT").param("b&r", "baz")
|
||||
.param("a", "alpha").build());
|
||||
}
|
||||
@@ -154,9 +144,8 @@ public class HttpRequestSnippetTests {
|
||||
.header("Content-Type",
|
||||
"multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
||||
new HttpRequestSnippet().document(new OperationBuilder("multipart-post",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/upload")
|
||||
.method("POST")
|
||||
new HttpRequestSnippet().document(operationBuilder("multipart-post")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes()).build());
|
||||
}
|
||||
@@ -177,8 +166,7 @@ public class HttpRequestSnippetTests {
|
||||
.header("Content-Type",
|
||||
"multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"multipart-post-with-parameters", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("multipart-post-with-parameters")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.param("a", "apple", "avocado").param("b", "banana")
|
||||
@@ -195,8 +183,7 @@ public class HttpRequestSnippetTests {
|
||||
.header("Content-Type",
|
||||
"multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
||||
new HttpRequestSnippet().document(new OperationBuilder(
|
||||
"multipart-post-with-content-type", this.snippet.getOutputDirectory())
|
||||
new HttpRequestSnippet().document(operationBuilder("multipart-post-with-content-type")
|
||||
.request("http://localhost/upload").method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
@@ -208,8 +195,8 @@ public class HttpRequestSnippetTests {
|
||||
this.snippet.expectHttpRequest("get-request-custom-host").withContents(
|
||||
httpRequest(RequestMethod.GET, "/foo").header(HttpHeaders.HOST,
|
||||
"api.example.com"));
|
||||
new HttpRequestSnippet().document(new OperationBuilder("get-request-custom-host",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost/foo")
|
||||
new HttpRequestSnippet().document(operationBuilder("get-request-custom-host")
|
||||
.request("http://localhost/foo")
|
||||
.header(HttpHeaders.HOST, "api.example.com").build());
|
||||
}
|
||||
|
||||
@@ -218,13 +205,10 @@ public class HttpRequestSnippetTests {
|
||||
this.snippet.expectHttpRequest("request-with-snippet-attributes").withContents(
|
||||
containsString("Title for the request"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("http-request"))
|
||||
.willReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/http-request-with-title.snippet"));
|
||||
given(resolver.resolveTemplateResource("http-request")).willReturn(
|
||||
snippetResource("http-request-with-title"));
|
||||
new HttpRequestSnippet(attributes(key("title").value("Title for the request")))
|
||||
.document(new OperationBuilder("request-with-snippet-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.document(operationBuilder("request-with-snippet-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost/foo").build());
|
||||
|
||||
@@ -18,24 +18,21 @@ package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
|
||||
/**
|
||||
* Tests for {@link HttpResponseSnippet}.
|
||||
@@ -43,25 +40,24 @@ import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
* @author Andy Wilkinson
|
||||
* @author Jonathan Pearlin
|
||||
*/
|
||||
public class HttpResponseSnippetTests {
|
||||
public class HttpResponseSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public HttpResponseSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicResponse() throws IOException {
|
||||
this.snippet.expectHttpResponse("basic-response").withContents(
|
||||
httpResponse(HttpStatus.OK));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("basic-response",
|
||||
this.snippet.getOutputDirectory()).build());
|
||||
new HttpResponseSnippet().document(operationBuilder("basic-response").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOkResponse() throws IOException {
|
||||
this.snippet.expectHttpResponse("non-ok-response").withContents(
|
||||
httpResponse(HttpStatus.BAD_REQUEST));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("non-ok-response",
|
||||
this.snippet.getOutputDirectory()).response()
|
||||
new HttpResponseSnippet().document(operationBuilder("non-ok-response").response()
|
||||
.status(HttpStatus.BAD_REQUEST.value()).build());
|
||||
}
|
||||
|
||||
@@ -70,8 +66,7 @@ public class HttpResponseSnippetTests {
|
||||
this.snippet.expectHttpResponse("response-with-headers").withContents(
|
||||
httpResponse(HttpStatus.OK).header("Content-Type", "application/json")
|
||||
.header("a", "alpha"));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("response-with-headers",
|
||||
this.snippet.getOutputDirectory()).response()
|
||||
new HttpResponseSnippet().document(operationBuilder("response-with-headers").response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha").build());
|
||||
}
|
||||
@@ -82,8 +77,8 @@ public class HttpResponseSnippetTests {
|
||||
this.snippet.expectHttpResponse("response-with-content").withContents(
|
||||
httpResponse(HttpStatus.OK).content(content).header(
|
||||
HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("response-with-content",
|
||||
this.snippet.getOutputDirectory()).response().content(content).build());
|
||||
new HttpResponseSnippet().document(operationBuilder("response-with-content").response()
|
||||
.content(content).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,8 +90,7 @@ public class HttpResponseSnippetTests {
|
||||
.header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.content(japaneseContent)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length));
|
||||
new HttpResponseSnippet().document(new OperationBuilder("response-with-charset",
|
||||
this.snippet.getOutputDirectory()).response()
|
||||
new HttpResponseSnippet().document(operationBuilder("response-with-charset").response()
|
||||
.header("Content-Type", "text/plain;charset=UTF-8").content(contentBytes)
|
||||
.build());
|
||||
}
|
||||
@@ -106,13 +100,10 @@ public class HttpResponseSnippetTests {
|
||||
this.snippet.expectHttpResponse("response-with-snippet-attributes").withContents(
|
||||
containsString("Title for the response"));
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("http-response"))
|
||||
.willReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/http-response-with-title.snippet"));
|
||||
given(resolver.resolveTemplateResource("http-response")).willReturn(
|
||||
snippetResource("http-response-with-title"));
|
||||
new HttpResponseSnippet(attributes(key("title").value("Title for the response")))
|
||||
.document(new OperationBuilder("response-with-snippet-attributes",
|
||||
this.snippet.getOutputDirectory()).attribute(
|
||||
.document(operationBuilder("response-with-snippet-attributes").attribute(
|
||||
TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2012-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.hypermedia;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link LinksSnippet} due to missing or undocumented
|
||||
* links.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class LinksSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " documented: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Collections.<LinkDescriptor>emptyList()).document(new OperationBuilder(
|
||||
"undocumented-link", this.snippet.getOutputDirectory()).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " found in the response: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor(), Arrays.asList(new LinkDescriptor("foo")
|
||||
.description("bar"))).document(new OperationBuilder("missing-link",
|
||||
this.snippet.getOutputDirectory()).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedLinkAndMissingLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " documented: [a]. Links with the following relations were not"
|
||||
+ " found in the response: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(new OperationBuilder("undocumented-link-and-missing-link",
|
||||
this.snippet.getOutputDirectory()).build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,51 +18,29 @@ package org.springframework.restdocs.hypermedia;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link LinksSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class LinksSnippetTests {
|
||||
public class LinksSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " documented: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Collections.<LinkDescriptor>emptyList()).document(new OperationBuilder(
|
||||
"undocumented-link", this.snippet.getOutputDirectory()).build());
|
||||
public LinksSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,19 +49,8 @@ public class LinksSnippetTests {
|
||||
tableWithHeader("Relation", "Description").row("b", "Link b"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"),
|
||||
new Link("b", "bravo")), Arrays.asList(new LinkDescriptor("a").ignored(),
|
||||
new LinkDescriptor("b").description("Link b")))
|
||||
.document(new OperationBuilder("ignored-link", this.snippet
|
||||
.getOutputDirectory()).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " found in the response: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor(), Arrays.asList(new LinkDescriptor("foo")
|
||||
.description("bar"))).document(new OperationBuilder("missing-link",
|
||||
this.snippet.getOutputDirectory()).build());
|
||||
new LinkDescriptor("b").description("Link b"))).document(operationBuilder(
|
||||
"ignored-link").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,8 +59,7 @@ public class LinksSnippetTests {
|
||||
tableWithHeader("Relation", "Description").row("foo", "bar"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "blah")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar").optional()))
|
||||
.document(new OperationBuilder("documented-optional-link", this.snippet
|
||||
.getOutputDirectory()).build());
|
||||
.document(operationBuilder("documented-optional-link").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -101,20 +67,8 @@ public class LinksSnippetTests {
|
||||
this.snippet.expectLinks("missing-optional-link").withContents(
|
||||
tableWithHeader("Relation", "Description").row("foo", "bar"));
|
||||
new LinksSnippet(new StubLinkExtractor(), Arrays.asList(new LinkDescriptor("foo")
|
||||
.description("bar").optional())).document(new OperationBuilder(
|
||||
"missing-optional-link", this.snippet.getOutputDirectory()).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedLinkAndMissingLink() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Links with the following relations were not"
|
||||
+ " documented: [a]. Links with the following relations were not"
|
||||
+ " found in the response: [foo]"));
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(new OperationBuilder("undocumented-link-and-missing-link",
|
||||
this.snippet.getOutputDirectory()).build());
|
||||
.description("bar").optional()))
|
||||
.document(operationBuilder("missing-optional-link").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,18 +79,32 @@ public class LinksSnippetTests {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"),
|
||||
new Link("b", "bravo")), Arrays.asList(
|
||||
new LinkDescriptor("a").description("one"),
|
||||
new LinkDescriptor("b").description("two")))
|
||||
.document(new OperationBuilder("documented-links", this.snippet
|
||||
.getOutputDirectory()).build());
|
||||
new LinkDescriptor("b").description("two"))).document(operationBuilder(
|
||||
"documented-links").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("links")).willReturn(
|
||||
snippetResource("links-with-title"));
|
||||
this.snippet.expectLinks("links-with-custom-attributes").withContents(
|
||||
containsString("Title for the links"));
|
||||
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"),
|
||||
new Link("b", "bravo")), Arrays.asList(
|
||||
new LinkDescriptor("a").description("one"),
|
||||
new LinkDescriptor("b").description("two")), attributes(key("title")
|
||||
.value("Title for the links"))).document(operationBuilder(
|
||||
"links-with-custom-attributes").attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("links"))
|
||||
.willReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/links-with-extra-column.snippet"));
|
||||
given(resolver.resolveTemplateResource("links")).willReturn(
|
||||
snippetResource("links-with-extra-column"));
|
||||
this.snippet.expectLinks("links-with-custom-descriptor-attributes").withContents(
|
||||
tableWithHeader("Relation", "Description", "Foo")
|
||||
.row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
@@ -146,49 +114,10 @@ public class LinksSnippetTests {
|
||||
new LinkDescriptor("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
new LinkDescriptor("b").description("two").attributes(
|
||||
key("foo").value("bravo")))).document(new OperationBuilder(
|
||||
"links-with-custom-descriptor-attributes", this.snippet
|
||||
.getOutputDirectory()).attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("links"))
|
||||
.willReturn(
|
||||
new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/links-with-title.snippet"));
|
||||
this.snippet.expectLinks("links-with-custom-attributes").withContents(
|
||||
startsWith(".Title for the links"));
|
||||
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"),
|
||||
new Link("b", "bravo")), Arrays.asList(
|
||||
new LinkDescriptor("a").description("one"),
|
||||
new LinkDescriptor("b").description("two")), attributes(key("title")
|
||||
.value("Title for the links"))).document(new OperationBuilder(
|
||||
"links-with-custom-attributes", this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
}
|
||||
|
||||
private static class StubLinkExtractor implements LinkExtractor {
|
||||
|
||||
private MultiValueMap<String, Link> linksByRel = new LinkedMultiValueMap<>();
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, Link> extractLinks(OperationResponse response)
|
||||
throws IOException {
|
||||
return this.linksByRel;
|
||||
}
|
||||
|
||||
private StubLinkExtractor withLinks(Link... links) {
|
||||
for (Link link : links) {
|
||||
this.linksByRel.add(link.getRel(), link);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
key("foo").value("bravo")))).document(operationBuilder(
|
||||
"links-with-custom-descriptor-attributes").attribute(
|
||||
TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.hypermedia;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* Stub implementation of {@code LinkExtractor} for testing.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class StubLinkExtractor implements LinkExtractor {
|
||||
|
||||
private MultiValueMap<String, Link> linksByRel = new LinkedMultiValueMap<>();
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, Link> extractLinks(OperationResponse response)
|
||||
throws IOException {
|
||||
return this.linksByRel;
|
||||
}
|
||||
|
||||
StubLinkExtractor withLinks(Link... links) {
|
||||
for (Link link : links) {
|
||||
this.linksByRel.add(link.getRel(), link);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2012-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.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestFieldsSnippet} that are specific to Asciidoctor.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class AsciidoctorRequestFieldsSnippetTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithListDescription() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields")).willReturn(
|
||||
snippetResource("request-fields-with-list-description"));
|
||||
this.snippet.expectRequestFields("request-fields-with-list-description")
|
||||
.withContents(
|
||||
tableWithHeader(asciidoctor(), "Path", "Type", "Description")
|
||||
//
|
||||
.row("a", "String", String.format(" - one%n - two"))
|
||||
.configuration("[cols=\"1,1,1a\"]"));
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description(
|
||||
Arrays.asList("one", "two"))))
|
||||
.document(new OperationBuilder("request-fields-with-list-description",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost").content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/adoc/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2012-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.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestFieldsSnippet} due to missing or
|
||||
* undocumented fields.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestFieldsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-request-field", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.content("{\"a\": 5}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a.b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(new OperationBuilder("missing-request-fields", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").content("{}")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalRequestFieldWithNoTypeProvided() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")
|
||||
.optional())).document(new OperationBuilder(
|
||||
"missing-optional-request-field-with-no-type", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").content("{ }")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestFieldAndMissingRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a.b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-request-field-and-missing-request-field",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost")
|
||||
.content("{ \"a\": { \"c\": 5 }}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlRequestFieldWithNoType() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(new OperationBuilder("missing-xml-request", this.snippet
|
||||
.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one"),
|
||||
fieldWithPath("a").description("one"))).document(new OperationBuilder(
|
||||
"missing-xml-request-fields", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost").content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestFieldAndMissingXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-xml-request-field-and-missing-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,43 +18,33 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestFieldsSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestFieldsSnippetTests {
|
||||
public class RequestFieldsSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public RequestFieldsSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestWithFields() throws IOException {
|
||||
@@ -65,9 +55,8 @@ public class RequestFieldsSnippetTests {
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one"),
|
||||
fieldWithPath("a.c").description("two"),
|
||||
fieldWithPath("a").description("three"))).document(new OperationBuilder(
|
||||
"map-request-with-fields", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
fieldWithPath("a").description("three"))).document(operationBuilder(
|
||||
"map-request-with-fields").request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
}
|
||||
|
||||
@@ -80,24 +69,11 @@ public class RequestFieldsSnippetTests {
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("[]a.b").description("one"),
|
||||
fieldWithPath("[]a.c").description("two"), fieldWithPath("[]a")
|
||||
.description("three"))).document(new OperationBuilder(
|
||||
"array-request-with-fields", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.description("three"))).document(operationBuilder(
|
||||
"array-request-with-fields").request("http://localhost")
|
||||
.content("[{\"a\": {\"b\": 5}},{\"a\": {\"c\": \"charlie\"}}]").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-request-field", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.content("{\"a\": 5}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredRequestField() throws IOException {
|
||||
this.snippet.expectRequestFields("ignored-request-field").withContents(
|
||||
@@ -105,48 +81,25 @@ public class RequestFieldsSnippetTests {
|
||||
"Field b"));
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").ignored(),
|
||||
fieldWithPath("b").description("Field b")))
|
||||
.document(new OperationBuilder("ignored-request-field", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.content("{\"a\": 5, \"b\": 4}").build());
|
||||
fieldWithPath("b").description("Field b"))).document(operationBuilder(
|
||||
"ignored-request-field").request("http://localhost")
|
||||
.content("{\"a\": 5, \"b\": 4}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a.b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(new OperationBuilder("missing-request-fields", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").content("{}")
|
||||
.build());
|
||||
}
|
||||
public void requestFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields")).willReturn(
|
||||
snippetResource("request-fields-with-title"));
|
||||
this.snippet.expectRequestFields("request-fields-with-custom-attributes")
|
||||
.withContents(containsString("Custom title"));
|
||||
|
||||
@Test
|
||||
public void missingOptionalRequestFieldWithNoTypeProvided() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")
|
||||
.optional())).document(new OperationBuilder(
|
||||
"missing-optional-request-field-with-no-type", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").content("{ }")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestFieldAndMissingRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a.b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-request-field-and-missing-request-field",
|
||||
this.snippet.getOutputDirectory()).request("http://localhost")
|
||||
.content("{ \"a\": { \"c\": 5 }}").build());
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title"))).document(operationBuilder(
|
||||
"request-fields-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,52 +120,13 @@ public class RequestFieldsSnippetTests {
|
||||
fieldWithPath("a.c").description("two").attributes(
|
||||
key("foo").value("bravo")),
|
||||
fieldWithPath("a").description("three").attributes(
|
||||
key("foo").value("charlie")))).document(new OperationBuilder(
|
||||
"request-fields-with-custom-descriptor-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
key("foo").value("charlie")))).document(operationBuilder(
|
||||
"request-fields-with-custom-descriptor-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields")).willReturn(
|
||||
snippetResource("request-fields-with-title"));
|
||||
this.snippet.expectRequestFields("request-fields-with-custom-attributes")
|
||||
.withContents(startsWith(".Custom title"));
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(new OperationBuilder("request-fields-with-custom-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost").content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithListDescription() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields")).willReturn(
|
||||
snippetResource("request-fields-with-list-description"));
|
||||
this.snippet.expectRequestFields("request-fields-with-list-description")
|
||||
.withContents(
|
||||
tableWithHeader("Path", "Type", "Description")
|
||||
//
|
||||
.row("a", "String", String.format(" - one%n - two"))
|
||||
.configuration("[cols=\"1,1,1a\"]"));
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description(
|
||||
Arrays.asList("one", "two"))))
|
||||
.document(new OperationBuilder("request-fields-with-list-description",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost").content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlRequestFields() throws IOException {
|
||||
this.snippet.expectRequestFields("xml-request").withContents(
|
||||
@@ -221,78 +135,11 @@ public class RequestFieldsSnippetTests {
|
||||
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")
|
||||
.type("b"), fieldWithPath("a/c").description("two").type("c"),
|
||||
fieldWithPath("a").description("three").type("a")))
|
||||
.document(new OperationBuilder("xml-request", this.snippet
|
||||
.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlRequestFieldWithNoType() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(new OperationBuilder("missing-xml-request", this.snippet
|
||||
.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one"),
|
||||
fieldWithPath("a").description("one"))).document(new OperationBuilder(
|
||||
"missing-xml-request-fields", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost").content("<a></a>")
|
||||
fieldWithPath("a").description("three").type("a"))).document(operationBuilder(
|
||||
"xml-request").request("http://localhost")
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestFieldAndMissingXmlRequestField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-xml-request-field-and-missing-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.request("http://localhost")
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2012-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.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link ResponseFieldsSnippet} due to missing or
|
||||
* undocumented fields.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseFieldsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-xml-response-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlAttribute() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/@id]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
|
||||
.type("b"), fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(new OperationBuilder("missing-xml-attribute", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void documentedXmlAttributesAreRemoved() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo(String
|
||||
.format("The following parts of the payload were not documented:"
|
||||
+ "%n<a>bar</a>%n")));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one")
|
||||
.type("a"))).document(new OperationBuilder(
|
||||
"documented-attribute-is-removed", this.snippet.getOutputDirectory())
|
||||
.response().content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlResponseFieldWithNoType() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(new OperationBuilder("xml-response-no-field-type", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlResponseField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one"),
|
||||
fieldWithPath("a").description("one"))).document(new OperationBuilder(
|
||||
"missing-xml-response-field", this.snippet.getOutputDirectory())
|
||||
.response().content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseFieldAndMissingXmlResponseField()
|
||||
throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-xml-request-field-and-missing-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,43 +18,33 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.endsWith;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link ResponseFieldsSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseFieldsSnippetTests {
|
||||
public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public final ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
public ResponseFieldsSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapResponseWithFields() throws IOException {
|
||||
@@ -69,14 +59,12 @@ public class ResponseFieldsSnippetTests {
|
||||
.description("three"),
|
||||
fieldWithPath("assets[]").description("four"),
|
||||
fieldWithPath("assets[].id").description("five"),
|
||||
fieldWithPath("assets[].name").description("six")))
|
||||
.document(new OperationBuilder("map-response-with-fields", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content(
|
||||
"{\"id\": 67,\"date\": \"2015-01-20\",\"assets\":"
|
||||
+ " [{\"id\":356,\"name\": \"sample\"}]}")
|
||||
.build());
|
||||
fieldWithPath("assets[].name").description("six"))).document(operationBuilder(
|
||||
"map-response-with-fields")
|
||||
.response()
|
||||
.content(
|
||||
"{\"id\": 67,\"date\": \"2015-01-20\",\"assets\":"
|
||||
+ " [{\"id\":356,\"name\": \"sample\"}]}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,8 +76,7 @@ public class ResponseFieldsSnippetTests {
|
||||
new ResponseFieldsSnippet(Arrays.asList(
|
||||
fieldWithPath("[]a.b").description("one"), fieldWithPath("[]a.c")
|
||||
.description("two"), fieldWithPath("[]a").description("three")))
|
||||
.document(new OperationBuilder("array-response-with-fields", this.snippet
|
||||
.getOutputDirectory()).response()
|
||||
.document(operationBuilder("array-response-with-fields").response()
|
||||
.content("[{\"a\": {\"b\": 5}},{\"a\": {\"c\": \"charlie\"}}]")
|
||||
.build());
|
||||
}
|
||||
@@ -101,8 +88,7 @@ public class ResponseFieldsSnippetTests {
|
||||
tableWithHeader("Path", "Type", "Description").row("[]",
|
||||
"String", "one"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("[]").description("one")))
|
||||
.document(new OperationBuilder("array-response", this.snippet
|
||||
.getOutputDirectory()).response()
|
||||
.document(operationBuilder("array-response").response()
|
||||
.content("[\"a\", \"b\", \"c\"]").build());
|
||||
}
|
||||
|
||||
@@ -113,10 +99,25 @@ public class ResponseFieldsSnippetTests {
|
||||
"Field b"));
|
||||
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").ignored(),
|
||||
fieldWithPath("b").description("Field b")))
|
||||
.document(new OperationBuilder("ignored-response-field", this.snippet
|
||||
.getOutputDirectory()).response().content("{\"a\": 5, \"b\": 4}")
|
||||
.build());
|
||||
fieldWithPath("b").description("Field b"))).document(operationBuilder(
|
||||
"ignored-response-field").response().content("{\"a\": 5, \"b\": 4}")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-fields")).willReturn(
|
||||
snippetResource("response-fields-with-title"));
|
||||
this.snippet.expectResponseFields("response-fields-with-custom-attributes")
|
||||
.withContents(containsString("Custom title"));
|
||||
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title"))).document(operationBuilder(
|
||||
"response-fields-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,31 +138,13 @@ public class ResponseFieldsSnippetTests {
|
||||
fieldWithPath("a.c").description("two").attributes(
|
||||
key("foo").value("bravo")),
|
||||
fieldWithPath("a").description("three").attributes(
|
||||
key("foo").value("charlie")))).document(new OperationBuilder(
|
||||
"response-fields-with-custom-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
key("foo").value("charlie")))).document(operationBuilder(
|
||||
"response-fields-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-fields")).willReturn(
|
||||
snippetResource("response-fields-with-title"));
|
||||
this.snippet.expectResponseFields("response-fields-with-custom-attributes")
|
||||
.withContents(startsWith(".Custom title"));
|
||||
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(new OperationBuilder("response-fields-with-custom-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).response()
|
||||
.content("{\"a\": \"foo\"}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlResponseFields() throws IOException {
|
||||
this.snippet.expectResponseFields("xml-response").withContents(
|
||||
@@ -169,28 +152,10 @@ public class ResponseFieldsSnippetTests {
|
||||
.row("a/c", "c", "two").row("a", "a", "three"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")
|
||||
.type("b"), fieldWithPath("a/c").description("two").type("c"),
|
||||
fieldWithPath("a").description("three").type("a")))
|
||||
.document(new OperationBuilder("xml-response", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-xml-response-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
fieldWithPath("a").description("three").type("a"))).document(operationBuilder(
|
||||
"xml-response").response().content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -200,30 +165,13 @@ public class ResponseFieldsSnippetTests {
|
||||
"a/@id", "c", "two"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
|
||||
.type("b"), fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(new OperationBuilder("xml-attribute", this.snippet
|
||||
.getOutputDirectory())
|
||||
.document(operationBuilder("xml-attribute")
|
||||
.response()
|
||||
.content("<a id=\"1\">foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlAttribute() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/@id]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
|
||||
.type("b"), fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(new OperationBuilder("missing-xml-attribute", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalXmlAttribute() throws IOException {
|
||||
this.snippet.expectResponseFields("missing-optional-xml-attribute").withContents(
|
||||
@@ -231,8 +179,7 @@ public class ResponseFieldsSnippetTests {
|
||||
"a/@id", "c", "two"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
|
||||
.type("b"), fieldWithPath("a/@id").description("two").type("c")
|
||||
.optional())).document(new OperationBuilder(
|
||||
"missing-optional-xml-attribute", this.snippet.getOutputDirectory())
|
||||
.optional())).document(operationBuilder("missing-optional-xml-attribute")
|
||||
.response().content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
@@ -243,76 +190,10 @@ public class ResponseFieldsSnippetTests {
|
||||
this.snippet.expectResponseFields("undocumented-attribute").withContents(
|
||||
tableWithHeader("Path", "Type", "Description").row("a", "a", "one"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
|
||||
.type("a"))).document(new OperationBuilder("undocumented-attribute",
|
||||
this.snippet.getOutputDirectory()).response()
|
||||
.type("a"))).document(operationBuilder("undocumented-attribute").response()
|
||||
.content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void documentedXmlAttributesAreRemoved() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo(String
|
||||
.format("The following parts of the payload were not documented:"
|
||||
+ "%n<a>bar</a>%n")));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one")
|
||||
.type("a"))).document(new OperationBuilder(
|
||||
"documented-attribute-is-removed", this.snippet.getOutputDirectory())
|
||||
.response().content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlResponseFieldWithNoType() throws IOException {
|
||||
this.thrown.expect(FieldTypeRequiredException.class);
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(new OperationBuilder("xml-response-no-field-type", this.snippet
|
||||
.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlResponseField() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one"),
|
||||
fieldWithPath("a").description("one"))).document(new OperationBuilder(
|
||||
"missing-xml-response-field", this.snippet.getOutputDirectory())
|
||||
.response().content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseFieldAndMissingXmlResponseField()
|
||||
throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(startsWith("The following parts of the payload were not"
|
||||
+ " documented:"));
|
||||
this.thrown
|
||||
.expectMessage(endsWith("Fields with the following paths were not found"
|
||||
+ " in the payload: [a/b]"));
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-xml-request-field-and-missing-xml-request-field",
|
||||
this.snippet.getOutputDirectory())
|
||||
.response()
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012-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.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link PathParametersSnippet} due to missing or
|
||||
* undocumented path parameters.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PathParametersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
new PathParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-path-parameter",
|
||||
this.snippet.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(new OperationBuilder("missing-path-parameter", this.snippet
|
||||
.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingPathParameters() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [b]. Path parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-and-missing-path-parameters", this.snippet
|
||||
.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{b}").build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,78 +18,30 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
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;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithTitleAndHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link PathParametersSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class PathParametersSnippetTests {
|
||||
public class PathParametersSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
|
||||
@Test
|
||||
public void undocumentedPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
new PathParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-path-parameter",
|
||||
this.snippet.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPathParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(new OperationBuilder("missing-path-parameter", this.snippet
|
||||
.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingPathParameters() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown.expectMessage(equalTo("Path parameters with the following names were"
|
||||
+ " not documented: [b]. Path parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(new OperationBuilder(
|
||||
"undocumented-and-missing-path-parameters", this.snippet
|
||||
.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{b}").build());
|
||||
public PathParametersSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -99,9 +51,9 @@ public class PathParametersSnippetTests {
|
||||
"one").row("b", "two"));
|
||||
new PathParametersSnippet(Arrays.asList(
|
||||
parameterWithName("a").description("one"), parameterWithName("b")
|
||||
.description("two"))).document(new OperationBuilder(
|
||||
"path-parameters", this.snippet.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/{b}").build());
|
||||
.description("two"))).document(operationBuilder("path-parameters")
|
||||
.attribute("org.springframework.restdocs.urlTemplate", "/{a}/{b}")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,10 +62,9 @@ public class PathParametersSnippetTests {
|
||||
tableWithTitleAndHeader("/{a}/{b}", "Parameter", "Description").row("b",
|
||||
"two"));
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").ignored(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(new OperationBuilder("ignored-path-parameter", this.snippet
|
||||
.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/{b}").build());
|
||||
parameterWithName("b").description("two"))).document(operationBuilder(
|
||||
"ignored-path-parameter").attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/{b}").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,11 +75,28 @@ public class PathParametersSnippetTests {
|
||||
.row("a", "one").row("b", "two"));
|
||||
new PathParametersSnippet(Arrays.asList(
|
||||
parameterWithName("a").description("one"), parameterWithName("b")
|
||||
.description("two")))
|
||||
.document(new OperationBuilder("path-parameters-with-query-string",
|
||||
this.snippet.getOutputDirectory()).attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/{b}?foo=bar")
|
||||
.build());
|
||||
.description("two"))).document(operationBuilder(
|
||||
"path-parameters-with-query-string").attribute(
|
||||
"org.springframework.restdocs.urlTemplate", "/{a}/{b}?foo=bar").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("path-parameters")).willReturn(
|
||||
snippetResource("path-parameters-with-title"));
|
||||
this.snippet.expectPathParameters("path-parameters-with-custom-attributes")
|
||||
.withContents(containsString("The title"));
|
||||
|
||||
new PathParametersSnippet(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(operationBuilder(
|
||||
"path-parameters-with-custom-attributes")
|
||||
.attribute("org.springframework.restdocs.urlTemplate", "/{a}/{b}")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,37 +112,10 @@ public class PathParametersSnippetTests {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one")
|
||||
.attributes(key("foo").value("alpha")), parameterWithName("b")
|
||||
.description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(new OperationBuilder(
|
||||
"path-parameters-with-custom-descriptor-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
.document(operationBuilder("path-parameters-with-custom-descriptor-attributes")
|
||||
.attribute("org.springframework.restdocs.urlTemplate", "/{a}/{b}")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("path-parameters")).willReturn(
|
||||
snippetResource("path-parameters-with-title"));
|
||||
this.snippet.expectPathParameters("path-parameters-with-custom-attributes")
|
||||
.withContents(startsWith(".The title"));
|
||||
|
||||
new PathParametersSnippet(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(new OperationBuilder("path-parameters-with-custom-attributes",
|
||||
this.snippet.getOutputDirectory())
|
||||
.attribute("org.springframework.restdocs.urlTemplate", "/{a}/{b}")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).build());
|
||||
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012-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.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestParametersSnippet} due to missing or
|
||||
* undocumented request parameters.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestParametersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet(SnippetFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void undocumentedParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
new RequestParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.param("a", "alpha").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description(
|
||||
"one"))).document(new OperationBuilder("missing-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingParameters() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not documented: [b]. Request parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"undocumented-and-missing-parameters", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,75 +18,30 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.test.ExpectedSnippet;
|
||||
import org.springframework.restdocs.test.OperationBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
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;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.tableWithHeader;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestParametersSnippet}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestParametersSnippetTests {
|
||||
public class RequestParametersSnippetTests extends AbstractSnippetTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public ExpectedSnippet snippet = new ExpectedSnippet();
|
||||
|
||||
@Test
|
||||
public void undocumentedParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not documented: [a]"));
|
||||
new RequestParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(new OperationBuilder("undocumented-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.param("a", "alpha").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingParameter() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not found in the request: [a]"));
|
||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description(
|
||||
"one"))).document(new OperationBuilder("missing-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingParameters() throws IOException {
|
||||
this.thrown.expect(SnippetException.class);
|
||||
this.thrown
|
||||
.expectMessage(equalTo("Request parameters with the following names were"
|
||||
+ " not documented: [b]. Request parameters with the following"
|
||||
+ " names were not found in the request: [a]"));
|
||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description(
|
||||
"one"))).document(new OperationBuilder(
|
||||
"undocumented-and-missing-parameters", this.snippet.getOutputDirectory())
|
||||
.request("http://localhost").param("b", "bravo").build());
|
||||
public RequestParametersSnippetTests(String name, SnippetFormat snippetFormat) {
|
||||
super(name, snippetFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,8 +51,7 @@ public class RequestParametersSnippetTests {
|
||||
"two"));
|
||||
new RequestParametersSnippet(Arrays.asList(
|
||||
parameterWithName("a").description("one"), parameterWithName("b")
|
||||
.description("two"))).document(new OperationBuilder(
|
||||
"request-parameters", this.snippet.getOutputDirectory())
|
||||
.description("two"))).document(operationBuilder("request-parameters")
|
||||
.request("http://localhost").param("a", "bravo").param("b", "bravo")
|
||||
.build());
|
||||
}
|
||||
@@ -107,10 +61,29 @@ public class RequestParametersSnippetTests {
|
||||
this.snippet.expectRequestParameters("ignored-request-parameter").withContents(
|
||||
tableWithHeader("Parameter", "Description").row("b", "two"));
|
||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").ignored(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(new OperationBuilder("ignored-request-parameter", this.snippet
|
||||
.getOutputDirectory()).request("http://localhost")
|
||||
.param("a", "bravo").param("b", "bravo").build());
|
||||
parameterWithName("b").description("two"))).document(operationBuilder(
|
||||
"ignored-request-parameter").request("http://localhost")
|
||||
.param("a", "bravo").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-parameters")).willReturn(
|
||||
snippetResource("request-parameters-with-title"));
|
||||
this.snippet.expectRequestParameters("request-parameters-with-custom-attributes")
|
||||
.withContents(containsString("The title"));
|
||||
|
||||
new RequestParametersSnippet(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(operationBuilder(
|
||||
"request-parameters-with-custom-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.param("a", "alpha").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,38 +100,11 @@ public class RequestParametersSnippetTests {
|
||||
parameterWithName("a").description("one").attributes(
|
||||
key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(
|
||||
key("foo").value("bravo")))).document(new OperationBuilder(
|
||||
"request-parameters-with-custom-descriptor-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
key("foo").value("bravo")))).document(operationBuilder(
|
||||
"request-parameters-with-custom-descriptor-attributes")
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.param("a", "alpha").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-parameters")).willReturn(
|
||||
snippetResource("request-parameters-with-title"));
|
||||
this.snippet.expectRequestParameters("request-parameters-with-custom-attributes")
|
||||
.withContents(startsWith(".The title"));
|
||||
|
||||
new RequestParametersSnippet(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(new OperationBuilder(
|
||||
"request-parameters-with-custom-attributes", this.snippet
|
||||
.getOutputDirectory())
|
||||
.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver)).request("http://localhost")
|
||||
.param("a", "alpha").param("b", "bravo").build());
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/"
|
||||
+ name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -26,6 +26,7 @@ import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
|
||||
/**
|
||||
* Tests for {@link StandardWriterResolver}.
|
||||
@@ -37,7 +38,7 @@ public class StandardWriterResolverTests {
|
||||
private final PlaceholderResolver placeholderResolver = mock(PlaceholderResolver.class);
|
||||
|
||||
private final StandardWriterResolver resolver = new StandardWriterResolver(
|
||||
this.placeholderResolver);
|
||||
this.placeholderResolver, "UTF-8", asciidoctor());
|
||||
|
||||
@Test
|
||||
public void noConfiguredOutputDirectoryAndRelativeInput() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -29,6 +29,7 @@ import org.springframework.core.io.Resource;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
|
||||
/**
|
||||
* Tests for {@link TemplateResourceResolver}.
|
||||
@@ -40,7 +41,8 @@ public class StandardTemplateResourceResolverTests {
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private final TemplateResourceResolver resolver = new StandardTemplateResourceResolver();
|
||||
private final TemplateResourceResolver resolver = new StandardTemplateResourceResolver(
|
||||
asciidoctor());
|
||||
|
||||
private final TestClassLoader classLoader = new TestClassLoader();
|
||||
|
||||
@@ -66,7 +68,7 @@ public class StandardTemplateResourceResolverTests {
|
||||
@Test
|
||||
public void fallsBackToDefaultSnippet() throws Exception {
|
||||
this.classLoader.addResource(
|
||||
"org/springframework/restdocs/templates/default-test.snippet", getClass()
|
||||
"org/springframework/restdocs/templates/adoc/test.snippet", getClass()
|
||||
.getResource("test.snippet"));
|
||||
Resource snippet = doWithThreadContextClassLoader(this.classLoader,
|
||||
new Callable<Resource>() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.hamcrest.Matcher;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
||||
import org.springframework.restdocs.test.SnippetMatchers.SnippetMatcher;
|
||||
|
||||
@@ -38,14 +39,21 @@ import static org.junit.Assert.assertThat;
|
||||
*/
|
||||
public class ExpectedSnippet implements TestRule {
|
||||
|
||||
private final SnippetFormat snippetFormat;
|
||||
|
||||
private final SnippetMatcher snippet;
|
||||
|
||||
private String expectedName;
|
||||
|
||||
private String expectedType;
|
||||
|
||||
private SnippetMatcher snippet = SnippetMatchers.snippet();
|
||||
|
||||
private File outputDirectory;
|
||||
|
||||
public ExpectedSnippet(SnippetFormat snippetFormat) {
|
||||
this.snippetFormat = snippetFormat;
|
||||
this.snippet = SnippetMatchers.snippet(snippetFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(final Statement base, Description description) {
|
||||
this.outputDirectory = new File("build/"
|
||||
@@ -56,7 +64,8 @@ public class ExpectedSnippet implements TestRule {
|
||||
private void verifySnippet() throws IOException {
|
||||
if (this.outputDirectory != null && this.expectedName != null) {
|
||||
File snippetDir = new File(this.outputDirectory, this.expectedName);
|
||||
File snippetFile = new File(snippetDir, this.expectedType + ".adoc");
|
||||
File snippetFile = new File(snippetDir, this.expectedType + "."
|
||||
+ this.snippetFormat.getFileExtension());
|
||||
assertThat(snippetFile, is(this.snippet));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -37,6 +37,8 @@ import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||
import org.springframework.restdocs.operation.Parameters;
|
||||
import org.springframework.restdocs.operation.StandardOperation;
|
||||
import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolver;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.restdocs.snippet.StandardWriterResolver;
|
||||
import org.springframework.restdocs.snippet.WriterResolver;
|
||||
import org.springframework.restdocs.templates.StandardTemplateResourceResolver;
|
||||
@@ -58,11 +60,18 @@ public class OperationBuilder {
|
||||
|
||||
private final File outputDirectory;
|
||||
|
||||
private final SnippetFormat snippetFormat;
|
||||
|
||||
private OperationRequestBuilder requestBuilder;
|
||||
|
||||
public OperationBuilder(String name, File outputDirectory) {
|
||||
this(name, outputDirectory, SnippetFormats.asciidoctor());
|
||||
}
|
||||
|
||||
public OperationBuilder(String name, File outputDirectory, SnippetFormat snippetFormat) {
|
||||
this.name = name;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
public OperationRequestBuilder request(String uri) {
|
||||
@@ -82,13 +91,15 @@ public class OperationBuilder {
|
||||
public Operation build() {
|
||||
if (this.attributes.get(TemplateEngine.class.getName()) == null) {
|
||||
this.attributes.put(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(new StandardTemplateResourceResolver()));
|
||||
new MustacheTemplateEngine(new StandardTemplateResourceResolver(
|
||||
this.snippetFormat)));
|
||||
}
|
||||
RestDocumentationContext context = new RestDocumentationContext(null, null,
|
||||
this.outputDirectory);
|
||||
this.attributes.put(RestDocumentationContext.class.getName(), context);
|
||||
this.attributes.put(WriterResolver.class.getName(), new StandardWriterResolver(
|
||||
new RestDocumentationContextPlaceholderResolver(context)));
|
||||
new RestDocumentationContextPlaceholderResolver(context), "UTF-8",
|
||||
this.snippetFormat));
|
||||
return new StandardOperation(this.name,
|
||||
(this.requestBuilder == null ? new OperationRequestBuilder(
|
||||
"http://localhost/").buildRequest() : this.requestBuilder
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.snippet.SnippetFormat;
|
||||
import org.springframework.restdocs.snippet.SnippetFormats;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@@ -45,37 +47,62 @@ public final class SnippetMatchers {
|
||||
|
||||
}
|
||||
|
||||
public static SnippetMatcher snippet() {
|
||||
return new SnippetMatcher();
|
||||
public static SnippetMatcher snippet(SnippetFormat snippetFormat) {
|
||||
return new SnippetMatcher(snippetFormat);
|
||||
}
|
||||
|
||||
public static AsciidoctorTableMatcher tableWithTitleAndHeader(String title,
|
||||
String... headers) {
|
||||
return new AsciidoctorTableMatcher(title, headers);
|
||||
public static TableMatcher<?> tableWithHeader(SnippetFormat format, String... headers) {
|
||||
if ("adoc".equals(format.getFileExtension())) {
|
||||
return new AsciidoctorTableMatcher(null, headers);
|
||||
}
|
||||
return new MarkdownTableMatcher(null, headers);
|
||||
}
|
||||
|
||||
public static AsciidoctorTableMatcher tableWithHeader(String... headers) {
|
||||
return new AsciidoctorTableMatcher(null, headers);
|
||||
public static TableMatcher<?> tableWithTitleAndHeader(SnippetFormat format,
|
||||
String title, String... headers) {
|
||||
if ("adoc".equals(format.getFileExtension())) {
|
||||
return new AsciidoctorTableMatcher(title, headers);
|
||||
}
|
||||
return new MarkdownTableMatcher(title, headers);
|
||||
}
|
||||
|
||||
public static HttpRequestMatcher httpRequest(RequestMethod method, String uri) {
|
||||
return new HttpRequestMatcher(method, uri);
|
||||
public static HttpRequestMatcher httpRequest(SnippetFormat format,
|
||||
RequestMethod requestMethod, String uri) {
|
||||
if ("adoc".equals(format.getFileExtension())) {
|
||||
return new HttpRequestMatcher(requestMethod, uri,
|
||||
new AsciidoctorCodeBlockMatcher<>("http"), 3);
|
||||
}
|
||||
return new HttpRequestMatcher(requestMethod, uri, new MarkdownCodeBlockMatcher<>(
|
||||
"http"), 2);
|
||||
}
|
||||
|
||||
public static HttpResponseMatcher httpResponse(HttpStatus status) {
|
||||
return new HttpResponseMatcher(status);
|
||||
public static HttpResponseMatcher httpResponse(SnippetFormat format, HttpStatus status) {
|
||||
if ("adoc".equals(format.getFileExtension())) {
|
||||
return new HttpResponseMatcher(status, new AsciidoctorCodeBlockMatcher<>(
|
||||
"http"), 3);
|
||||
}
|
||||
return new HttpResponseMatcher(status, new MarkdownCodeBlockMatcher<>("http"), 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public static AsciidoctorCodeBlockMatcher<?> codeBlock(String language) {
|
||||
return new AsciidoctorCodeBlockMatcher(language);
|
||||
public static CodeBlockMatcher<?> codeBlock(SnippetFormat format, String language) {
|
||||
if ("adoc".equals(format.getFileExtension())) {
|
||||
return new AsciidoctorCodeBlockMatcher(language);
|
||||
}
|
||||
return new MarkdownCodeBlockMatcher(language);
|
||||
}
|
||||
|
||||
private static abstract class AbstractSnippetContentMatcher extends
|
||||
BaseMatcher<String> {
|
||||
|
||||
private final SnippetFormat snippetFormat;
|
||||
|
||||
private List<String> lines = new ArrayList<>();
|
||||
|
||||
protected AbstractSnippetContentMatcher(SnippetFormat snippetFormat) {
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
protected void addLine(String line) {
|
||||
this.lines.add(line);
|
||||
}
|
||||
@@ -94,7 +121,7 @@ public final class SnippetMatchers {
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Asciidoctor snippet");
|
||||
description.appendText(this.snippetFormat.getFileExtension() + " snippet");
|
||||
description.appendText(getLinesAsString());
|
||||
}
|
||||
|
||||
@@ -123,17 +150,15 @@ public final class SnippetMatchers {
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for an Asciidoctor code block.
|
||||
* Base class for code block matchers.
|
||||
*
|
||||
* @param <T> The type of the matcher
|
||||
*/
|
||||
public static class AsciidoctorCodeBlockMatcher<T extends AsciidoctorCodeBlockMatcher<T>>
|
||||
extends AbstractSnippetContentMatcher {
|
||||
public static class CodeBlockMatcher<T extends CodeBlockMatcher<T>> extends
|
||||
AbstractSnippetContentMatcher {
|
||||
|
||||
protected AsciidoctorCodeBlockMatcher(String language) {
|
||||
this.addLine("[source," + language + "]");
|
||||
this.addLine("----");
|
||||
this.addLine("----");
|
||||
protected CodeBlockMatcher(SnippetFormat snippetFormat) {
|
||||
super(snippetFormat);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -144,32 +169,84 @@ public final class SnippetMatchers {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for an Asciidoctor code block.
|
||||
*
|
||||
* @param <T> The type of the matcher
|
||||
*/
|
||||
public static class AsciidoctorCodeBlockMatcher<T extends AsciidoctorCodeBlockMatcher<T>>
|
||||
extends CodeBlockMatcher<T> {
|
||||
|
||||
protected AsciidoctorCodeBlockMatcher(String language) {
|
||||
super(SnippetFormats.asciidoctor());
|
||||
this.addLine("[source," + language + "]");
|
||||
this.addLine("----");
|
||||
this.addLine("----");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for a Markdown code block.
|
||||
*
|
||||
* @param <T> The type of the matcher
|
||||
*/
|
||||
public static class MarkdownCodeBlockMatcher<T extends MarkdownCodeBlockMatcher<T>>
|
||||
extends CodeBlockMatcher<T> {
|
||||
|
||||
protected MarkdownCodeBlockMatcher(String language) {
|
||||
super(SnippetFormats.markdown());
|
||||
this.addLine("```" + language);
|
||||
this.addLine("```");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for an HTTP request or response.
|
||||
*
|
||||
* @param <T> The type of the matcher
|
||||
*/
|
||||
public static abstract class HttpMatcher<T extends HttpMatcher<T>> extends
|
||||
AsciidoctorCodeBlockMatcher<HttpMatcher<T>> {
|
||||
BaseMatcher<String> {
|
||||
|
||||
private int headerOffset = 3;
|
||||
private final CodeBlockMatcher<?> delegate;
|
||||
|
||||
protected HttpMatcher() {
|
||||
super("http");
|
||||
private int headerOffset;
|
||||
|
||||
protected HttpMatcher(CodeBlockMatcher<?> delegate, int headerOffset) {
|
||||
this.delegate = delegate;
|
||||
this.headerOffset = headerOffset;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T header(String name, String value) {
|
||||
this.addLine(this.headerOffset++, name + ": " + value);
|
||||
this.delegate.addLine(this.headerOffset++, name + ": " + value);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T header(String name, long value) {
|
||||
this.addLine(this.headerOffset++, name + ": " + value);
|
||||
this.delegate.addLine(this.headerOffset++, name + ": " + value);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T content(String content) {
|
||||
this.delegate.addLine(-1, content);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
return this.delegate.matches(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
this.delegate.describeTo(description);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +255,9 @@ public final class SnippetMatchers {
|
||||
public static final class HttpResponseMatcher extends
|
||||
HttpMatcher<HttpResponseMatcher> {
|
||||
|
||||
private HttpResponseMatcher(HttpStatus status) {
|
||||
private HttpResponseMatcher(HttpStatus status, CodeBlockMatcher<?> delegate,
|
||||
int headerOffset) {
|
||||
super(delegate, headerOffset);
|
||||
this.content("HTTP/1.1 " + status.value() + " " + status.getReasonPhrase());
|
||||
this.content("");
|
||||
}
|
||||
@@ -190,20 +269,41 @@ public final class SnippetMatchers {
|
||||
*/
|
||||
public static final class HttpRequestMatcher extends HttpMatcher<HttpRequestMatcher> {
|
||||
|
||||
private HttpRequestMatcher(RequestMethod requestMethod, String uri) {
|
||||
private HttpRequestMatcher(RequestMethod requestMethod, String uri,
|
||||
CodeBlockMatcher<?> delegate, int headerOffset) {
|
||||
super(delegate, headerOffset);
|
||||
this.content(requestMethod.name() + " " + uri + " HTTP/1.1");
|
||||
this.content("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for table matchers.
|
||||
*
|
||||
* @param <T> The concrete type of the matcher
|
||||
*/
|
||||
public static abstract class TableMatcher<T extends TableMatcher<T>> extends
|
||||
AbstractSnippetContentMatcher {
|
||||
|
||||
protected TableMatcher(SnippetFormat snippetFormat) {
|
||||
super(snippetFormat);
|
||||
}
|
||||
|
||||
public abstract T row(String... entries);
|
||||
|
||||
public abstract T configuration(String configuration);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for an Asciidoctor table.
|
||||
*/
|
||||
public static final class AsciidoctorTableMatcher extends
|
||||
AbstractSnippetContentMatcher {
|
||||
TableMatcher<AsciidoctorTableMatcher> {
|
||||
|
||||
private AsciidoctorTableMatcher(String title, String... columns) {
|
||||
super(SnippetFormats.asciidoctor());
|
||||
if (StringUtils.hasText(title)) {
|
||||
this.addLine("." + title);
|
||||
}
|
||||
@@ -216,6 +316,7 @@ public final class SnippetMatchers {
|
||||
this.addLine("|===");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorTableMatcher row(String... entries) {
|
||||
for (String entry : entries) {
|
||||
this.addLine(-1, "|" + entry);
|
||||
@@ -224,19 +325,68 @@ public final class SnippetMatchers {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorTableMatcher configuration(String configuration) {
|
||||
this.addLine(0, configuration);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for a Markdown table.
|
||||
*/
|
||||
public static final class MarkdownTableMatcher extends
|
||||
TableMatcher<MarkdownTableMatcher> {
|
||||
|
||||
private MarkdownTableMatcher(String title, String... columns) {
|
||||
super(SnippetFormats.asciidoctor());
|
||||
if (StringUtils.hasText(title)) {
|
||||
this.addLine(title);
|
||||
}
|
||||
String header = StringUtils.collectionToDelimitedString(
|
||||
Arrays.asList(columns), " | ");
|
||||
this.addLine(header);
|
||||
List<String> components = new ArrayList<>();
|
||||
for (String column : columns) {
|
||||
StringBuilder dashes = new StringBuilder();
|
||||
for (int i = 0; i < column.length(); i++) {
|
||||
dashes.append("-");
|
||||
}
|
||||
components.add(dashes.toString());
|
||||
}
|
||||
this.addLine(StringUtils.collectionToDelimitedString(components, " | "));
|
||||
this.addLine("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownTableMatcher row(String... entries) {
|
||||
this.addLine(-1, StringUtils.collectionToDelimitedString(
|
||||
Arrays.asList(entries), " | "));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownTableMatcher configuration(String configuration) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Markdown does not support table configuration");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Matcher} for a snippet file.
|
||||
*/
|
||||
public static class SnippetMatcher extends BaseMatcher<File> {
|
||||
public static final class SnippetMatcher extends BaseMatcher<File> {
|
||||
|
||||
private final SnippetFormat snippetFormat;
|
||||
|
||||
private Matcher<String> expectedContents;
|
||||
|
||||
private SnippetMatcher(SnippetFormat snippetFormat) {
|
||||
this.snippetFormat = snippetFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
if (snippetFileExists(item)) {
|
||||
@@ -285,7 +435,8 @@ public final class SnippetMatchers {
|
||||
this.expectedContents.describeTo(description);
|
||||
}
|
||||
else {
|
||||
description.appendText("Asciidoctor snippet");
|
||||
description
|
||||
.appendText(this.snippetFormat.getFileExtension() + " snippet");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,4 +446,5 @@ public final class SnippetMatchers {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{{title}}
|
||||
```bash
|
||||
$ curl {{url}} {{options}}
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
{{title}}
|
||||
```http
|
||||
{{method}} {{path}} HTTP/1.1
|
||||
{{#headers}}
|
||||
{{name}}: {{value}}
|
||||
{{/headers}}
|
||||
{{requestBody}}
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
{{title}}
|
||||
```http
|
||||
HTTP/1.1 {{statusCode}} {{statusReason}}
|
||||
{{#headers}}
|
||||
{{name}}: {{value}}
|
||||
{{/headers}}
|
||||
{{responseBody}}
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
Relation | Description | Foo
|
||||
-------- | ----------- | ---
|
||||
{{#links}}
|
||||
{{rel}} | {{description}} | {{foo}}
|
||||
{{/links}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Relation | Description
|
||||
-------- | -----------
|
||||
{{#links}}
|
||||
{{rel}} | {{description}}
|
||||
{{/links}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Parameter | Description | Foo
|
||||
--------- | ----------- | ---
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}} | {{foo}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Path | Type | Description | Foo
|
||||
---- | ---- | ----------- | ---
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}} | {{foo}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Path | Type | Description
|
||||
---- | ---- | -----------
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description | Foo
|
||||
---- | ----------- | ---
|
||||
{{#headers}}
|
||||
{{name}} | {{description}} | {{foo}}
|
||||
{{/headers}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#headers}}
|
||||
{{name}} | {{description}}
|
||||
{{/headers}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Parameter | Description | Foo
|
||||
--------- | ----------- | ---
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}} | {{foo}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Parameter | Description
|
||||
--------- | -----------
|
||||
{{#parameters}}
|
||||
{{name}} | {{description}}
|
||||
{{/parameters}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Path | Type | Description | Foo
|
||||
---- | ---- | ----------- | ---
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}} | {{foo}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Path | Type | Description
|
||||
---- | ---- | -----------
|
||||
{{#fields}}
|
||||
{{path}} | {{type}} | {{description}}
|
||||
{{/fields}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description | Foo
|
||||
---- | ----------- | ---
|
||||
{{#headers}}
|
||||
{{name}} | {{description}} | {{foo}}
|
||||
{{/headers}}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{title}}
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#headers}}
|
||||
{{name}} | {{description}}
|
||||
{{/headers}}
|
||||
@@ -67,8 +67,8 @@ public class MockMvcRestDocumentationConfigurer
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
return new ConfigurerApplyingRequestPostProcessor(this.restDocumentation,
|
||||
Arrays.asList(getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer(), snippets(), this.uriConfigurer));
|
||||
Arrays.asList(snippets(), getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer(), this.uriConfigurer));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -75,6 +75,8 @@ import static org.springframework.restdocs.request.RequestDocumentation.pathPara
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.markdown;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
@@ -123,6 +125,20 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
"http-request.adoc", "http-response.adoc", "curl-request.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void markdownSnippetGeneration() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(this.context)
|
||||
.apply(new MockMvcRestDocumentationConfigurer(this.restDocumentation)
|
||||
.snippets().withEncoding("UTF-8").withFormat(markdown())).build();
|
||||
|
||||
mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andDo(document("basic-markdown"));
|
||||
assertExpectedSnippetFilesExist(new File(
|
||||
"build/generated-snippets/basic-markdown"), "http-request.md",
|
||||
"http-response.md", "curl-request.md");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithContent() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
@@ -130,10 +146,11 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
|
||||
mockMvc.perform(post("/").accept(MediaType.APPLICATION_JSON).content("content"))
|
||||
.andExpect(status().isOk()).andDo(document("curl-snippet-with-content"));
|
||||
assertThat(new File(
|
||||
"build/generated-snippets/curl-snippet-with-content/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-content/curl-request.adoc"),
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
codeBlock(asciidoctor(), "bash").content(
|
||||
"$ curl " + "'http://localhost:8080/' -i -X POST "
|
||||
+ "-H 'Accept: application/json' -d 'content'"))));
|
||||
}
|
||||
@@ -150,8 +167,8 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
codeBlock(asciidoctor(), "bash").content(
|
||||
"$ curl "
|
||||
+ "'http://localhost:8080/?foo=bar' -i -X POST "
|
||||
+ "-H 'Accept: application/json' -d 'a=alpha'"))));
|
||||
@@ -298,9 +315,9 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
|
||||
assertThat(
|
||||
new File("build/generated-snippets/original-request/http-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpRequest(RequestMethod.GET, "/").header("a", "alpha")
|
||||
.header("b", "bravo")
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
httpRequest(asciidoctor(), RequestMethod.GET, "/")
|
||||
.header("a", "alpha").header("b", "bravo")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("Host", "localhost")
|
||||
@@ -310,8 +327,9 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-request/http-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpRequest(RequestMethod.GET, "/").header("b", "bravo")
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
httpRequest(asciidoctor(), RequestMethod.GET, "/")
|
||||
.header("b", "bravo")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", MediaType.APPLICATION_JSON_VALUE)
|
||||
.content(prettyPrinted))));
|
||||
@@ -337,8 +355,8 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
+ "\"href\":\"href\"}]}";
|
||||
assertThat(
|
||||
new File("build/generated-snippets/original-response/http-response.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpResponse(HttpStatus.OK)
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
httpResponse(asciidoctor(), HttpStatus.OK)
|
||||
.header("a", "alpha")
|
||||
.header("Content-Type", "application/json")
|
||||
.header(HttpHeaders.CONTENT_LENGTH,
|
||||
@@ -348,8 +366,8 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-response/http-response.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpResponse(HttpStatus.OK)
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
httpResponse(asciidoctor(), HttpStatus.OK)
|
||||
.header("Content-Type", "application/json")
|
||||
.header(HttpHeaders.CONTENT_LENGTH,
|
||||
prettyPrinted.getBytes().length)
|
||||
@@ -376,7 +394,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
assertThat(new File(
|
||||
"build/generated-snippets/custom-snippet-template/curl-request.adoc"),
|
||||
is(snippet().withContents(equalTo("Custom curl request"))));
|
||||
is(snippet(asciidoctor()).withContents(equalTo("Custom curl request"))));
|
||||
|
||||
mockMvc.perform(get("/")).andDo(
|
||||
document(
|
||||
@@ -395,9 +413,9 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
.andExpect(status().isOk()).andDo(document("custom-context-path"));
|
||||
assertThat(
|
||||
new File("build/generated-snippets/custom-context-path/curl-request.adoc"),
|
||||
is(snippet()
|
||||
is(snippet(asciidoctor())
|
||||
.withContents(
|
||||
codeBlock("bash")
|
||||
codeBlock(asciidoctor(), "bash")
|
||||
.content(
|
||||
"$ curl 'http://localhost:8080/custom/' -i -H 'Accept: application/json'"))));
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ public final class RestAssuredRestDocumentationConfigurer
|
||||
|
||||
RestAssuredRestDocumentationConfigurer(RestDocumentation restDocumentation) {
|
||||
this.restDocumentation = restDocumentation;
|
||||
this.configurers = Arrays.asList(getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer(), snippets());
|
||||
this.configurers = Arrays.asList(snippets(), getTemplateEngineConfigurer(),
|
||||
getWriterResolverConfigurer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,6 +70,7 @@ import static org.springframework.restdocs.request.RequestDocumentation.requestP
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.restassured.operation.preprocess.RestAssuredPreprocessors.modifyUris;
|
||||
import static org.springframework.restdocs.snippet.SnippetFormats.asciidoctor;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.codeBlock;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpRequest;
|
||||
import static org.springframework.restdocs.test.SnippetMatchers.httpResponse;
|
||||
@@ -114,8 +115,8 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-content/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
codeBlock(asciidoctor(), "bash").content(
|
||||
"$ curl 'http://localhost:" + this.port + "/' -i "
|
||||
+ "-X POST -H 'Accept: application/json' "
|
||||
+ "-H 'Content-Type: " + contentType + "' "
|
||||
@@ -133,8 +134,8 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"),
|
||||
is(snippet().withContents(
|
||||
codeBlock("bash").content(
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
codeBlock(asciidoctor(), "bash").content(
|
||||
"$ curl " + "'http://localhost:" + this.port
|
||||
+ "/?foo=bar' -i -X POST "
|
||||
+ "-H 'Accept: application/json' "
|
||||
@@ -261,9 +262,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
.then().statusCode(200);
|
||||
assertThat(
|
||||
new File("build/generated-snippets/original-request/http-request.adoc"),
|
||||
is(snippet()
|
||||
is(snippet(asciidoctor())
|
||||
.withContents(
|
||||
httpRequest(RequestMethod.GET, "/")
|
||||
httpRequest(asciidoctor(), RequestMethod.GET, "/")
|
||||
.header("a", "alpha")
|
||||
.header("b", "bravo")
|
||||
.header("Accept",
|
||||
@@ -277,9 +278,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-request/http-request.adoc"),
|
||||
is(snippet()
|
||||
is(snippet(asciidoctor())
|
||||
.withContents(
|
||||
httpRequest(RequestMethod.GET, "/")
|
||||
httpRequest(asciidoctor(), RequestMethod.GET, "/")
|
||||
.header("b", "bravo")
|
||||
.header("Accept",
|
||||
MediaType.APPLICATION_JSON_VALUE)
|
||||
@@ -308,8 +309,8 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
assertThat(
|
||||
new File(
|
||||
"build/generated-snippets/preprocessed-response/http-response.adoc"),
|
||||
is(snippet().withContents(
|
||||
httpResponse(HttpStatus.OK)
|
||||
is(snippet(asciidoctor()).withContents(
|
||||
httpResponse(asciidoctor(), HttpStatus.OK)
|
||||
.header("Foo", "https://api.example.com/foo/bar")
|
||||
.header("Content-Type", "application/json;charset=UTF-8")
|
||||
.header(HttpHeaders.CONTENT_LENGTH,
|
||||
@@ -335,7 +336,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
assertThat(new File(
|
||||
"build/generated-snippets/custom-snippet-template/curl-request.adoc"),
|
||||
is(snippet().withContents(equalTo("Custom curl request"))));
|
||||
is(snippet(asciidoctor()).withContents(equalTo("Custom curl request"))));
|
||||
}
|
||||
|
||||
private void assertExpectedSnippetFilesExist(File directory, String... snippets) {
|
||||
|
||||
Reference in New Issue
Block a user