From 0699cdd068f042aee98ea454b343c4cae18fad73 Mon Sep 17 00:00:00 2001 From: Kellen Dye Date: Wed, 10 Jun 2015 15:48:57 +0200 Subject: [PATCH] Allow links to be optional Previously, if a link was documented then it had to be present in the response payload for the test to pass. This was unnecessarily restrictive and caused problems when a link was omitted due to the application's current state. This commit allows a link to be declared as optional. If a link is optional then the test will pass irrespective of the link's presence in the response. See gh-74 --- .../restdocs/hypermedia/LinkDescriptor.java | 16 ++++++++++++++ .../hypermedia/LinkSnippetResultHandler.java | 12 ++++++----- .../HypermediaDocumentationTests.java | 21 ++++++++++++++++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java index 24a2044c..dca8adcb 100644 --- a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java @@ -29,6 +29,8 @@ public class LinkDescriptor { private String description; + private boolean optional; + LinkDescriptor(String rel) { this.rel = rel; } @@ -44,6 +46,16 @@ public class LinkDescriptor { return this; } + /** + * Marks the link as optional + * + * @return {@code this} + */ + public LinkDescriptor optional() { + this.optional = true; + return this; + } + String getRel() { return this.rel; } @@ -51,4 +63,8 @@ public class LinkDescriptor { String getDescription() { return this.description; } + + boolean isOptional() { + return this.optional; + } } diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java index 5bd8cbe7..033364cd 100644 --- a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java @@ -42,6 +42,8 @@ public class LinkSnippetResultHandler extends SnippetWritingResultHandler { private final Map descriptorsByRel = new LinkedHashMap<>(); + private final Set requiredRels = new HashSet(); + private final LinkExtractor extractor; LinkSnippetResultHandler(String outputDir, LinkExtractor linkExtractor, @@ -52,6 +54,9 @@ public class LinkSnippetResultHandler extends SnippetWritingResultHandler { Assert.hasText(descriptor.getRel()); Assert.hasText(descriptor.getDescription()); this.descriptorsByRel.put(descriptor.getRel(), descriptor); + if (!descriptor.isOptional()) { + this.requiredRels.add(descriptor.getRel()); + } } } @@ -78,12 +83,11 @@ public class LinkSnippetResultHandler extends SnippetWritingResultHandler { } Set actualRels = links.keySet(); - Set expectedRels = this.descriptorsByRel.keySet(); Set undocumentedRels = new HashSet(actualRels); - undocumentedRels.removeAll(expectedRels); + undocumentedRels.removeAll(this.descriptorsByRel.keySet()); - Set missingRels = new HashSet(expectedRels); + Set missingRels = new HashSet(this.requiredRels); missingRels.removeAll(actualRels); if (!undocumentedRels.isEmpty() || !missingRels.isEmpty()) { @@ -102,8 +106,6 @@ public class LinkSnippetResultHandler extends SnippetWritingResultHandler { throw new SnippetGenerationException(message); } - Assert.isTrue(actualRels.equals(expectedRels)); - writer.table(new TableAction() { @Override diff --git a/spring-restdocs/src/test/java/org/springframework/restdocs/hypermedia/HypermediaDocumentationTests.java b/spring-restdocs/src/test/java/org/springframework/restdocs/hypermedia/HypermediaDocumentationTests.java index 8f7df315..56588a06 100644 --- a/spring-restdocs/src/test/java/org/springframework/restdocs/hypermedia/HypermediaDocumentationTests.java +++ b/spring-restdocs/src/test/java/org/springframework/restdocs/hypermedia/HypermediaDocumentationTests.java @@ -60,10 +60,29 @@ public class HypermediaDocumentationTests { this.thrown.expect(SnippetGenerationException.class); this.thrown.expectMessage(equalTo("Links with the following relations were not" + " found in the response: [foo]")); - documentLinks("undocumented-link", new StubLinkExtractor(), + documentLinks("missing-link", new StubLinkExtractor(), new LinkDescriptor("foo").description("bar")).handle(result()); } + @Test + public void documentedOptionalLink() throws IOException { + this.snippet.expectLinks("documented-optional-link").withContents( // + tableWithHeader("Relation", "Description") // + .row("foo", "bar")); + documentLinks("documented-optional-link", + new StubLinkExtractor().withLinks(new Link("foo", "blah")), + new LinkDescriptor("foo").description("bar").optional()).handle(result()); + } + + @Test + public void missingOptionalLink() throws IOException { + this.snippet.expectLinks("missing-optional-link").withContents( // + tableWithHeader("Relation", "Description") // + .row("foo", "bar")); + documentLinks("missing-optional-link", new StubLinkExtractor(), + new LinkDescriptor("foo").description("bar").optional()).handle(result()); + } + @Test public void undocumentedLinkAndMissingLink() throws IOException { this.thrown.expect(SnippetGenerationException.class);