diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java index 89b0aecf..79801373 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java @@ -116,7 +116,6 @@ class XmlContentHandler implements ContentHandler { } for (int i = 0; i < matchingNodes.getLength(); i++) { Node node = matchingNodes.item(i); - if (node.getNodeType() == Node.ATTRIBUTE_NODE) { Attr attr = (Attr) node; attr.getOwnerElement().removeAttributeNode(attr); diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java index 72048301..ad6653d3 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java @@ -192,22 +192,78 @@ public class ResponseFieldsSnippetTests { .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) .build()); } - + @Test - public void undocumentedXmlWithAttributeResponseField() throws IOException { - this.thrown.expect(SnippetException.class); - this.thrown - .expectMessage(equalTo("The following parts of the payload were not" - + " documented:\r\n\r\n 5\r\n\r\n")); - new ResponseFieldsSnippet(Arrays.asList(new FieldDescriptor("/a/b/@id").type("").description(""))) - .document(new OperationBuilder("undocumented-xml-response-field", - this.snippet.getOutputDirectory()) + public void xmlAttribute() throws IOException { + this.snippet.expectResponseFields("xml-attribute").withContents( + tableWithHeader("Path", "Type", "Description").row("a", "b", "one").row( + "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()) .response() - .content("5") + .content("foo") .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("foo") + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) + .build()); + } + + @Test + public void missingOptionalXmlAttribute() throws IOException { + this.snippet.expectResponseFields("missing-optional-xml-attribute").withContents( + tableWithHeader("Path", "Type", "Description").row("a", "b", "one").row( + "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()) + .response().content("foo") + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) + .build()); + } + + @Test + public void undocumentedAttributeDoesNotCauseFailure() throws IOException { + 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() + .content("bar") + .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:" + + "%nbar%n"))); + new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one") + .type("a"))).document(new OperationBuilder( + "documented-attribute-is-removed", this.snippet.getOutputDirectory()) + .response().content("bar") + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) + .build()); + } + @Test public void xmlResponseFieldWithNoType() throws IOException { this.thrown.expect(FieldTypeRequiredException.class);