/** * Returns a new {@code LinksSnippet} configured with this snippet's link extractor * and attributes, and its descriptors combined with the given * {@code additionalDescriptors}. * @param additionalDescriptors the additional descriptors * @return the new snippet */ public final LinksSnippet and(LinkDescriptor... additionalDescriptors) { return and(Arrays.asList(additionalDescriptors)); }
/** * Returns a new {@code Snippet} that will document the links in the API operation's * response. Links will be extracted from the response using the given * {@code linkExtractor} 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 linkExtractor used to extract the links from the response * @param descriptors the descriptions of the response's links * @return the snippet that will document the links */ public static LinksSnippet relaxedLinks(LinkExtractor linkExtractor, List<LinkDescriptor> descriptors) { return new LinksSnippet(linkExtractor, descriptors, true); }
private List<Map<String, Object>> createLinksModel(Map<String, List<Link>> links) { List<Map<String, Object>> model = new ArrayList<>(); for (Entry<String, LinkDescriptor> entry : this.descriptorsByRel.entrySet()) { LinkDescriptor descriptor = entry.getValue(); if (!descriptor.isIgnored()) { if (descriptor.getDescription() == null) { descriptor = createDescriptor( getDescriptionFromLinkTitle(links, descriptor.getRel()), descriptor); } model.add(createModelForDescriptor(descriptor)); } } return model; }
/** * Returns a new {@code LinksSnippet} configured with this snippet's link extractor * and attributes, and its descriptors combined with the given * {@code additionalDescriptors}. * @param additionalDescriptors the additional descriptors * @return the new snippet */ public final LinksSnippet and(List<LinkDescriptor> additionalDescriptors) { List<LinkDescriptor> combinedDescriptors = new ArrayList<>( this.descriptorsByRel.values()); combinedDescriptors.addAll(additionalDescriptors); return new LinksSnippet(this.linkExtractor, combinedDescriptors, getAttributes()); }
@Override protected Map<String, Object> createModel(Operation operation) { OperationResponse response = operation.getResponse(); Map<String, List<Link>> links; try { links = this.linkExtractor.extractLinks(response); validate(links); } catch (IOException ex) { throw new ModelCreationException(ex); } Map<String, Object> model = new HashMap<>(); model.put("links", createLinksModel(links)); return model; }
@Test public void undocumentedLink() throws IOException { this.thrown.expect(SnippetException.class); this.thrown.expectMessage(equalTo( "Links with the following relations were not" + " documented: [foo]")); new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")), Collections.<LinkDescriptor>emptyList()) .document(this.operationBuilder.build()); }
@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")); }
@Test public void missingLink() throws IOException { this.thrown.expect(SnippetException.class); this.thrown.expectMessage(equalTo("Links with the following relations were not" + " found in the response: [foo]")); new LinksSnippet(new StubLinkExtractor(), Arrays.asList(new LinkDescriptor("foo").description("bar"))) .document(this.operationBuilder.build()); }
@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()); }
public static LinksSnippet links(LinkDescriptor... descriptors) { return HypermediaDocumentation.links(linkWithRel("self").ignored().optional(), linkWithRel("curies").ignored()).and(descriptors); } // end::ignore-links[]
/** * Returns a new {@code Snippet} that will document the links in the API operation's * response. The given {@code attributes} will be available during snippet generation. * Links will be extracted from the response using the given {@code linkExtractor} 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 attributes the attributes * @param linkExtractor used to extract the links from the response * @param descriptors the descriptions of the response's links * @return the snippet that will document the links */ public static LinksSnippet relaxedLinks(LinkExtractor linkExtractor, Map<String, Object> attributes, List<LinkDescriptor> descriptors) { return new LinksSnippet(linkExtractor, descriptors, attributes, true); }
@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()); }
public void documentation() throws Exception { // tag::use[] RestAssured.given(this.spec) .accept("application/json") .filter(document("example", this.pagingLinks.and( // <1> linkWithRel("alpha").description("Link to the alpha resource"), linkWithRel("bravo").description("Link to the bravo resource")))) .get("/").then().assertThat().statusCode(is(200)); // end::use[] }
/** * Returns a new {@code Snippet} that will document the links in the API operation's * response. Links will be extracted from the response using the given * {@code linkExtractor} and will be documented using the given {@code descriptors}. * <p> * If a link is present in the response, but is not documented by one of the * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. * <p> * If you do not want to document a link, a link descriptor can be marked as * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the * generated snippet while avoiding the failure described above. * <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 linkExtractor used to extract the links from the response * @param descriptors the descriptions of the response's links * @return the snippet that will document the links */ public static LinksSnippet links(LinkExtractor linkExtractor, List<LinkDescriptor> descriptors) { return new LinksSnippet(linkExtractor, descriptors); }
@Test public void missingOptionalLink() throws IOException { new LinksSnippet(new StubLinkExtractor(), Arrays.asList(new LinkDescriptor("foo").description("bar").optional())) .document(this.operationBuilder.build()); assertThat(this.generatedSnippets.links()) .is(tableWithHeader("Relation", "Description").row("`foo`", "bar")); }
public void documentation() throws Exception { // tag::use[] this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(document("example", this.pagingLinks.and( // <1> linkWithRel("alpha").description("Link to the alpha resource"), linkWithRel("bravo").description("Link to the bravo resource")))); // end::use[] }
/** * Returns a new {@code Snippet} that will document the links in the API operation's * response. The given {@code attributes} will be available during snippet generation. * Links will be extracted from the response using the given {@code linkExtractor} and * will be documented using the given {@code descriptors}. * <p> * If a link is present in the response, but is not documented by one of the * descriptors, a failure will occur when the snippet is invoked. Similarly, if a link * is documented, is not marked as optional, and is not present in the response, a * failure will also occur. * <p> * If you do not want to document a link, a link descriptor can be marked as * {@link LinkDescriptor#ignored}. This will prevent it from appearing in the * generated snippet while avoiding the failure described above. * <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 attributes the attributes * @param linkExtractor used to extract the links from the response * @param descriptors the descriptions of the response's links * @return the snippet that will document the links */ public static LinksSnippet links(LinkExtractor linkExtractor, Map<String, Object> attributes, List<LinkDescriptor> descriptors) { return new LinksSnippet(linkExtractor, descriptors, attributes); }
@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")); }
public void documentation() throws Exception { // tag::use[] this.webTestClient.get().uri("/").accept(MediaType.APPLICATION_JSON).exchange() .expectStatus().isOk().expectBody() .consumeWith(document("example", this.pagingLinks.and( // <1> linkWithRel("alpha").description("Link to the alpha resource"), linkWithRel("bravo").description("Link to the bravo resource")))); // end::use[] }
/** * 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); }