/* * 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.MockDataConfiguration; import com.juick.service.MessagesService; import com.juick.service.UserService; import com.juick.test.util.MockUtils; 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.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; 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.List; import java.util.Optional; import java.util.stream.Collectors; 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; import static org.mockito.Mockito.when; /** * Created by vitalyster on 12.01.2017. */ @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration public class WebAppTests { @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.juick.www.controllers") @Import(value = { WwwServletConfiguration.class, WwwAppConfiguration.class, SapeConfiguration.class, MockDataConfiguration.class }) static class Config {} @Inject private WebApplicationContext wac; @Inject private WebApp webApp; private WebClient webClient; @Inject UserService userService; @Inject MessagesService messagesService; @Inject PebbleEngine pebbleEngine; @Before public void setup() { webClient = MockMvcWebClientBuilder.webAppContextSetup(this.wac).build(); webClient.getOptions().setJavaScriptEnabled(false); webClient.getOptions().setCssEnabled(false); } @After public void teardown() { webClient.close(); } @Test public void postWithoutTagsShouldNotHaveAsteriskInTitle() throws Exception { String ugnichName = "ugnich"; String ugnichPassword = "MyPassw0rd!"; String msgText = "Привет, я - Угнич"; String hash = "12345678"; User user = MockUtils.mockUser(1, ugnichName, ugnichPassword); Message msg = MockUtils.mockMessage(1, user, msgText); when(userService.getUIDbyName(ugnichName)) .thenReturn(1); when(userService.getUserByName(ugnichName)) .thenReturn(user); when(userService.getUserByUID(1)) .thenReturn(Optional.of(user)); when(userService.getFullyUserByName(ugnichName)) .thenReturn(user); when(messagesService.getMyFeed(1, 0, false)) .thenReturn(Collections.singletonList(1)); when(messagesService.getMessages(Collections.singletonList(1))) .thenReturn(Collections.singletonList(msg)); when(userService.getUIDbyHash(hash)) .thenReturn(1); when(messagesService.getMessageAuthor(1)).thenReturn(user); when(messagesService.canViewThread(1, 0)).thenReturn(true); when(messagesService.getMessage(1)).thenReturn(msg); HtmlPage threadPage = webClient.getPage("http://localhost:8080/ugnich/1"); assertThat(threadPage.getTitleText(), equalTo("ugnich:")); } @Test public void bannedUserBlogandPostShouldReturn404() throws IOException { String userName = "isilmine"; String userPassword = "secret"; String msgText = "автор этого поста был забанен"; String hash = "12345678"; User user = MockUtils.mockUser(2, userName, userPassword); user.setBanned(true); Message msg = MockUtils.mockMessage(2, user, msgText); when(userService.getUIDbyName(userName)) .thenReturn(2); when(userService.getUserByName(userName)) .thenReturn(user); when(userService.getUserByUID(2)) .thenReturn(Optional.of(user)); when(userService.getFullyUserByName(userName)) .thenReturn(user); when(messagesService.getMyFeed(2, 0, false)) .thenReturn(Collections.singletonList(2)); when(messagesService.getMessages(Collections.singletonList(2))) .thenReturn(Collections.singletonList(msg)); when(userService.getUIDbyHash(hash)) .thenReturn(1); when(messagesService.getMessageAuthor(2)).thenReturn(user); when(messagesService.canViewThread(2, 0)).thenReturn(true); when(messagesService.getMessage(2)).thenReturn(msg); webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); Page blogPage = webClient.getPage("http://localhost:8080/isilmine"); Page threadPage = webClient.getPage("http://localhost:8080/isilmine/2"); assertThat(blogPage.getWebResponse().getStatusCode(), equalTo(404)); assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(404)); } @Test public void repliesTree() throws IOException { User ugnich = MockUtils.mockUser(1, "ugnich", "secret"); User freefd = MockUtils.mockUser(3, "freefd", "secret"); Message hello = MockUtils.mockMessage(1, ugnich, null); List replies = IntStream.range(1, 15).mapToObj(i -> MockUtils.mockReply(hello.getMid(), i, freefd, i-1, null )).collect(Collectors.toList()); when(userService.getUIDbyName("ugnich")).thenReturn(1); when(userService.getUIDbyName("freefd")).thenReturn(3); when(userService.getUserByName("ugnich")).thenReturn(ugnich); when(userService.getUserByName("freefd")).thenReturn(freefd); when(messagesService.canViewThread(1, 0)).thenReturn(true); when(messagesService.getMessage(1)).thenReturn(hello); when(messagesService.getReplies(1)).thenReturn(replies); HtmlPage threadPage = webClient.getPage("http://localhost:8080/ugnich/1"); 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 { String ugnichName = "ugnich"; String ugnichPassword = "MyPassw0rd!"; String msgText = "Привет, я - Угнич"; String hash = "12345678"; User user = MockUtils.mockUser(1, ugnichName, ugnichPassword); Message msg = MockUtils.mockMessage(1, user, msgText); when(userService.getUIDbyName(ugnichName)) .thenReturn(1); when(userService.getUserByName(ugnichName)) .thenReturn(user); when(userService.getUserByUID(1)) .thenReturn(Optional.of(user)); when(userService.getFullyUserByName(ugnichName)) .thenReturn(user); when(messagesService.getMyFeed(1, 0, false)) .thenReturn(Collections.singletonList(1)); when(messagesService.getMessages(Collections.singletonList(1))) .thenReturn(Collections.singletonList(msg)); when(userService.getUIDbyHash(hash)) .thenReturn(1); when(messagesService.getMessageAuthor(1)).thenReturn(user); when(messagesService.canViewThread(1, 0)).thenReturn(true); when(messagesService.getMessage(1)).thenReturn(msg); assertThat(fetchMeta("http://localhost:8080/ugnich/1", "twitter:card") .getAttribute("content"), equalTo("summary")); msg.setAttachmentType("png"); assertThat(fetchMeta("http://localhost:8080/ugnich/1", "twitter:card") .getAttribute("content"), equalTo("summary_large_image")); assertThat(fetchMeta("http://localhost:8080/ugnich/1", "og:description") .getAttribute("content"), startsWith(StringEscapeUtils.escapeHtml4(MessageUtils.getMessageHashTags(msg)))); } }