Skip to content

Commit 8b039e5

Browse files
committed
Add support for reusing a snippet to document common elements
This commit updates all of the Snippet implementations that take one or more descriptors to provide an and method that can be used to create a new Snippet that has additional descriptors. Closes gh-168
1 parent feb2f35 commit 8b039e5

24 files changed

+435
-36
lines changed

docs/src/docs/asciidoc/documenting-your-api.adoc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,45 @@ When documenting HTTP Headers, the test will fail if a documented header is not
445445
the request or response.
446446

447447

448+
449+
[[documenting-your-api-reusing-snippets]]
450+
=== Reusing snippets
451+
452+
It's common for an API that's being documented to have some features that are common
453+
across several of its resources. To avoid repetition when documenting such resources a
454+
`Snippet` configured with the common elements can be reused.
455+
456+
First, create the `Snippet` that describes the common elements. For example:
457+
458+
[source,java,indent=0]
459+
----
460+
include::{examples-dir}/com/example/SnippetReuse.java[tags=field]
461+
----
462+
463+
Second, use this snippet and add further descriptors that are resource-specific. For
464+
example:
465+
466+
[source,java,indent=0,role="primary"]
467+
.MockMvc
468+
----
469+
include::{examples-dir}/com/example/mockmvc/MockMvcSnippetReuse.java[tags=use]
470+
----
471+
<1> Reuse the `pagingLinks` `Snippet` calling `and` to add descriptors that are specific
472+
to the resource that is being documented.
473+
474+
[source,java,indent=0,role="secondary"]
475+
.REST Assured
476+
----
477+
include::{examples-dir}/com/example/restassured/RestAssuredSnippetReuse.java[tags=use]
478+
----
479+
<1> Reuse the `pagingLinks` `Snippet` calling `and` to add descriptors that are specific
480+
to the resource that is being documented.
481+
482+
The result of the example is that links with the rels `first`, `last`, `next`, `previous`,
483+
`alpha`, and `bravo` are all documented.
484+
485+
486+
448487
[[documenting-your-api-constraints]]
449488
=== Documenting constraints
450489

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2012-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example;
18+
19+
import org.springframework.restdocs.hypermedia.LinksSnippet;
20+
21+
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
22+
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
23+
24+
public class SnippetReuse {
25+
26+
// tag::field[]
27+
protected final LinksSnippet pagingLinks = links(
28+
linkWithRel("first").optional().description("The first page of results"),
29+
linkWithRel("last").optional().description("The last page of results"),
30+
linkWithRel("next").optional().description("The next page of results"),
31+
linkWithRel("prev").optional().description("The previous page of results"));
32+
// end::field[]
33+
34+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.mockmvc;
18+
19+
import com.example.SnippetReuse;
20+
21+
import org.springframework.http.MediaType;
22+
import org.springframework.test.web.servlet.MockMvc;
23+
24+
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
25+
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
26+
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
27+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
28+
29+
public class MockMvcSnippetReuse extends SnippetReuse {
30+
31+
private MockMvc mockMvc;
32+
33+
public void documentation() throws Exception {
34+
// tag::use[]
35+
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
36+
.andExpect(status().isOk())
37+
.andDo(document("example", this.pagingLinks.and( // <1>
38+
linkWithRel("alpha").description("Link to the alpha resource"),
39+
linkWithRel("bravo").description("Link to the bravo resource"))));
40+
// end::use[]
41+
}
42+
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.restassured;
18+
19+
import com.example.SnippetReuse;
20+
import com.jayway.restassured.RestAssured;
21+
import com.jayway.restassured.specification.RequestSpecification;
22+
23+
24+
import static org.hamcrest.CoreMatchers.is;
25+
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
26+
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
27+
28+
public class RestAssuredSnippetReuse extends SnippetReuse {
29+
30+
private RequestSpecification spec;
31+
32+
public void documentation() throws Exception {
33+
// tag::use[]
34+
RestAssured.given(this.spec)
35+
.accept("application/json")
36+
.filter(document("example", this.pagingLinks.and( // <1>
37+
linkWithRel("alpha").description("Link to the alpha resource"),
38+
linkWithRel("bravo").description("Link to the bravo resource"))))
39+
.get("/").then().assertThat().statusCode(is(200));
40+
// end::use[]
41+
}
42+
43+
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/headers/HeaderDocumentation.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ public static HeaderDescriptor headerWithName(String name) {
5555
* @return the snippet that will document the request headers
5656
* @see #headerWithName(String)
5757
*/
58-
public static Snippet requestHeaders(HeaderDescriptor... descriptors) {
58+
public static RequestHeadersSnippet requestHeaders(HeaderDescriptor... descriptors) {
5959
return new RequestHeadersSnippet(Arrays.asList(descriptors));
6060
}
6161

@@ -72,7 +72,7 @@ public static Snippet requestHeaders(HeaderDescriptor... descriptors) {
7272
* @return the snippet that will document the request headers
7373
* @see #headerWithName(String)
7474
*/
75-
public static Snippet requestHeaders(Map<String, Object> attributes,
75+
public static RequestHeadersSnippet requestHeaders(Map<String, Object> attributes,
7676
HeaderDescriptor... descriptors) {
7777
return new RequestHeadersSnippet(Arrays.asList(descriptors), attributes);
7878
}
@@ -88,7 +88,8 @@ public static Snippet requestHeaders(Map<String, Object> attributes,
8888
* @return the snippet that will document the response headers
8989
* @see #headerWithName(String)
9090
*/
91-
public static Snippet responseHeaders(HeaderDescriptor... descriptors) {
91+
public static ResponseHeadersSnippet responseHeaders(
92+
HeaderDescriptor... descriptors) {
9293
return new ResponseHeadersSnippet(Arrays.asList(descriptors));
9394
}
9495

@@ -106,7 +107,7 @@ public static Snippet responseHeaders(HeaderDescriptor... descriptors) {
106107
* @return the snippet that will document the response headers
107108
* @see #headerWithName(String)
108109
*/
109-
public static Snippet responseHeaders(Map<String, Object> attributes,
110+
public static ResponseHeadersSnippet responseHeaders(Map<String, Object> attributes,
110111
HeaderDescriptor... descriptors) {
111112
return new ResponseHeadersSnippet(Arrays.asList(descriptors), attributes);
112113
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/headers/RequestHeadersSnippet.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.restdocs.headers;
1818

19+
import java.util.ArrayList;
20+
import java.util.Arrays;
1921
import java.util.List;
2022
import java.util.Map;
2123
import java.util.Set;
@@ -27,6 +29,7 @@
2729
* A {@link Snippet} that documents the headers in a request.
2830
*
2931
* @author Andreas Evers
32+
* @author Andy Wilkinson
3033
* @see HeaderDocumentation#requestHeaders(HeaderDescriptor...)
3134
* @see HeaderDocumentation#requestHeaders(Map, HeaderDescriptor...)
3235
*/
@@ -60,4 +63,18 @@ protected Set<String> extractActualHeaders(Operation operation) {
6063
return operation.getRequest().getHeaders().keySet();
6164
}
6265

66+
/**
67+
* Returns a new {@code RequestHeadersSnippet} configured with this snippet's
68+
* attributes and its descriptors combined with the given
69+
* {@code additionalDescriptors}.
70+
* @param additionalDescriptors the additional descriptors
71+
* @return the new snippet
72+
*/
73+
public RequestHeadersSnippet and(HeaderDescriptor... additionalDescriptors) {
74+
List<HeaderDescriptor> combinedDescriptors = new ArrayList<>();
75+
combinedDescriptors.addAll(this.getHeaderDescriptors());
76+
combinedDescriptors.addAll(Arrays.asList(additionalDescriptors));
77+
return new RequestHeadersSnippet(combinedDescriptors, getAttributes());
78+
}
79+
6380
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/headers/ResponseHeadersSnippet.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.restdocs.headers;
1818

19+
import java.util.ArrayList;
20+
import java.util.Arrays;
1921
import java.util.List;
2022
import java.util.Map;
2123
import java.util.Set;
@@ -27,6 +29,7 @@
2729
* A {@link Snippet} that documents the headers in a response.
2830
*
2931
* @author Andreas Evers
32+
* @author Andy Wilkinson
3033
* @see HeaderDocumentation#responseHeaders(HeaderDescriptor...)
3134
* @see HeaderDocumentation#responseHeaders(Map, HeaderDescriptor...)
3235
*/
@@ -60,4 +63,18 @@ protected Set<String> extractActualHeaders(Operation operation) {
6063
return operation.getResponse().getHeaders().keySet();
6164
}
6265

66+
/**
67+
* Returns a new {@code ResponseHeadersSnippet} configured with this snippet's
68+
* attributes and its descriptors combined with the given
69+
* {@code additionalDescriptors}.
70+
* @param additionalDescriptors the additional descriptors
71+
* @return the new snippet
72+
*/
73+
public final ResponseHeadersSnippet and(HeaderDescriptor... additionalDescriptors) {
74+
List<HeaderDescriptor> combinedDescriptors = new ArrayList<>();
75+
combinedDescriptors.addAll(this.getHeaderDescriptors());
76+
combinedDescriptors.addAll(Arrays.asList(additionalDescriptors));
77+
return new ResponseHeadersSnippet(combinedDescriptors, getAttributes());
78+
}
79+
6380
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpDocumentation.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@
1818

1919
import java.util.Map;
2020

21-
import org.springframework.restdocs.snippet.Snippet;
22-
2321
/**
2422
* Static factory methods for documenting a RESTful API's HTTP requests.
2523
*
@@ -38,7 +36,7 @@ private HttpDocumentation() {
3836
*
3937
* @return the snippet that will document the HTTP request
4038
*/
41-
public static Snippet httpRequest() {
39+
public static HttpRequestSnippet httpRequest() {
4240
return new HttpRequestSnippet();
4341
}
4442

@@ -50,7 +48,7 @@ public static Snippet httpRequest() {
5048
* @param attributes the attributes
5149
* @return the snippet that will document the HTTP request
5250
*/
53-
public static Snippet httpRequest(Map<String, Object> attributes) {
51+
public static HttpRequestSnippet httpRequest(Map<String, Object> attributes) {
5452
return new HttpRequestSnippet(attributes);
5553
}
5654

@@ -60,7 +58,7 @@ public static Snippet httpRequest(Map<String, Object> attributes) {
6058
*
6159
* @return the snippet that will document the HTTP response
6260
*/
63-
public static Snippet httpResponse() {
61+
public static HttpResponseSnippet httpResponse() {
6462
return new HttpResponseSnippet();
6563
}
6664

@@ -72,7 +70,7 @@ public static Snippet httpResponse() {
7270
* @param attributes the attributes
7371
* @return the snippet that will document the HTTP response
7472
*/
75-
public static Snippet httpResponse(Map<String, Object> attributes) {
73+
public static HttpResponseSnippet httpResponse(Map<String, Object> attributes) {
7674
return new HttpResponseSnippet(attributes);
7775
}
7876

0 commit comments

Comments
 (0)