/** * Creates a {@code LinkDescriptor} that describes a link with the given {@code rel}. * @param rel the rel of the link * @return a {@code LinkDescriptor} ready for further configuration */ public static LinkDescriptor linkWithRel(String rel) { return new LinkDescriptor(rel); }
private LinkDescriptor createDescriptor(String description, LinkDescriptor source) { LinkDescriptor newDescriptor = new LinkDescriptor(source.getRel()) .description(description); if (source.isOptional()) { newDescriptor.optional(); } if (source.isIgnored()) { newDescriptor.ignored(); } return newDescriptor; }
/** * Returns a new {@code Snippet} that will document the links in the API operation's * response. Links will be extracted from the response automatically based on its * content type and will be documented using the given {@code descriptors}. * <p> * If a link is documented, is not marked as optional, and is not present in the * response, a failure will occur. Any undocumented links will be ignored. * <p> * If a descriptor does not have a {@link LinkDescriptor#description(Object) * description}, the {@link Link#getTitle() title} of the link will be used. If the * link does not have a title a failure will occur. * @param descriptors the descriptions of the response's links * @return the snippet that will document the links */ public static LinksSnippet relaxedLinks(List<LinkDescriptor> descriptors) { return new LinksSnippet(new ContentTypeLinkExtractor(), descriptors, true); }
@Test public void ignoredLink() throws IOException { 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(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`b`", "Link b")); }
@Test public void additionalDescriptors() throws IOException { HypermediaDocumentation .links(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")), new LinkDescriptor("a").description("one")) .and(new LinkDescriptor("b").description("two")) .document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`a`", "one") .row("`b`", "two")); }
public static LinksSnippet links(LinkDescriptor... descriptors) { return HypermediaDocumentation.links(linkWithRel("self").ignored().optional(), linkWithRel("curies").ignored()).and(descriptors); } // end::ignore-links[]
@Test public void multipleLinksWithDifferentRels() throws IOException { Map<String, List<Link>> links = this.linkExtractor .extractLinks(createResponse("multiple-links-different-rels")); assertLinks(Arrays.asList(new Link("alpha", "http://alpha.example.com", "Alpha"), new Link("bravo", "http://bravo.example.com")), links); }
ContentTypeLinkExtractor() { this.linkExtractors.put(MediaType.APPLICATION_JSON, new AtomLinkExtractor()); this.linkExtractors.put(HalLinkExtractor.HAL_MEDIA_TYPE, new HalLinkExtractor()); }
@Test public void linksInTheWrongFormat() throws IOException { Map<String, List<Link>> links = this.linkExtractor .extractLinks(createResponse("wrong-format")); assertLinks(Collections.<Link>emptyList(), links); }
@Test public void tableCellContentIsEscapedWhenNecessary() throws IOException { new LinksSnippet(new StubLinkExtractor().withLinks(new Link("Foo|Bar", "foo")), Arrays.asList(new LinkDescriptor("Foo|Bar").description("one|two"))) .document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row( escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two"))); }
@Test public void multipleLinksWithSameRels() throws IOException { Map<String, List<Link>> links = this.linkExtractor .extractLinks(createResponse("multiple-links-same-rels")); assertLinks(Arrays.asList( new Link("alpha", "http://alpha.example.com/one", "Alpha one"), new Link("alpha", "http://alpha.example.com/two")), links); }
@Parameters(name = "{1}") public static Collection<Object[]> data() { return Arrays.asList(new Object[] { new HalLinkExtractor(), "hal" }, new Object[] { new AtomLinkExtractor(), "atom" }); }
@Test public void noLinks() throws IOException { Map<String, List<Link>> links = this.linkExtractor .extractLinks(createResponse("no-links")); assertLinks(Collections.<Link>emptyList(), links); }
@Test public void documentedLinks() throws IOException { 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(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`a`", "one") .row("`b`", "two")); }
@Test public void singleLink() throws IOException { Map<String, List<Link>> links = this.linkExtractor .extractLinks(createResponse("single-link")); assertLinks(Arrays.asList(new Link("alpha", "http://alpha.example.com", "Alpha")), links); }
@Test public void linkDescriptionFromTitleInPayload() throws IOException { new LinksSnippet( new StubLinkExtractor().withLinks(new Link("a", "alpha", "Link a"), new Link("b", "bravo", "Link b")), Arrays.asList(new LinkDescriptor("a").description("one"), new LinkDescriptor("b"))).document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`a`", "one") .row("`b`", "Link b")); }
@Test public void allUndocumentedLinksCanBeIgnored() throws IOException { new LinksSnippet( new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")), Arrays.asList(new LinkDescriptor("b").description("Link b")), true) .document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`b`", "Link b")); }
@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(this.operationBuilder.build()); }
@Test public void presentOptionalLink() throws IOException { new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "blah")), Arrays.asList(new LinkDescriptor("foo").description("bar").optional())) .document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`foo`", "bar")); }
@Test public void linkWithNoDescription() throws IOException { this.thrown.expect(SnippetException.class); this.thrown.expectMessage( equalTo("No description was provided for the link with rel 'foo' and no" + " title was available from the link in the payload")); new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")), Arrays.asList(new LinkDescriptor("foo"))) .document(this.operationBuilder.build()); }