package sagan.blog.support; import sagan.blog.Post; import sagan.blog.PostBuilder; import saganx.AbstractIntegrationTests; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.MvcResult; import static java.util.stream.Collectors.toList; import static org.hamcrest.Matchers.*; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.junit.Assert.assertThat; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; public class BlogIndexTests extends AbstractIntegrationTests { @Autowired private PostRepository postRepository; @Test public void showsBlogIndex() throws Exception { MvcResult result = mockMvc.perform(get("/blog")).andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("text/html")).andReturn(); Document document = Jsoup.parse(result.getResponse().getContentAsString()); assertThat(document.select("ul.nav li.active").text(), equalTo("Blog")); assertThat(document.select(".secondary-nav .blog-category.active").text(), equalTo("All Posts")); assertThat(document.select(".content--title.blog-category.active").text(), equalTo("The Spring Blog")); assertThat( document.head() .getElementsByAttributeValue("type", "application/atom+xml") .get(0).attr("href"), equalTo("/blog.atom")); } @Test public void given1Post_blogIndexShowsPostSummary() throws Exception { Post post = createSinglePost(); MvcResult response = mockMvc.perform(get("/blog")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("text/html")).andReturn(); Document html = Jsoup.parse(response.getResponse().getContentAsString()); assertThat(html.select(".blog--title a").first().text(), is(post.getTitle())); } @Test public void givenPostContentThatIsEqualToSummary_blogIndexShouldNotShow_ReadMore() throws Exception { String summary = "A blog post string that is longish."; String content = summary; Post post = new PostBuilder().renderedContent(content).renderedSummary(summary).build(); postRepository.save(post); MvcResult result = mockMvc.perform(get("/blog")).andReturn(); String response = result.getResponse().getContentAsString(); assertThat(response, not(containsString("Read more"))); } @Test public void givenPostContentThatIsLongerThanSummary_blogIndexShouldShow_ReadMore() throws Exception { String summary = "A blog post string that is longish."; String content = ""; for (int i = 0; i < 50; i++) { content = content + summary; } Post post = new PostBuilder().renderedContent(content).renderedSummary(summary).build(); postRepository.save(post); MvcResult result = mockMvc.perform(get("/blog")).andReturn(); String response = result.getResponse().getContentAsString(); assertThat(response, containsString("Read more")); } private Post createSinglePost() { Post post = new PostBuilder().title("This week in Spring - June 3, 2013") .rawContent("Raw content").renderedContent("Html content") .renderedSummary("Html summary").build(); postRepository.save(post); return post; } @Test public void givenManyPosts_blogIndexShowsLatest10PostSummaries() throws Exception { createManyPostsInNovember(11); MvcResult response = mockMvc.perform(get("/blog")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith("text/html")).andReturn(); Document html = Jsoup.parse(response.getResponse().getContentAsString()); assertThat(numberOfBlogPosts(html), is(10)); assertThat(html.select(".blog--container .date").first().text(), is("November 11, 2012")); assertThat(html.select(".blog--container .date").last().text(), is("November 2, 2012")); } private int numberOfBlogPosts(Document html) { return html.select(".blog--title").size(); } private void createManyPostsInNovember(int numPostsToCreate) { Calendar calendar = Calendar.getInstance(); List<Post> posts = new ArrayList<>(); for (int postNumber = 1; postNumber <= numPostsToCreate; postNumber++) { calendar.set(2012, 10, postNumber); Post post = new PostBuilder() .title("This week in Spring - November " + postNumber + ", 2012") .rawContent("Raw content").renderedContent("Html content") .renderedSummary("Html summary").createdAt(calendar.getTime()) .publishAt(calendar.getTime()).build(); posts.add(post); } postRepository.save(posts); } @Test public void givenPostsCreatedOutOfOrder_blogIndexShowsPostsOrderedByPublishedDate() throws Exception { createPublishedPost("Happy New Year", "2013-01-01 00:00"); createPublishedPost("Back to Work", "2013-01-03 00:00"); createPublishedPost("Off to the Sales", "2013-01-02 00:00"); MvcResult response = mockMvc.perform(get("/blog")) .andExpect(status().isOk()) .andReturn(); Document html = Jsoup.parse(response.getResponse().getContentAsString()); List<String> titles = html.select(".blog--title").stream() .map(Element::text).collect(toList()); assertThat(titles, contains("Back to Work", "Off to the Sales", "Happy New Year")); } private Post createPublishedPost(String title, String publishAt) throws ParseException { Post post = PostBuilder.post().title(title).publishAt(publishAt).build(); return postRepository.save(post); } @Test public void given1PageOfResults_blogIndexDoesNotShowPaginationControl() throws Exception { createManyPostsInNovember(1); MvcResult response = mockMvc.perform(get("/blog")).andReturn(); Document html = Jsoup.parse(response.getResponse().getContentAsString()); assertThat(html.select("#pagination_control").first(), is(nullValue())); } @Test public void givenManyPosts_blogIndexShowsPaginationControl() throws Exception { createManyPostsInNovember(21); MvcResult response = mockMvc.perform(get("/blog?page=2")).andReturn(); Document html = Jsoup.parse(response.getResponse().getContentAsString()); Element previousLink = html.select("#pagination_control a.previous").first(); assertThat("No previous pagination link found", previousLink, is(notNullValue())); String previousHref = previousLink.attributes().get("href"); assertThat(previousHref, is("/blog?page=1")); Element nextLink = html.select("#pagination_control a.next").first(); assertThat("No next pagination link found", nextLink, is(notNullValue())); String nextHref = nextLink.attributes().get("href"); assertThat(nextHref, is("/blog?page=3")); } }