aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/test/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/test/java/com')
-rw-r--r--juick-server/src/test/java/com/juick/server/tests/ServerTests.java110
-rw-r--r--juick-server/src/test/java/com/juick/server/tests/WebAppTests.java466
2 files changed, 521 insertions, 55 deletions
diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
index 1931f13b7..fc18dbf5e 100644
--- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
+++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java
@@ -368,19 +368,19 @@ public class ServerTests {
@Test
public void testAllUnAuthorized() throws Exception {
- mockMvc.perform(get("/"))
+ mockMvc.perform(get("/api/"))
.andExpect(status().isMovedPermanently());
- mockMvc.perform(get("/auth"))
+ mockMvc.perform(get("/api/auth"))
.andExpect(status().isUnauthorized());
- mockMvc.perform(get("/home"))
+ mockMvc.perform(get("/api/home"))
.andExpect(status().isUnauthorized());
- mockMvc.perform(get("/messages/recommended"))
+ mockMvc.perform(get("/api/messages/recommended"))
.andExpect(status().isUnauthorized());
- mockMvc.perform(get("/messages/set_privacy"))
+ mockMvc.perform(get("/api/messages/set_privacy"))
.andExpect(status().isUnauthorized());
}
@@ -392,7 +392,7 @@ public class ServerTests {
Message msg = messagesService.getMessage(mid);
tagService.createTag("тест");
mockMvc.perform(
- get("/home")
+ get("/api/home")
.with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
@@ -411,12 +411,12 @@ public class ServerTests {
public void homeTestWithMessagesAndRememberMe() throws Exception {
String ugnichHash = userService.getHashByUID(ugnich.getUid());
mockMvc.perform(
- get("/home")
+ get("/api/home")
.with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk())
.andReturn();
- mockMvc.perform(get("/home")
+ mockMvc.perform(get("/api/home")
.param("hash", ugnichHash))
.andExpect(status().isOk());
}
@@ -424,7 +424,7 @@ public class ServerTests {
@Test
public void homeTestWithMessagesAndSimpleCors() throws Exception {
mockMvc.perform(
- get("/home")
+ get("/api/home")
.with(httpBasic(ugnichName, ugnichPassword))
.header("Origin", "http://api.example.net"))
.andExpect(status().isOk())
@@ -434,7 +434,7 @@ public class ServerTests {
@Test
public void homeTestWithPreflightCors() throws Exception {
mockMvc.perform(
- options("/home")
+ options("/api/home")
.with(httpBasic(ugnichName, ugnichPassword))
.header("Origin", "http://api.example.net")
.header("Access-Control-Request-Method", "POST")
@@ -449,10 +449,10 @@ public class ServerTests {
public void anonymousApis() throws Exception {
- mockMvc.perform(get("/messages"))
+ mockMvc.perform(get("/api/messages"))
.andExpect(status().isOk());
- mockMvc.perform(get("/users")
+ mockMvc.perform(get("/api/users")
.param("uname", "ugnich")
.param("uname", "freefd"))
.andExpect(status().isOk())
@@ -473,7 +473,7 @@ public class ServerTests {
messagesService.likeMessage(mid, freefdId, 2 );
messagesService.likeMessage(mid, freefdId, 3 );
- mockMvc.perform(get("/messages?"+ "hash=" + userIdHash))
+ mockMvc.perform(get("/api/messages?"+ "hash=" + userIdHash))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
@@ -482,7 +482,7 @@ public class ServerTests {
.andExpect((jsonPath("$[0].reactions[?(@.id == 2)].count",
is(Collections.singletonList(2)))));
- mockMvc.perform(get("/reactions?hash=" + userIdHash))
+ mockMvc.perform(get("/api/reactions?hash=" + userIdHash))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.length()", is(7)));
@@ -494,14 +494,14 @@ public class ServerTests {
Tag yo = tagService.getTag("yo", true);
messagesService.createMessage(ugnich.getUid(), "text", null, Arrays.asList(yo, weather));
messagesService.createMessage(freefd.getUid(), "text2", null, Collections.singletonList(yo));
- MvcResult result = mockMvc.perform(get("/tags"))
+ MvcResult result = mockMvc.perform(get("/api/tags"))
.andExpect(status().isOk())
.andReturn();
List<TagStats> tagsFromApi = jsonMapper.readValue(result.getResponse().getContentAsString(),
new TypeReference<List<TagStats>>(){});
TagStats yoStats = tagsFromApi.stream().filter(t -> t.getTag().getName().equals("yo")).findFirst().get();
assertThat(yoStats.getUsageCount(), is(2));
- MvcResult result2 = mockMvc.perform(get("/tags")
+ MvcResult result2 = mockMvc.perform(get("/api/tags")
.param("user_id", String.valueOf(ugnich.getUid())))
.andExpect(status().isOk())
.andReturn();
@@ -513,40 +513,40 @@ public class ServerTests {
@Test
public void postWithReferer() throws Exception {
- mockMvc.perform(post("/post")
+ mockMvc.perform(post("/api/post")
.param("body", "yo")
.with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk());
}
@Test
public void threadWithEphemeralNumberShouldReturn404() throws Exception {
- mockMvc.perform(get("/thread").param("mid", "999999999")
+ mockMvc.perform(get("/api/thread").param("mid", "999999999")
.with(httpBasic(ugnichName, ugnichPassword))).andExpect(status().is4xxClientError());
}
@Test
public void performRequestsWithIssuedToken() throws Exception {
String ugnichHash = userService.getHashByUID(ugnich.getUid());
- mockMvc.perform(get("/home")).andExpect(status().isUnauthorized());
- mockMvc.perform(get("/auth"))
+ mockMvc.perform(get("/api/home")).andExpect(status().isUnauthorized());
+ mockMvc.perform(get("/api/auth"))
.andExpect(status().isUnauthorized());
- mockMvc.perform(get("/auth").with(httpBasic(ugnichName, "wrongpassword")))
+ mockMvc.perform(get("/api/auth").with(httpBasic(ugnichName, "wrongpassword")))
.andExpect(status().isUnauthorized());
- MvcResult result = mockMvc.perform(get("/auth").with(httpBasic(ugnichName, ugnichPassword)))
+ MvcResult result = mockMvc.perform(get("/api/auth").with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk())
.andReturn();
String authHash = result.getResponse().getContentAsString();
assertThat(authHash, equalTo(ugnichHash));
- mockMvc.perform(get("/home").param("hash", ugnichHash)).andExpect(status().isOk());
+ mockMvc.perform(get("/api/home").param("hash", ugnichHash)).andExpect(status().isOk());
}
@Test
public void registerForNotificationsTests() throws Exception {
String token = "123456";
ExternalToken registration = new ExternalToken(null, "apns", token, null);
- mockMvc.perform(put("/notifications").with(httpBasic(ugnichName, ugnichPassword))
+ mockMvc.perform(put("/api/notifications").with(httpBasic(ugnichName, ugnichPassword))
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(jsonMapper.writeValueAsBytes(Collections.singletonList(registration))))
.andExpect(status().isOk());
- MvcResult result = mockMvc.perform(get("/notifications")
+ MvcResult result = mockMvc.perform(get("/api/notifications")
.param("uid", String.valueOf(ugnich.getUid()))
.with(httpBasic(juickName, juickPassword)))
.andExpect(status().isOk())
@@ -565,10 +565,10 @@ public class ServerTests {
@Test
public void notificationsTokensTest() throws Exception {
List<ExternalToken> tokens = Collections.singletonList(new ExternalToken(null, "gcm", "123456", null));
- mockMvc.perform(delete("/notifications").with(httpBasic(ugnichName, ugnichPassword))
+ mockMvc.perform(delete("/api/notifications").with(httpBasic(ugnichName, ugnichPassword))
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(jsonMapper.writeValueAsBytes(tokens))).andExpect(status().isForbidden());
- mockMvc.perform(delete("/notifications").with(httpBasic(juickName, juickPassword))
+ mockMvc.perform(delete("/api/notifications").with(httpBasic(juickName, juickPassword))
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(jsonMapper.writeValueAsBytes(tokens))).andExpect(status().isOk());
}
@@ -576,9 +576,9 @@ public class ServerTests {
public void notificationsSettingsAllowedOnlyForServiceUser() throws Exception {
CommandResult result = commandsManager.processCommand(ugnich, "yo", emptyUri);
String stringValueOfMid = String.valueOf(result.getNewMessage().get().getMid());
- mockMvc.perform(get("/notifications").with(httpBasic(juickName, juickPassword))
+ mockMvc.perform(get("/api/notifications").with(httpBasic(juickName, juickPassword))
.param("mid", stringValueOfMid).param("uid", String.valueOf(ugnich.getUid()))).andExpect(status().isOk());
- mockMvc.perform(get("/notifications")
+ mockMvc.perform(get("/api/notifications")
.param("mid", stringValueOfMid).param("uid", String.valueOf(ugnich.getUid()))).andExpect(status().isUnauthorized());
}
@Test
@@ -858,7 +858,7 @@ public class ServerTests {
"<div dir=\"ltr\">s2313334</div>\n" +
"\n" +
"--001a11454886e42be5056786ca70--";
- mockMvc.perform(post("/mail").with(httpBasic(juickName, juickPassword)).content(mail))
+ mockMvc.perform(post("/api/mail").with(httpBasic(juickName, juickPassword)).content(mail))
.andExpect(status().isOk());
}
@@ -869,14 +869,14 @@ public class ServerTests {
String freefdHash = userService.getHashByUID(freefd.getUid());
int freefdMid = messagesService.createMessage(freefd.getUid(), "to be not liked", null, null);
- mockMvc.perform(post("/like?mid=" + mid + "&hash=" + freefdHash))
+ mockMvc.perform(post("/api/like?mid=" + mid + "&hash=" + freefdHash))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status", is("Message is added to your recommendations")));
- mockMvc.perform(get("/thread?mid=" + mid + "&hash=" + freefdHash))
+ mockMvc.perform(get("/api/thread?mid=" + mid + "&hash=" + freefdHash))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].recommendations.length()", is(1)))
.andExpect(jsonPath("$[0].recommendations[0]", is(freefdName)));
- mockMvc.perform(post("/like?mid=" + freefdMid + "&hash=" + freefdHash))
+ mockMvc.perform(post("/api/like?mid=" + freefdMid + "&hash=" + freefdHash))
.andExpect(status().isForbidden());
}
@@ -886,7 +886,7 @@ public class ServerTests {
String freefdHash = userService.getHashByUID(freefd.getUid());
int mid1 = messagesService.createMessage(user_id, "yo", null, new ArrayList<>());
- mockMvc.perform(post("/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=2"))
+ mockMvc.perform(post("/api/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=2"))
.andExpect(status().isOk());
Message msg4 = messagesService.getMessage(mid1);
@@ -894,9 +894,9 @@ public class ServerTests {
assertThat(messagesService.getMessages(AnonymousUser.INSTANCE, Collections.singletonList(mid1)).get(0).getLikes(), is(0));
Assert.assertEquals(1, msg4.getReactions().stream().filter(r -> r.getId() == 2)
.findFirst().orElseThrow(IllegalStateException::new).getCount());
- mockMvc.perform(post("/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=1"))
+ mockMvc.perform(post("/api/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=1"))
.andExpect(status().isOk());
- mockMvc.perform(post("/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=1"))
+ mockMvc.perform(post("/api/react?mid=" + mid1 + "&hash=" + freefdHash+ "&reactionId=1"))
.andExpect(status().isOk());
assertThat(messagesService.getMessage(mid1).getLikes(), is(1));
}
@@ -920,7 +920,7 @@ public class ServerTests {
assertThat(lastRead.apply(ugnich, mid), is(1));
String ugnichHash = userService.getHashByUID(ugnich.getUid());
int freefdrid = messagesService.createReply(mid, 0, freefd, "again", null);
- mockMvc.perform(get(String.format("/thread/mark_read/%d-%d.gif?hash=%s", mid, freefdrid, ugnichHash)))
+ mockMvc.perform(get(String.format("/api/thread/mark_read/%d-%d.gif?hash=%s", mid, freefdrid, ugnichHash)))
.andExpect(status().isOk())
.andExpect(content().bytes(IOUtils.toByteArray(
Objects.requireNonNull(getClass().getClassLoader().getResource("Transparent.gif")))));
@@ -934,7 +934,7 @@ public class ServerTests {
privacyQueriesService.blacklistUser(ugnich, freefd);
newfreefdrid = messagesService.createReply(mid, 0, freefd, "after ban", null);
assertThat(lastRead.apply(ugnich, mid), lessThan(newfreefdrid));
- mockMvc.perform(get(String.format("/thread?mid=%d&hash=%s", mid, ugnichHash)))
+ mockMvc.perform(get(String.format("/api/thread?mid=%d&hash=%s", mid, ugnichHash)))
.andExpect(status().isOk());
assertThat(lastRead.apply(ugnich, mid), is(newfreefdrid));
}
@@ -1035,13 +1035,13 @@ public class ServerTests {
map.add("body", "yo");
map.add("hash", userService.getHashByUID(ugnich.getUid()));
ResponseEntity<CommandResult> result = restTemplate.postForEntity(
- "/post",
+ "/api/post",
request, CommandResult.class);
assertThat(result.getStatusCode(), is(HttpStatus.OK));
}
@Test
public void emptyAuthenticatedPostShouldThrowBadRequest() throws Exception {
- mockMvc.perform(post("/post")
+ mockMvc.perform(post("/api/post")
.with(httpBasic(juickName, juickPassword)))
.andExpect(status().isBadRequest());
}
@@ -1061,7 +1061,7 @@ public class ServerTests {
commandsManager.processCommand(ugnich, "S @freefd", emptyUri);
assertThat(userService.getUserReaders(ugnich.getUid()).size(), is(1));
String hash = userService.getHashByUID(ugnich.getUid());
- mockMvc.perform(get("/me")
+ mockMvc.perform(get("/api/me")
.with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(jsonPath("$.hash", is(hash)))
.andExpect(jsonPath("$.readers.length()", is(1)))
@@ -1148,7 +1148,7 @@ public class ServerTests {
}
@Test
public void messageEditingSpec() throws Exception {
- MvcResult result = mockMvc.perform(post("/post").with(httpBasic(ugnichName, ugnichPassword))
+ MvcResult result = mockMvc.perform(post("/api/post").with(httpBasic(ugnichName, ugnichPassword))
.param("body", "YO")).andExpect(status().is2xxSuccessful()).andReturn();
Message original = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class)
.getNewMessage().get();
@@ -1156,17 +1156,17 @@ public class ServerTests {
assertThat(original.getUpdatedAt(), equalTo(original.getTimestamp()));
// to have updated_at greater than ts
Thread.sleep(1000);
- result = mockMvc.perform(post("/update").with(httpBasic(ugnichName, ugnichPassword))
+ result = mockMvc.perform(post("/api/update").with(httpBasic(ugnichName, ugnichPassword))
.param("mid", String.valueOf(original.getMid()))
.param("body", "PEOPLE")).andExpect(status().is2xxSuccessful()).andReturn();
Message edited = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class)
.getNewMessage().get();
assertThat(edited.getText(), equalTo("PEOPLE"));
assertThat(edited.getUpdatedAt(), greaterThan(edited.getTimestamp()));
- mockMvc.perform(post("/update").with(httpBasic(freefdName, freefdPassword))
+ mockMvc.perform(post("/api/update").with(httpBasic(freefdName, freefdPassword))
.param("mid", String.valueOf(original.getMid()))
.param("body", "PEOPLE")).andExpect(status().is(403));
- result = mockMvc.perform(post("/comment").with(httpBasic(freefdName, freefdPassword))
+ result = mockMvc.perform(post("/api/comment").with(httpBasic(freefdName, freefdPassword))
.param("mid", String.valueOf(original.getMid()))
.param("body", "HEY")).andExpect(status().is2xxSuccessful()).andReturn();
Message comment = jsonMapper.readValue(result.getResponse().getContentAsString(), Message.class);
@@ -1174,7 +1174,7 @@ public class ServerTests {
assertThat(comment.getUpdatedAt(), is(comment.getTimestamp()));
// to have updated_at greater than ts
Thread.sleep(1000);
- result = mockMvc.perform(post("/update").with(httpBasic(freefdName, freefdPassword))
+ result = mockMvc.perform(post("/api/update").with(httpBasic(freefdName, freefdPassword))
.param("mid", String.valueOf(comment.getMid()))
.param("rid", String.valueOf(comment.getRid()))
.param("body", "HEY, JOE")).andExpect(status().is2xxSuccessful()).andReturn();
@@ -1223,7 +1223,7 @@ public class ServerTests {
public void xmppStatusApi() throws Exception {
Supplier<XMPPStatus> getStatus = () -> {
try {
- MvcResult result = mockMvc.perform(get("/xmpp/status").with(httpBasic(ugnichName, ugnichPassword)))
+ MvcResult result = mockMvc.perform(get("/api/xmpp-status").with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk()).andReturn();
return jsonMapper.readValue(result.getResponse().getContentAsString(), XMPPStatus.class);
} catch (Exception e) {
@@ -1273,16 +1273,16 @@ public class ServerTests {
User isilmine = userService.getUserByUID(userService.createUser(userName, userPassword)).orElseThrow(IllegalStateException::new);
int mid = messagesService.createMessage(isilmine.getUid(), msgText, null, null);
- mockMvc.perform(get(String.format("/thread?mid=%d", mid)).with(httpBasic(ugnichName, ugnichPassword)))
+ mockMvc.perform(get(String.format("/api/thread?mid=%d", mid)).with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk());
jdbcTemplate.update("UPDATE users SET banned=1 WHERE id=?", isilmine.getUid());
- mockMvc.perform(get(String.format("/thread?mid=%d", mid)).with(httpBasic(ugnichName, ugnichPassword)))
+ mockMvc.perform(get(String.format("/api/thread?mid=%d", mid)).with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isNotFound());
- mockMvc.perform(get("/messages?uname=isilmine").with(httpBasic(ugnichName, ugnichPassword)))
+ mockMvc.perform(get("/api/messages?uname=isilmine").with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isNotFound());
- mockMvc.perform(get("/info/isilmine").with(httpBasic(ugnichName, ugnichPassword)))
+ mockMvc.perform(get("/api/info/isilmine").with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isNotFound());
- mockMvc.perform(get("/info/ugnich").with(httpBasic(ugnichName, ugnichPassword)))
+ mockMvc.perform(get("/api/info/ugnich").with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk());
}
@@ -1293,7 +1293,7 @@ public class ServerTests {
userService.createUser(userName, userPassword);
- mockMvc.perform(get("/auth").with(httpBasic(userName, userPassword))).andExpect(status().isUnauthorized());
+ mockMvc.perform(get("/api/auth").with(httpBasic(userName, userPassword))).andExpect(status().isUnauthorized());
}
@Test
public void bannedUserShouldBeShadowedFromRecommendationsList() throws IOException {
@@ -1342,7 +1342,7 @@ public class ServerTests {
}
@Test
public void userProfileAndBlogShouldBeExposedAsActivityStream() throws Exception {
- mockMvc.perform(get("/u/ugnich").accept(ActivityObject.LD_JSON_MEDIA_TYPE))
+ mockMvc.perform(get("/api/u/ugnich").accept(ActivityObject.LD_JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.icon.url", is("http://localhost:8080/i/a/1.png")))
.andExpect(jsonPath("$.publicKey.publicKeyPem", is(keystoreManager.getPublicKey())));
@@ -1352,7 +1352,7 @@ public class ServerTests {
String.format("message %d", i), null, null))
.collect(Collectors.toCollection(ArrayDeque::new)).descendingIterator());
List<Integer> midsPage = mids.stream().limit(20).collect(Collectors.toList());
- mockMvc.perform(get("/u/ugnich/blog").accept(ActivityObject.ACTIVITY_JSON_MEDIA_TYPE))
+ mockMvc.perform(get("/api/u/ugnich/blog").accept(ActivityObject.ACTIVITY_JSON_MEDIA_TYPE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.orderedItems", hasSize(20)))
.andExpect(jsonPath("$.next", is("http://localhost:8080/u/ugnich/blog?before=" + midsPage.get(midsPage.size() - 1))));
diff --git a/juick-server/src/test/java/com/juick/server/tests/WebAppTests.java b/juick-server/src/test/java/com/juick/server/tests/WebAppTests.java
new file mode 100644
index 000000000..456c5f327
--- /dev/null
+++ b/juick-server/src/test/java/com/juick/server/tests/WebAppTests.java
@@ -0,0 +1,466 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.tests;
+
+import com.gargoylesoftware.htmlunit.CookieManager;
+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.server.www.Utils;
+import com.juick.server.www.WebApp;
+import com.juick.service.*;
+import com.juick.util.MessageUtils;
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import org.apache.commons.collections4.CollectionUtils;
+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.beans.factory.annotation.Value;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.MediaType;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.util.FileSystemUtils;
+
+import javax.inject.Inject;
+import javax.servlet.http.Cookie;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+/**
+ * Created by vitalyster on 12.01.2017.
+ */
+@RunWith(SpringRunner.class)
+@AutoConfigureMockMvc
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@TestPropertySource(properties = {"ios_app_id=12345678.com.juick.ExampleApp"})
+public class WebAppTests {
+ @MockBean
+ private ImagesService imagesService;
+ @Inject
+ private WebApp webApp;
+
+ @Inject
+ private MockMvc mockMvc;
+ @Inject
+ private WebClient webClient;
+
+ @Inject
+ private UserService userService;
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private PrivacyQueriesService privacyQueriesService;
+ @Inject
+ private JdbcTemplate jdbcTemplate;
+ @Inject
+ private SubscriptionService subscriptionService;
+ @Inject
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ @Inject
+ private PebbleEngine pebbleEngine;
+ @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
+ private String imgPath;
+ @Value("${ios_app_id:}")
+ private String appId;
+
+ private static User ugnich, freefd;
+ private static String ugnichName, ugnichPassword, freefdName, freefdPassword;
+
+ private static boolean isSetUp = false;
+
+ @Before
+ public void setup() throws IOException {
+ if (!isSetUp) {
+ webClient.getOptions().setJavaScriptEnabled(false);
+ webClient.getOptions().setCssEnabled(false);
+ webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+
+ ugnichName = "ugnich";
+ ugnichPassword = "secret";
+ freefdName = "freefd";
+ freefdPassword = "MyPassw0rd!";
+
+ userService.createUser(ugnichName, ugnichPassword);
+ ugnich = userService.getUserByName(ugnichName);
+ int freefdId = userService.createUser(freefdName, freefdPassword);
+ freefd = userService.getUserByUID(freefdId).orElseThrow(IllegalStateException::new);
+
+ isSetUp = true;
+ }
+ Files.createDirectory(Paths.get(imgPath, "p"));
+ Files.createDirectory(Paths.get(imgPath, "photos-1024"));
+ Files.createDirectory(Paths.get(imgPath, "photos-512"));
+ Files.createDirectory(Paths.get(imgPath, "ps"));
+ }
+
+ @After
+ public void teardown() throws IOException {
+ FileSystemUtils.deleteRecursively(Paths.get(imgPath, "p"));
+ FileSystemUtils.deleteRecursively(Paths.get(imgPath, "photos-1024"));
+ FileSystemUtils.deleteRecursively(Paths.get(imgPath, "photos-512"));
+ FileSystemUtils.deleteRecursively(Paths.get(imgPath, "ps"));
+ }
+
+ @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 emptyPasswordMeansUserIsDisabledForWeb() throws Exception {
+ String userName = "oldschooluser";
+ String userPassword = "";
+
+ User daddy = userService.getUserByUID(userService.createUser(userName, userPassword)).orElseThrow(IllegalStateException::new);
+
+ mockMvc.perform(post("/login")
+ .param("username", userName)
+ .param("password", userPassword)).andExpect(status().is3xxRedirection())
+ .andExpect(redirectedUrl("/login?error=1"));
+ }
+ @Test
+ public void repliesList() throws IOException {
+ int mid = messagesService.createMessage(ugnich.getUid(), "hello", null, null);
+ IntStream.range(1, 15).forEach(i ->
+ messagesService.createReply(mid, i-1, freefd, 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(14L));
+ }
+ @Test
+ public void userShouldNotSeeReplyButtonToBannedUser() throws Exception {
+ int mid = messagesService.createMessage(ugnich.getUid(), "freefd bl me", null, null);
+ messagesService.createReply(mid, 0, ugnich, "yo", null);
+ MvcResult loginResult = mockMvc.perform(post("/login")
+ .param("username", freefdName)
+ .param("password", freefdPassword))
+ .andExpect(status().isFound()).andReturn();
+ Cookie loginCookie = loginResult.getResponse().getCookie("juick-remember-me");
+ webClient.setCookieManager(new CookieManager());
+ webClient.getCookieManager().addCookie(
+ new com.gargoylesoftware.htmlunit.util.Cookie(loginCookie.getDomain(),
+ loginCookie.getName(),
+ loginCookie.getValue()));
+ HtmlPage threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid));
+ assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(200));
+ assertThat(threadPage.querySelectorAll(".msg-comment-target").isEmpty(), equalTo(false));
+ assertThat(threadPage.querySelectorAll(".a-thread-comment").isEmpty(), equalTo(false));
+ privacyQueriesService.blacklistUser(freefd, ugnich);
+ assertThat(userService.isInBLAny(freefd.getUid(), ugnich.getUid()), equalTo(true));
+ int renhaId = userService.createUser("renha", "secret");
+ messagesService.createReply(mid, 0, userService.getUserByUID(renhaId).orElseThrow(IllegalStateException::new),
+ "people", null);
+ threadPage = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid));
+ assertThat(threadPage.getWebResponse().getStatusCode(), equalTo(200));
+ assertThat(threadPage.querySelectorAll(".msg-comment-target").isEmpty(), equalTo(true));
+ assertThat(threadPage.querySelectorAll(".a-thread-comment").isEmpty(), equalTo(true));
+ }
+ @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("<a href=\"/ugnich/?tag=%26gt%3B_%26lt%3B\">&gt;_&lt;</a>"));
+ }
+
+ 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))));
+ }
+ @Test
+ public void postMessageTests() throws Exception {
+ mockMvc.perform(post("/post2").param("body", "yo"))
+ .andExpect(status().is3xxRedirection()).andExpect(redirectedUrl("http://localhost/login"));
+ MvcResult loginResult = mockMvc.perform(post("/login")
+ .param("username", ugnichName)
+ .param("password", ugnichPassword)).andReturn();
+ String msgText = "yoppppl";
+ mockMvc.perform(post("/post2")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("body", msgText)).andExpect(status().isFound());
+ Message lastMessage = messagesService.getMessage(messagesService.getMyFeed(ugnich.getUid(), 0, false).get(0));
+ assertThat(lastMessage.getText(), equalTo(msgText));
+ mockMvc.perform(post("/post2")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("img", "http://static.juick.com/settings/facebook.png")).andExpect(status().isFound());
+ lastMessage = messagesService.getMessage(messagesService.getMyFeed(ugnich.getUid(), 0, false).get(0));
+ assertThat(lastMessage.getAttachmentType(), equalTo("png"));
+ mockMvc.perform(post("/post2")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("img", "bad_url")).andExpect(status().isBadRequest());
+ FileInputStream fi = new FileInputStream(new ClassPathResource("static/tagscloud.png").getFile());
+ MockMultipartFile file = new MockMultipartFile("attach", fi);
+ mockMvc.perform(multipart("/post2")
+ .file(file)
+ .cookie(loginResult.getResponse().getCookies())).andExpect(status().isFound());
+ int mid = messagesService.createMessage(ugnich.getUid(), "dummy message", null, null);
+ mockMvc.perform(post("/comment")
+ .param("mid", String.valueOf(mid))
+ .param("body", "yo")).andExpect(redirectedUrl("http://localhost/login"));
+ mockMvc.perform(post("/comment")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("wrong_param", "yo")).andExpect(status().isBadRequest());
+ mockMvc.perform(post("/comment")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("mid", String.valueOf(mid))
+ .param("wrong_param", "yo")).andExpect(status().isBadRequest());
+ mockMvc.perform(post("/comment")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("mid", String.valueOf(mid))
+ .param("img", "http://static.juick.com/settings/facebook.png")).andExpect(status().isFound());
+ mockMvc.perform(multipart("/comment")
+ .file(file)
+ .cookie(loginResult.getResponse().getCookies())
+ .param("mid", String.valueOf(mid))).andExpect(status().isFound());
+ mockMvc.perform(post("/comment")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("mid", String.valueOf(mid))
+ .param("body", "yo")).andExpect(redirectedUrl(String.format("/%s/%d#%d", ugnichName, mid, 3)));
+ mockMvc.perform(post("/post2")
+ .cookie(loginResult.getResponse().getCookies())
+ .param("body", String.format("D #%d/%d", mid, 3)))
+ .andExpect(status().isFound());
+ assertThat(messagesService.getReplies(ugnich, mid).size(), equalTo(2));
+ }
+ @Test
+ public void hashLoginShouldNotUseSession() throws Exception {
+ String hash = userService.getHashByUID(ugnich.getUid());
+ MvcResult hashLoginResult = mockMvc.perform(get("/?show=my&hash=" + hash))
+ .andExpect(status().isOk())
+ .andExpect(model().attribute("visitor", hasProperty("authHash", equalTo(hash))))
+ .andExpect(content().string(containsString(hash)))
+ .andReturn();
+ Cookie rememberMeFromHash = hashLoginResult.getResponse().getCookie("juick-remember-me");
+ MvcResult formLoginResult = mockMvc.perform(post("/login")
+ .param("username", ugnichName)
+ .param("password", ugnichPassword))
+ .andExpect(status().is3xxRedirection()).andReturn();
+ Cookie rememberMeFromForm = formLoginResult.getResponse().getCookie("juick-remember-me");
+ mockMvc.perform(get("/?show=my").cookie(rememberMeFromForm)).andExpect(status().isOk())
+ .andExpect(model().attribute("visitor", hasProperty("authHash", equalTo(hash))))
+ .andExpect(content().string(containsString(hash)));
+ mockMvc.perform(get("/?show=my").cookie(rememberMeFromHash)).andExpect(status().isOk())
+ .andExpect(model().attribute("visitor", hasProperty("authHash", equalTo(hash))))
+ .andExpect(content().string(containsString(hash)));
+ }
+ @Test
+ public void nonExistentBlogShouldReturn404() throws Exception {
+ mockMvc.perform(get("/ololoe/")).andExpect(status().isNotFound());
+ }
+ @Test
+ public void discussionsShouldBePageableByTimestamp() throws Exception {
+ String msgText = "Привет, я снова Угнич";
+ int mid = messagesService.createMessage(ugnich.getUid(), msgText, null, null);
+ int midNew = messagesService.createMessage(ugnich.getUid(), "Я более новый Угнич", null, null);
+ MvcResult loginResult = mockMvc.perform(post("/login")
+ .param("username", freefdName)
+ .param("password", freefdPassword))
+ .andExpect(status().is3xxRedirection()).andReturn();
+ Cookie loginCookie = loginResult.getResponse().getCookie("juick-remember-me");
+ webClient.setCookieManager(new CookieManager());
+ webClient.getCookieManager().addCookie(
+ new com.gargoylesoftware.htmlunit.util.Cookie(loginCookie.getDomain(),
+ loginCookie.getName(),
+ loginCookie.getValue()));
+ String discussionsUrl = "http://localhost:8080/?show=discuss";
+ HtmlPage discussions = webClient.getPage(discussionsUrl);
+ assertThat(discussions.querySelectorAll("article").size(), is(0));
+ subscriptionService.subscribeMessage(messagesService.getMessage(mid), freefd);
+ discussions = (HtmlPage) discussions.refresh();
+ assertThat(discussions.querySelectorAll("article").size(), is(1));
+ subscriptionService.subscribeMessage(messagesService.getMessage(midNew), freefd);
+ discussions = (HtmlPage) discussions.refresh();
+ assertThat(discussions.querySelectorAll("article").size(), is(2));
+ assertThat(discussions.querySelectorAll("article").get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(midNew)));
+ messagesService.createReply(mid, 0, freefd, "I'm replied", null);
+ discussions = (HtmlPage) discussions.refresh();
+ assertThat(discussions.querySelectorAll("article").size(), is(2));
+ assertThat(discussions.querySelectorAll("article").get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(mid)));
+ Message msg = messagesService.getMessage(mid);
+ HtmlPage discussionsOld = webClient.getPage(discussionsUrl + "&to=" + msg.getUpdated().toEpochMilli());
+ assertThat(discussionsOld.querySelectorAll("article").size(), is(1));
+ assertThat(discussionsOld.querySelectorAll("article").get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(midNew)));
+ List<Integer> newMids = IntStream.rangeClosed(1, 19).map(i -> messagesService.createMessage(ugnich.getUid(), String.valueOf(i), null, null)).boxed().collect(Collectors.toList());
+ for (Integer m : newMids) {
+ subscriptionService.subscribeMessage(messagesService.getMessage(m), freefd);
+ }
+ discussions = (HtmlPage) discussions.refresh();
+ assertThat(discussions.querySelectorAll("article").size(), is(20));
+ assertThat(discussions.querySelectorAll("article")
+ .get(19).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(mid)));
+ messagesService.createReply(midNew, 0, freefd, "I'm replied", null);
+ discussions = (HtmlPage) discussions.refresh();
+ assertThat(discussions.querySelectorAll("article")
+ .get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(midNew)));
+ Message old = messagesService.getMessage(newMids.get(0));
+ discussionsOld = webClient.getPage(discussionsUrl + "&to=" + old.getUpdated().toEpochMilli());
+ assertThat(discussionsOld.querySelectorAll("article").size(), is(1));
+ assertThat(discussionsOld.querySelectorAll("article")
+ .get(0).getAttributes().getNamedItem("data-mid").getNodeValue(), is(String.valueOf(mid)));
+ }
+ @Test
+ public void redirectParamShouldCorrectlyRedirectLoggedUser() throws Exception {
+ MvcResult formLoginResult = mockMvc.perform(post("/login")
+ .param("username", ugnichName)
+ .param("password", ugnichPassword))
+ .andExpect(status().isFound()).andReturn();
+ Cookie rememberMeFromForm = formLoginResult.getResponse().getCookie("juick-remember-me");
+ mockMvc.perform(get("/login").cookie(rememberMeFromForm))
+ .andExpect(status().is3xxRedirection())
+ .andExpect(redirectedUrl("/"));
+ mockMvc.perform(get("/login?redirect=false").cookie(rememberMeFromForm))
+ .andExpect(status().is3xxRedirection())
+ .andExpect(redirectedUrl("/login/success"));
+ }
+ @Test
+ public void anythingRedirects() throws Exception {
+ int mid = messagesService.createMessage(ugnich.getUid(), "yo", null, null);
+ mockMvc.perform(get(String.format("/%d", mid)))
+ .andExpect(status().isMovedPermanently())
+ .andExpect(redirectedUrl(String.format("/%s/%d", ugnich.getName(), mid)));
+ }
+ @Test
+ public void appAssociationsTest() throws Exception {
+ mockMvc.perform((get("/.well-known/apple-app-site-association")))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(jsonPath("$.webcredentials.apps[0]", is(appId)));
+ }
+ @Test
+ public void notificationsTests() throws Exception {
+ MvcResult loginResult = mockMvc.perform(post("/login")
+ .param("username", freefdName)
+ .param("password", freefdPassword))
+ .andExpect(status().is3xxRedirection()).andReturn();
+ Cookie loginCookie = loginResult.getResponse().getCookie("juick-remember-me");
+ webClient.setCookieManager(new CookieManager());
+ webClient.getCookieManager().addCookie(
+ new com.gargoylesoftware.htmlunit.util.Cookie(loginCookie.getDomain(),
+ loginCookie.getName(),
+ loginCookie.getValue()));
+ int mid = messagesService.createMessage(ugnich.getUid(), "new test", null, null);
+ subscriptionService.subscribeMessage(messagesService.getMessage(mid), freefd);
+ int rid = messagesService.createReply(mid, 0, ugnich, "new reply", null);
+ HtmlPage discussionsPage = webClient.getPage("http://localhost:8080/?show=discuss");
+ assertThat(discussionsPage.querySelectorAll("#global a .badge").size(), is(1));
+ HtmlPage unreadThread = webClient.getPage(String.format("http://localhost:8080/ugnich/%d", mid));
+ assertThat(unreadThread.querySelectorAll("#global a .badge").size(), is(0));
+ }
+ @Test
+ public void escapeSqlTests() {
+ String sql = String.format("SELECT * FROM table WHERE data='%s'", Utils.encodeSphinx("';-- DROP TABLE table"));
+ assertThat(sql, is("SELECT * FROM table WHERE data='\\';-- DROP TABLE table\'"));
+ }
+ @Test
+ public void bannedUserShouldBeShadowedFromRecommendationsList() throws IOException {
+ int ermineId = userService.createUser("ermine", "secret");
+ int monstreekId = userService.createUser("monstreek", "secret");
+ int pogoId = userService.createUser("pogo", "secret");
+ int fmapId = userService.createUser("fmap", "secret");
+ int mid = messagesService.createMessage(monstreekId, "KURWA", null, null);
+ assertThat(messagesService.recommendMessage(mid, ermineId), is(MessagesService.RecommendStatus.Added));
+ assertThat(messagesService.recommendMessage(mid, fmapId), is(MessagesService.RecommendStatus.Added));
+ assertThat(messagesService.recommendMessage(mid, pogoId), is(MessagesService.RecommendStatus.Added));
+ assertThat(messagesService.getMessage(mid).getLikes(), is(3));
+ assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid), Arrays.asList("fmap", "ermine", "pogo")), is(true));
+ privacyQueriesService.blacklistUser(userService.getUserByName("monstreek"), userService.getUserByName("pogo"));
+ assertThat(messagesService.getMessage(mid).getLikes(), is(3));
+ assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid), Arrays.asList("fmap", "ermine")), is(true));
+ HtmlPage page = webClient.getPage(String.format("http://localhost:8080/monstreek/%d", mid));
+ assertTrue(page.querySelector(".msg-recomms").getTextContent().contains("и еще 1"));
+ }
+}