/* * Copyright (C) 2008-2017, Juick * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package com.juick.www; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.css.StyleElement; import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.juick.Message; import com.juick.Tag; import com.juick.User; import com.juick.configuration.RepositoryConfiguration; import com.juick.service.ImagesService; import com.juick.service.MessagesService; import com.juick.service.MockImagesService; import com.juick.service.UserService; import com.juick.util.MessageUtils; import com.juick.www.configuration.SapeConfiguration; import com.juick.www.configuration.WwwAppConfiguration; import com.juick.www.configuration.WwwServletConfiguration; import com.mitchellbosecke.pebble.PebbleEngine; import com.mitchellbosecke.pebble.error.PebbleException; import com.mitchellbosecke.pebble.template.PebbleTemplate; import org.apache.commons.text.StringEscapeUtils; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import javax.inject.Inject; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Collections; import java.util.stream.IntStream; import java.util.stream.StreamSupport; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.startsWith; /** * Created by vitalyster on 12.01.2017. */ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = { WwwServletConfiguration.class, WwwAppConfiguration.class, SapeConfiguration.class, RepositoryConfiguration.class }) public class WebAppTests { @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.juick.www.controllers") static class Config { @Bean public ImagesService imagesService() { return new MockImagesService(); } } @Inject private WebApplicationContext wac; @Inject private WebApp webApp; private static WebClient webClient; @Inject UserService userService; @Inject MessagesService messagesService; @Inject JdbcTemplate jdbcTemplate; @Inject PebbleEngine pebbleEngine; private static User ugnich, freefd; private static String ugnichName, ugnichPassword, freefdName, freefdPassword; private static boolean isSetUp = false; @Before public void setup() { if (!isSetUp) { webClient = MockMvcWebClientBuilder.webAppContextSetup(this.wac).build(); webClient.getOptions().setJavaScriptEnabled(false); webClient.getOptions().setCssEnabled(false); webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); ugnichName = "ugnich"; ugnichPassword = "MyPassw0rd!"; freefdName = "freefd"; freefdPassword = "MyPassw0rd!"; int ugnichId = userService.createUser(ugnichName, ugnichPassword); ugnich = userService.getUserByUID(ugnichId).orElseThrow(IllegalStateException::new); int freefdId = userService.createUser(freefdName, freefdPassword); freefd = userService.getUserByUID(freefdId).orElseThrow(IllegalStateException::new); isSetUp = true; } } @Test public void postWithoutTagsShouldNotHaveAsteriskInTitle() throws Exception { String msgText = "Привет, я - Угнич"; int mid = messagesService.createMessage(ugnich.getUid(), msgText, null, null); HtmlPage threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid)); assertThat(threadPage.getTitleText(), equalTo("ugnich:")); } @Test public void bannedUserBlogandPostShouldReturn404() throws IOException { String userName = "isilmine"; String userPassword = "secret"; String msgText = "автор этого поста был забанен"; String hash = "12345678"; User isilmine = userService.getUserByUID(userService.createUser(userName, userPassword)).orElseThrow(IllegalStateException::new); int mid = messagesService.createMessage(isilmine.getUid(), msgText, null, null); jdbcTemplate.update("UPDATE users SET banned=1 WHERE id=?", isilmine.getUid()); Page blogPage = webClient.getPage("http://localhost:8080/isilmine"); Page threadPage = webClient.getPage(String.format("http://localhost:8080/isilmine/%d", mid)); assertThat(blogPage.getWebResponse().getStatusCode(), equalTo(404)); assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(404)); } @Test public void repliesTree() throws IOException { int mid = messagesService.createMessage(ugnich.getUid(), "hello", null, null); IntStream.range(1, 15).forEach(i -> messagesService.createReply(mid, i-1, freefd.getUid(), String.valueOf(i-1), null )); HtmlPage threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid)); assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(200)); Long visibleItems = StreamSupport.stream(threadPage.getHtmlElementById("replies") .getChildElements().spliterator(), false).filter(e -> { StyleElement display = e.getStyleElement("display"); return display == null || !display.getValue().equals("none"); }).count(); assertThat(visibleItems, equalTo(1L)); } @Test public void correctTagsEscaping() throws PebbleException, IOException { PebbleTemplate template = pebbleEngine.getTemplate("views/test"); Writer writer = new StringWriter(); template.evaluate(writer, Collections.singletonMap("tagsList", Collections.singletonList(StringEscapeUtils.escapeHtml4(new Tag(">_<").getName())))); String output = writer.toString().trim(); assertThat(output, equalTo(">_<")); } public DomElement fetchMeta(String url, String name) throws IOException { HtmlPage page = webClient.getPage(url); DomElement emptyMeta = new DomElement("", "meta", null, null); return page.getElementsByTagName("meta").stream() .filter(t -> t.getAttribute("name").equals(name)).findFirst().orElse(emptyMeta); } @Test public void testTwitterCards() throws Exception { int mid = messagesService.createMessage(ugnich.getUid(), "without image", null, null); assertThat(fetchMeta(String.format("http://localhost:8080/ugnich/%d", mid), "twitter:card") .getAttribute("content"), equalTo("summary")); int mid2 = messagesService.createMessage(ugnich.getUid(), "with image", "png", null); Message message = messagesService.getMessage(mid2); assertThat(fetchMeta(String.format("http://localhost:8080/ugnich/%d", mid2), "twitter:card") .getAttribute("content"), equalTo("summary_large_image")); assertThat(fetchMeta(String.format("http://localhost:8080/ugnich/%d", mid2), "og:description") .getAttribute("content"), startsWith(StringEscapeUtils.escapeHtml4(MessageUtils.getMessageHashTags(message)))); } }