From ff7119ec542dfd2d0b6ed4ed37d2e1b16c3916ec Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Mon, 17 Nov 2014 12:28:11 -0600 Subject: [PATCH] RestDocumentationResultActions->RestDocumentationResultHandler Previously documentation was handled by using a ResultActions implementation that had custom methods added to it. Now documentation is handled using a ResultHandler. This has a few advantages: - Fit better with the MockMvc programming model. This is similar to andDo(print()) - Support for using alwaysDo --- .../com/example/notes/ApiDocumentation.java | 119 +++++++++-------- .../notes/GettingStartedDocumentation.java | 121 +++++++++--------- .../com/example/notes/ApiDocumentation.java | 117 ++++++++--------- .../notes/GettingStartedDocumentation.java | 118 +++++++++-------- .../restdocs/core/RestDocumentation.java | 40 +++--- .../core/RestDocumentationResultActions.java | 63 --------- .../core/RestDocumentationResultHandler.java | 52 ++++++++ 7 files changed, 297 insertions(+), 333 deletions(-) delete mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultActions.java create mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java diff --git a/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/ApiDocumentation.java b/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/ApiDocumentation.java index 2c99a395..e3d26418 100644 --- a/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/ApiDocumentation.java +++ b/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/ApiDocumentation.java @@ -19,8 +19,8 @@ package com.example.notes; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.springframework.restdocs.core.RestDocumentation.document; -import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; import static org.springframework.restdocs.core.RestDocumentation.halLinks; +import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -76,34 +76,33 @@ public class ApiDocumentation { @Test public void errorExample() throws Exception { - document( - "error-example", - this.mockMvc - .perform(get("/error") - .requestAttr(RequestDispatcher.ERROR_STATUS_CODE, 400) - .requestAttr(RequestDispatcher.ERROR_REQUEST_URI, - "/notes") - .requestAttr(RequestDispatcher.ERROR_MESSAGE, - "The tag 'http://localhost:8080/tags/123' does not exist"))) + this.mockMvc + .perform(get("/error") + .requestAttr(RequestDispatcher.ERROR_STATUS_CODE, 400) + .requestAttr(RequestDispatcher.ERROR_REQUEST_URI, + "/notes") + .requestAttr(RequestDispatcher.ERROR_MESSAGE, + "The tag 'http://localhost:8080/tags/123' does not exist")) .andDo(print()).andExpect(status().isBadRequest()) .andExpect(jsonPath("error", is("Bad Request"))) .andExpect(jsonPath("timestamp", is(notNullValue()))) .andExpect(jsonPath("status", is(400))) - .andExpect(jsonPath("path", is(notNullValue()))); + .andExpect(jsonPath("path", is(notNullValue()))) + .andDo(document("error-example")); } @Test public void indexExample() throws Exception { - document("index-example", - this.mockMvc.perform(get("/")).andExpect(status().isOk())) - .andDocumentLinks( - halLinks(), + this.mockMvc.perform(get("/")) + .andExpect(status().isOk()) + .andDo(document("index-example").withLinks(halLinks(), linkWithRel("notes").description( "The <>"), linkWithRel("tags").description( "The <>"), linkWithRel("profile").description( - "The ALPS profile for the service")); + "The ALPS profile for the service"))); + } @Test @@ -116,8 +115,9 @@ public class ApiDocumentation { "http://stateless.co/hal_specification.html"); createNote("Application-Level Profile Semantics (ALPS)", "http://alps.io/spec/"); - document("notes-list-example", this.mockMvc.perform(get("/notes"))).andExpect( - status().isOk()); + this.mockMvc.perform(get("/notes")) + .andExpect(status().isOk()) + .andDo(document("notes-list-example")); } @Test @@ -137,12 +137,11 @@ public class ApiDocumentation { note.put("body", "http://martinfowler.com/articles/richardsonMaturityModel.html"); note.put("tags", Arrays.asList(tagLocation)); - document( - "notes-create-example", - this.mockMvc.perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(note))).andExpect( - status().isCreated())); + this.mockMvc.perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(note))).andExpect( + status().isCreated()) + .andDo(document("notes-create-example")); } @Test @@ -169,17 +168,17 @@ public class ApiDocumentation { .andExpect(status().isCreated()).andReturn().getResponse() .getHeader("Location"); - document("note-get-example", this.mockMvc.perform(get(noteLocation))) - .andExpect(status().isOk()) - .andExpect(jsonPath("title", is(note.get("title")))) - .andExpect(jsonPath("body", is(note.get("body")))) - .andExpect(jsonPath("_links.self.href", is(noteLocation))) - .andExpect(jsonPath("_links.tags", is(notNullValue()))) - .andDocumentLinks( - halLinks(), - linkWithRel("self").description("This <>"), - linkWithRel("tags").description( - "This note's <>")); + this.mockMvc.perform(get(noteLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("title", is(note.get("title")))) + .andExpect(jsonPath("body", is(note.get("body")))) + .andExpect(jsonPath("_links.self.href", is(noteLocation))) + .andExpect(jsonPath("_links.tags", is(notNullValue()))) + .andDo(document("note-get-example") + .withLinks(halLinks(), + linkWithRel("self").description("This <>"), + linkWithRel("tags").description( + "This note's <>"))); } @@ -192,8 +191,9 @@ public class ApiDocumentation { createTag("Hypermedia"); createTag("HTTP"); - document("tags-list-example", this.mockMvc.perform(get("/tags"))).andExpect( - status().isOk()); + this.mockMvc.perform(get("/tags")) + .andExpect(status().isOk()) + .andDo(document("tags-list-example")); } @Test @@ -201,12 +201,11 @@ public class ApiDocumentation { Map tag = new HashMap(); tag.put("name", "REST"); - document( - "tags-create-example", - this.mockMvc.perform( - post("/tags").contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(tag))).andExpect( - status().isCreated())); + this.mockMvc.perform( + post("/tags").contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(tag))).andExpect( + status().isCreated()) + .andDo(document("tags-create-example")); } @Test @@ -241,12 +240,11 @@ public class ApiDocumentation { Map noteUpdate = new HashMap(); noteUpdate.put("tags", Arrays.asList(tagLocation)); - document( - "note-update-example", - this.mockMvc.perform( - patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(noteUpdate))) - .andExpect(status().isNoContent())); + this.mockMvc.perform( + patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(noteUpdate))) + .andExpect(status().isNoContent()) + .andDo(document("note-update-example")); } @Test @@ -261,16 +259,14 @@ public class ApiDocumentation { .andExpect(status().isCreated()).andReturn().getResponse() .getHeader("Location"); - document("tag-get-example", this.mockMvc.perform(get(tagLocation))) - .andExpect(status().isOk()) - .andExpect(jsonPath("name", is(tag.get("name")))) - .andDocumentLinks( - halLinks(), + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("name", is(tag.get("name")))) + .andDo(document("tag-get-example").withLinks(halLinks(), linkWithRel("self").description("This <>"), linkWithRel("notes") .description( - "The <> that have this tag")); - + "The <> that have this tag"))); } @Test @@ -288,12 +284,11 @@ public class ApiDocumentation { Map tagUpdate = new HashMap(); tagUpdate.put("name", "RESTful"); - document( - "tag-update-example", - this.mockMvc.perform( - patch(tagLocation).contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(tagUpdate))) - .andExpect(status().isNoContent())); + this.mockMvc.perform( + patch(tagLocation).contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(tagUpdate))) + .andExpect(status().isNoContent()) + .andDo(document("tag-update-example")); } private void createNote(String title, String body) { diff --git a/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/GettingStartedDocumentation.java b/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/GettingStartedDocumentation.java index fe7e0e65..8687ff2a 100644 --- a/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/GettingStartedDocumentation.java +++ b/rest-notes-spring-data-rest/src/documentation/java/com/example/notes/GettingStartedDocumentation.java @@ -71,12 +71,11 @@ public class GettingStartedDocumentation { @Test public void index() throws Exception { - document( - "index", - this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("_links.notes", is(notNullValue()))) - .andExpect(jsonPath("_links.tags", is(notNullValue())))); + this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_links.notes", is(notNullValue()))) + .andExpect(jsonPath("_links.tags", is(notNullValue()))) + .andDo(document("index")); } @Test @@ -101,49 +100,47 @@ public class GettingStartedDocumentation { note.put("title", "Note creation with cURL"); note.put("body", "An example of how to create a note using cURL"); - String noteLocation = document( - "create-note", - this.mockMvc - .perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(note))) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) + String noteLocation = this.mockMvc + .perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(note))) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-note")) .andReturn().getResponse().getHeader("Location"); return noteLocation; } void getNote(String noteLocation) throws Exception { - document( - "get-note", - this.mockMvc.perform(get(noteLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("title", is(notNullValue()))) - .andExpect(jsonPath("body", is(notNullValue()))) - .andExpect(jsonPath("_links.tags", is(notNullValue())))); + this.mockMvc.perform(get(noteLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("title", is(notNullValue()))) + .andExpect(jsonPath("body", is(notNullValue()))) + .andExpect(jsonPath("_links.tags", is(notNullValue()))) + .andDo(document("get-note")); } String createTag() throws Exception, JsonProcessingException { Map tag = new HashMap(); tag.put("name", "getting-started"); - String tagLocation = document( - "create-tag", - this.mockMvc - .perform( - post("/tags").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(tag))) + String tagLocation = this.mockMvc + .perform( + post("/tags").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(tag))) .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) - .andReturn().getResponse().getHeader("Location"); + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-tag")) + .andReturn().getResponse().getHeader("Location"); return tagLocation; } void getTag(String tagLocation) throws Exception { - document( - "get-tag", - this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("name", is(notNullValue()))) - .andExpect(jsonPath("_links.notes", is(notNullValue())))); + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("name", is(notNullValue()))) + .andExpect(jsonPath("_links.notes", is(notNullValue()))) + .andDo(document("get-tag")); } String createTaggedNote(String tag) throws Exception { @@ -152,59 +149,61 @@ public class GettingStartedDocumentation { note.put("body", "An example of how to create a tagged note using cURL"); note.put("tags", Arrays.asList(tag)); - String noteLocation = document( - "create-tagged-note", - this.mockMvc - .perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(note))) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) + String noteLocation = this.mockMvc + .perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(note))) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-tagged-note")) .andReturn().getResponse().getHeader("Location"); return noteLocation; } void getTaggedNote(String tagLocation) throws Exception { - document( - "get-tagged-note", - this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("title", is(notNullValue()))) - .andExpect(jsonPath("body", is(notNullValue()))) - .andExpect(jsonPath("_links.tags", is(notNullValue())))); + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("title", is(notNullValue()))) + .andExpect(jsonPath("body", is(notNullValue()))) + .andExpect(jsonPath("_links.tags", is(notNullValue()))) + .andDo(document("get-tagged-note")); } void getTags(String taggedNoteLocation) throws Exception { String tagsLocation = getLink(this.mockMvc.perform(get(taggedNoteLocation)) .andReturn(), "tags"); - document("get-tags", - this.mockMvc.perform(get(tagsLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("_embedded.tags", hasSize(1)))); + + this.mockMvc.perform(get(tagsLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_embedded.tags", hasSize(1))) + .andDo(document("get-tags")); } void tagExistingNote(String noteLocation, String tagLocation) throws Exception { Map update = new HashMap(); update.put("tags", Arrays.asList(tagLocation)); - document( - "tag-existing-note", - this.mockMvc.perform( - patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(update))).andExpect( - status().isNoContent())); + this.mockMvc.perform( + patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(update))) + .andExpect(status().isNoContent()) + .andDo(document("tag-existing-note")); } void getTaggedExistingNote(String tagLocation) throws Exception { - document("get-tagged-existing-note", this.mockMvc.perform(get(tagLocation)) - .andExpect(status().isOk())); + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andDo(document("get-tagged-existing-note")); } void getTagsForExistingNote(String taggedNoteLocation) throws Exception { String tagsLocation = getLink(this.mockMvc.perform(get(taggedNoteLocation)) .andReturn(), "tags"); - document("get-tags-for-existing-note", - this.mockMvc.perform(get(tagsLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("_embedded.tags", hasSize(1)))); + this.mockMvc.perform(get(tagsLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_embedded.tags", hasSize(1))) + .andDo(document("get-tags-for-existing-note")); } private String getLink(MvcResult result, String href) diff --git a/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/ApiDocumentation.java b/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/ApiDocumentation.java index dfa12050..745c4bfe 100644 --- a/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/ApiDocumentation.java +++ b/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/ApiDocumentation.java @@ -76,32 +76,30 @@ public class ApiDocumentation { @Test public void errorExample() throws Exception { - document( - "error-example", - this.mockMvc - .perform(get("/error") - .requestAttr(RequestDispatcher.ERROR_STATUS_CODE, 400) - .requestAttr(RequestDispatcher.ERROR_REQUEST_URI, - "/notes") - .requestAttr(RequestDispatcher.ERROR_MESSAGE, - "The tag 'http://localhost:8080/tags/123' does not exist"))) - .andDo(print()).andExpect(status().isBadRequest()) - .andExpect(jsonPath("error", is("Bad Request"))) - .andExpect(jsonPath("timestamp", is(notNullValue()))) - .andExpect(jsonPath("status", is(400))) - .andExpect(jsonPath("path", is(notNullValue()))); + this.mockMvc + .perform(get("/error") + .requestAttr(RequestDispatcher.ERROR_STATUS_CODE, 400) + .requestAttr(RequestDispatcher.ERROR_REQUEST_URI, + "/notes") + .requestAttr(RequestDispatcher.ERROR_MESSAGE, + "The tag 'http://localhost:8080/tags/123' does not exist")) + .andDo(print()).andExpect(status().isBadRequest()) + .andExpect(jsonPath("error", is("Bad Request"))) + .andExpect(jsonPath("timestamp", is(notNullValue()))) + .andExpect(jsonPath("status", is(400))) + .andExpect(jsonPath("path", is(notNullValue()))) + .andDo(document("error-example")); } @Test public void indexExample() throws Exception { - document("index-example", - this.mockMvc.perform(get("/")) - .andExpect(status().isOk())) - .andDocumentLinks(halLinks(), + this.mockMvc.perform(get("/")) + .andExpect(status().isOk()) + .andDo(document("index-example").withLinks(halLinks(), linkWithRel("notes").description( "The <>"), linkWithRel("tags").description( - "The <>")); + "The <>"))); } @Test @@ -114,8 +112,9 @@ public class ApiDocumentation { "http://stateless.co/hal_specification.html"); createNote("Application-Level Profile Semantics (ALPS)", "http://alps.io/spec/"); - document("notes-list-example", this.mockMvc.perform(get("/notes"))).andExpect( - status().isOk()); + this.mockMvc.perform(get("/notes")) + .andExpect(status().isOk()) + .andDo(document("notes-list-example")); } @Test @@ -135,12 +134,11 @@ public class ApiDocumentation { note.put("body", "http://martinfowler.com/articles/richardsonMaturityModel.html"); note.put("tags", Arrays.asList(tagLocation)); - document( - "notes-create-example", - this.mockMvc.perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(note))).andExpect( - status().isCreated())); + this.mockMvc.perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(note))) + .andExpect(status().isCreated()) + .andDo(document("notes-create-example")); } @Test @@ -167,16 +165,16 @@ public class ApiDocumentation { .andExpect(status().isCreated()).andReturn().getResponse() .getHeader("Location"); - document("note-get-example", this.mockMvc.perform(get(noteLocation))) - .andExpect(status().isOk()) - .andExpect(jsonPath("title", is(note.get("title")))) - .andExpect(jsonPath("body", is(note.get("body")))) - .andExpect(jsonPath("_links.self.href", is(noteLocation))) - .andExpect(jsonPath("_links.note-tags", is(notNullValue()))) - .andDocumentLinks(halLinks(), + this.mockMvc.perform(get(noteLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("title", is(note.get("title")))) + .andExpect(jsonPath("body", is(note.get("body")))) + .andExpect(jsonPath("_links.self.href", is(noteLocation))) + .andExpect(jsonPath("_links.note-tags", is(notNullValue()))) + .andDo(document("note-get-example").withLinks(halLinks(), linkWithRel("self").description("This <>"), linkWithRel("note-tags").description( - "This note's <>")); + "This note's <>"))); } @@ -189,8 +187,9 @@ public class ApiDocumentation { createTag("Hypermedia"); createTag("HTTP"); - document("tags-list-example", this.mockMvc.perform(get("/tags"))).andExpect( - status().isOk()); + this.mockMvc.perform(get("/tags")) + .andExpect(status().isOk()) + .andDo(document("tags-list-example")); } @Test @@ -198,12 +197,11 @@ public class ApiDocumentation { Map tag = new HashMap(); tag.put("name", "REST"); - document( - "tags-create-example", - this.mockMvc.perform( - post("/tags").contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(tag))).andExpect( - status().isCreated())); + this.mockMvc.perform( + post("/tags").contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(tag))) + .andExpect(status().isCreated()) + .andDo(document("tags-create-example")); } @Test @@ -238,12 +236,11 @@ public class ApiDocumentation { Map noteUpdate = new HashMap(); noteUpdate.put("tags", Arrays.asList(tagLocation)); - document( - "note-update-example", - this.mockMvc.perform( - patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(noteUpdate))) - .andExpect(status().isNoContent())); + this.mockMvc.perform( + patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(noteUpdate))) + .andExpect(status().isNoContent()) + .andDo(document("note-update-example")); } @Test @@ -258,15 +255,14 @@ public class ApiDocumentation { .andExpect(status().isCreated()).andReturn().getResponse() .getHeader("Location"); - document("tag-get-example", this.mockMvc.perform(get(tagLocation))) - .andExpect(status().isOk()) - .andExpect(jsonPath("name", is(tag.get("name")))) - .andDocumentLinks(halLinks(), + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("name", is(tag.get("name")))) + .andDo(document("tag-get-example").withLinks(halLinks(), linkWithRel("self").description("This <>"), linkWithRel("tagged-notes") .description( - "The <> that have this tag")); - + "The <> that have this tag"))); } @Test @@ -284,12 +280,11 @@ public class ApiDocumentation { Map tagUpdate = new HashMap(); tagUpdate.put("name", "RESTful"); - document( - "tag-update-example", - this.mockMvc.perform( - patch(tagLocation).contentType(MediaTypes.HAL_JSON).content( - this.objectMapper.writeValueAsString(tagUpdate))) - .andExpect(status().isNoContent())); + this.mockMvc.perform( + patch(tagLocation).contentType(MediaTypes.HAL_JSON).content( + this.objectMapper.writeValueAsString(tagUpdate))) + .andExpect(status().isNoContent()) + .andDo(document("tag-update-example")); } private void createNote(String title, String body) { diff --git a/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/GettingStartedDocumentation.java b/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/GettingStartedDocumentation.java index 437cfb97..9c57ede9 100644 --- a/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/GettingStartedDocumentation.java +++ b/rest-notes-spring-hateoas/src/documentation/java/com/example/notes/GettingStartedDocumentation.java @@ -71,12 +71,11 @@ public class GettingStartedDocumentation { @Test public void index() throws Exception { - document( - "index", - this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("_links.notes", is(notNullValue()))) - .andExpect(jsonPath("_links.tags", is(notNullValue())))); + this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_links.notes", is(notNullValue()))) + .andExpect(jsonPath("_links.tags", is(notNullValue()))) + .andDo(document("index")); } @Test @@ -101,49 +100,45 @@ public class GettingStartedDocumentation { note.put("title", "Note creation with cURL"); note.put("body", "An example of how to create a note using cURL"); - String noteLocation = document( - "create-note", - this.mockMvc - .perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(note))) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) + String noteLocation = this.mockMvc + .perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(note))) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-note")) .andReturn().getResponse().getHeader("Location"); return noteLocation; } void getNote(String noteLocation) throws Exception { - document( - "get-note", - this.mockMvc.perform(get(noteLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("title", is(notNullValue()))) - .andExpect(jsonPath("body", is(notNullValue()))) - .andExpect(jsonPath("_links.note-tags", is(notNullValue())))); + this.mockMvc.perform(get(noteLocation)).andExpect(status().isOk()) + .andExpect(jsonPath("title", is(notNullValue()))) + .andExpect(jsonPath("body", is(notNullValue()))) + .andExpect(jsonPath("_links.note-tags", is(notNullValue()))) + .andDo(document("get-note")); } String createTag() throws Exception, JsonProcessingException { Map tag = new HashMap(); tag.put("name", "getting-started"); - String tagLocation = document( - "create-tag", - this.mockMvc - .perform( - post("/tags").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(tag))) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) + String tagLocation = this.mockMvc + .perform( + post("/tags").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(tag))) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-tag")) .andReturn().getResponse().getHeader("Location"); return tagLocation; } void getTag(String tagLocation) throws Exception { - document( - "get-tag", - this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("name", is(notNullValue()))) - .andExpect(jsonPath("_links.tagged-notes", is(notNullValue())))); + this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) + .andExpect(jsonPath("name", is(notNullValue()))) + .andExpect(jsonPath("_links.tagged-notes", is(notNullValue()))) + .andDo(document("get-tag")); } String createTaggedNote(String tag) throws Exception { @@ -152,59 +147,60 @@ public class GettingStartedDocumentation { note.put("body", "An example of how to create a tagged note using cURL"); note.put("tags", Arrays.asList(tag)); - String noteLocation = document( - "create-tagged-note", - this.mockMvc - .perform( - post("/notes").contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(note))) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", notNullValue()))) + String noteLocation = this.mockMvc + .perform( + post("/notes").contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(note))) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", notNullValue())) + .andDo(document("create-tagged-note")) .andReturn().getResponse().getHeader("Location"); return noteLocation; } void getTaggedNote(String tagLocation) throws Exception { - document( - "get-tagged-note", - this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("title", is(notNullValue()))) - .andExpect(jsonPath("body", is(notNullValue()))) - .andExpect(jsonPath("_links.note-tags", is(notNullValue())))); + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("title", is(notNullValue()))) + .andExpect(jsonPath("body", is(notNullValue()))) + .andExpect(jsonPath("_links.note-tags", is(notNullValue()))) + .andDo(document("get-tagged-note")); } void getTags(String taggedNoteLocation) throws Exception { String tagsLocation = getLink(this.mockMvc.perform(get(taggedNoteLocation)) .andReturn(), "note-tags"); - document("get-tags", - this.mockMvc.perform(get(tagsLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("_embedded.tags", hasSize(1)))); + this.mockMvc.perform(get(tagsLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_embedded.tags", hasSize(1))) + .andDo(document("get-tags")); } void tagExistingNote(String noteLocation, String tagLocation) throws Exception { Map update = new HashMap(); update.put("tags", Arrays.asList(tagLocation)); - document( - "tag-existing-note", - this.mockMvc.perform( - patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( - objectMapper.writeValueAsString(update))).andExpect( - status().isNoContent())); + this.mockMvc.perform( + patch(noteLocation).contentType(MediaTypes.HAL_JSON).content( + objectMapper.writeValueAsString(update))) + .andExpect(status().isNoContent()) + .andDo(document("tag-existing-note")); } void getTaggedExistingNote(String tagLocation) throws Exception { - document("get-tagged-existing-note", this.mockMvc.perform(get(tagLocation)) - .andExpect(status().isOk())); + this.mockMvc.perform(get(tagLocation)) + .andExpect(status().isOk()) + .andDo(document("get-tagged-existing-note")); } void getTagsForExistingNote(String taggedNoteLocation) throws Exception { String tagsLocation = getLink(this.mockMvc.perform(get(taggedNoteLocation)) .andReturn(), "note-tags"); - document("get-tags-for-existing-note", - this.mockMvc.perform(get(tagsLocation)).andExpect(status().isOk()) - .andExpect(jsonPath("_embedded.tags", hasSize(1)))); + this.mockMvc.perform(get(tagsLocation)) + .andExpect(status().isOk()) + .andExpect(jsonPath("_embedded.tags", hasSize(1))) + .andDo(document("get-tags-for-existing-note")); } private String getLink(MvcResult result, String rel) diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java index effbf6a0..2aa9865a 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java @@ -16,36 +16,26 @@ package org.springframework.restdocs.core; -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequest; -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequestAndResponse; -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlResponse; - import java.util.Map; -import org.springframework.test.web.servlet.ResultActions; - public class RestDocumentation { - public static RestDocumentationResultActions document(String outputDir, - ResultActions resultActions) throws Exception { - return new RestDocumentationResultActions(outputDir, resultActions) - .andDo(documentCurlRequest(outputDir).includeResponseHeaders()) - .andDo(documentCurlResponse(outputDir).includeResponseHeaders()) - .andDo(documentCurlRequestAndResponse(outputDir).includeResponseHeaders()); - } + public static RestDocumentationResultHandler document(String outputDir) throws Exception { + return new RestDocumentationResultHandler(outputDir); + } - public static LinkDescriptor linkWithRel(String rel) { - return new LinkDescriptor(rel); - } + public static LinkDescriptor linkWithRel(String rel) { + return new LinkDescriptor(rel); + } - public static LinkExtractor halLinks() { - return new LinkExtractor() { + public static LinkExtractor halLinks() { + return new LinkExtractor() { - @SuppressWarnings("unchecked") - @Override - public Map extractLinks(Map responseJson) { - return (Map) responseJson.get("_links"); - } - }; - } + @SuppressWarnings("unchecked") + @Override + public Map extractLinks(Map responseJson) { + return (Map) responseJson.get("_links"); + } + }; + } } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultActions.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultActions.java deleted file mode 100644 index 670a32e7..00000000 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultActions.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014 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.core; - -import java.util.Arrays; - -import org.springframework.restdocs.core.RestDocumentationResultHandlers.LinkDocumentingResultHandler; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.ResultHandler; -import org.springframework.test.web.servlet.ResultMatcher; - -public class RestDocumentationResultActions implements ResultActions { - - private final ResultActions delegate; - - private final String outputDir; - - public RestDocumentationResultActions(String outputDir, ResultActions delegate) { - this.outputDir = outputDir; - this.delegate = delegate; - } - - @Override - public RestDocumentationResultActions andExpect(ResultMatcher matcher) - throws Exception { - this.delegate.andExpect(matcher); - return this; - } - - @Override - public RestDocumentationResultActions andDo(ResultHandler handler) throws Exception { - this.delegate.andDo(handler); - return this; - } - - @Override - public MvcResult andReturn() { - return this.delegate.andReturn(); - } - - public RestDocumentationResultActions andDocumentLinks(LinkExtractor linkExtractor, LinkDescriptor... descriptors) - throws Exception { - this.delegate.andDo(new LinkDocumentingResultHandler(this.outputDir, linkExtractor, Arrays - .asList(descriptors))); - return this; - } - -} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java new file mode 100644 index 00000000..1e00cf4d --- /dev/null +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java @@ -0,0 +1,52 @@ +/* + * Copyright 2014 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.core; + +import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequest; +import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequestAndResponse; +import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlResponse; + +import java.util.Arrays; + +import org.springframework.restdocs.core.RestDocumentationResultHandlers.LinkDocumentingResultHandler; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultHandler; + +public class RestDocumentationResultHandler implements ResultHandler { + + private final String outputDir; + private ResultHandler linkDocumentingResultHandler; + + public RestDocumentationResultHandler(String outputDir) { + this.outputDir = outputDir; + } + + @Override + public void handle(MvcResult result) throws Exception { + documentCurlRequest(outputDir).includeResponseHeaders().handle(result); + documentCurlResponse(outputDir).includeResponseHeaders().handle(result); + documentCurlRequestAndResponse(outputDir).includeResponseHeaders().handle(result); + if(linkDocumentingResultHandler != null) { + linkDocumentingResultHandler.handle(result); + } + } + + public RestDocumentationResultHandler withLinks(LinkExtractor linkExtractor, LinkDescriptor... descriptors) { + linkDocumentingResultHandler = new LinkDocumentingResultHandler(outputDir, linkExtractor, Arrays.asList(descriptors)); + return this; + } +}