From c541fb3cfe0070db3f8ff5f422d203be5e0e2e27 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Wed, 9 Nov 2016 21:34:16 +0100 Subject: [PATCH] Add unit test for parser filter --- .../sone/template/ParserFilterTest.java | 258 +++++++++++++++++++-- 1 file changed, 239 insertions(+), 19 deletions(-) diff --git a/src/test/java/net/pterodactylus/sone/template/ParserFilterTest.java b/src/test/java/net/pterodactylus/sone/template/ParserFilterTest.java index f6275fc..5820652 100644 --- a/src/test/java/net/pterodactylus/sone/template/ParserFilterTest.java +++ b/src/test/java/net/pterodactylus/sone/template/ParserFilterTest.java @@ -1,20 +1,33 @@ package net.pterodactylus.sone.template; +import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentCaptor.forClass; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.net.URLEncoder; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import net.pterodactylus.sone.core.Core; +import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.Profile; import net.pterodactylus.sone.data.Sone; import net.pterodactylus.sone.text.FreemailPart; +import net.pterodactylus.sone.text.FreenetLinkPart; +import net.pterodactylus.sone.text.LinkPart; import net.pterodactylus.sone.text.Part; +import net.pterodactylus.sone.text.PartContainer; +import net.pterodactylus.sone.text.PlainTextPart; +import net.pterodactylus.sone.text.PostPart; +import net.pterodactylus.sone.text.SonePart; import net.pterodactylus.sone.text.SoneTextParser; import net.pterodactylus.sone.text.SoneTextParserContext; import net.pterodactylus.util.template.HtmlFilter; @@ -24,10 +37,10 @@ import net.pterodactylus.util.template.TemplateContextFactory; import com.google.common.base.Optional; import org.jsoup.Jsoup; import org.jsoup.nodes.Attribute; -import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.junit.Before; +import org.jsoup.nodes.TextNode; import org.junit.Test; +import org.mockito.ArgumentCaptor; /** * Unit test for {@link ParserFilter}. @@ -39,35 +52,242 @@ public class ParserFilterTest { private static final String FREEMAIL_ID = "t4dlzfdww3xvsnsc6j6gtliox6zaoak7ymkobbmcmdw527ubuqra"; private static final String SONE_FREEMAIL = "sone@" + FREEMAIL_ID + ".freemail"; private static final String SONE_IDENTITY = "nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI"; + private static final String POST_ID = "37a06250-6775-4b94-86ff-257ba690953c"; private final Core core = mock(Core.class); private final TemplateContextFactory templateContextFactory = new TemplateContextFactory(); + private final TemplateContext templateContext; private final SoneTextParser soneTextParser = mock(SoneTextParser.class); private final ParserFilter filter = new ParserFilter(core, templateContextFactory, soneTextParser); + private final Sone sone = setupSone(SONE_IDENTITY, "Sone", "First"); + private final Map parameters = new HashMap<>(); - @Before - public void setupTemplateContextFactory() { + public ParserFilterTest() { templateContextFactory.addFilter("html", new HtmlFilter()); + templateContext = templateContextFactory.createTemplateContext(); } @Test - public void freemailAddressIsDisplayedCorrectly() { - Sone sone = mock(Sone.class); - when(sone.getProfile()).thenReturn(new Profile(sone)); - sone.getProfile().setFirstName("Sone"); - when(core.getSone(SONE_IDENTITY)).thenReturn(Optional.of(sone)); - when(soneTextParser.parse(anyString(), any(SoneTextParserContext.class))).thenReturn(Collections.singletonList(new FreemailPart("sone", FREEMAIL_ID, SONE_IDENTITY))); - TemplateContext templateContext = templateContextFactory.createTemplateContext(); - String output = String.valueOf(filter.format(templateContext, SONE_FREEMAIL, Collections.emptyMap())); - Document document = Jsoup.parseBodyFragment(output); - Element linkNode = document.body().child(0); + public void givenSoneIsUsedInParseContext() { + setupSoneAndVerifyItIsUsedInContext(sone, sone); + } + + private void setupSoneAndVerifyItIsUsedInContext(Object soneOrSoneId, Sone sone) { + setupParser("text", new PlainTextPart("text")); + parameters.put("sone", sone); + filter.format(templateContext, "text", parameters); + ArgumentCaptor context = forClass(SoneTextParserContext.class); + verify(soneTextParser).parse(eq("text"), context.capture()); + assertThat(context.getValue().getPostingSone(), is(sone)); + } + + @Test + public void soneWithGivenSoneIdIsUsedInParseContext() { + setupSoneAndVerifyItIsUsedInContext(SONE_IDENTITY, sone); + } + + @Test + public void plainTextIsRenderedCorrectly() { + setupParser("plain text", new PlainTextPart("plain text")); + String result = (String) filter.format(templateContext, "plain text", Collections.emptyMap()); + assertThat(result, is("plain text")); + } + + private void setupParser(String text, Part... parsedParts) { + when(soneTextParser.parse(eq(text), any(SoneTextParserContext.class))).thenReturn(asList(parsedParts)); + } + + @Test + public void plainTextPartIsShortenedIfLengthExceedsMaxLength() { + setupParser("text", new PlainTextPart("This is a long text.")); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + @Test + public void plainTextPartIsNotShortenedIfLengthDoesNotExceedMaxLength() { + setupParser("text", new PlainTextPart("This is a long text.")); + setLengthAndCutOffLength(20, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + @Test + public void shortPartsAreNotShortened() { + setupParser("text", new PlainTextPart("This.")); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This.")); + } + + @Test + public void multiplePlainTextPartsAreShortened() { + setupParser("text", new PlainTextPart("This "), new PlainTextPart("is a long text.")); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + @Test + public void partsAfterLengthHasBeenReachedAreIgnored() { + setupParser("text", new PlainTextPart("This is a long text."), new PlainTextPart(" And even more.")); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + @Test + public void linkPartsAreNotShortened() { + setupParser("text", new FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false)); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + Element linkNode = Jsoup.parseBodyFragment(output).body().child(0); + verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "This is a long text."); + } + + @Test + public void additionalLinkPartsAreIgnored() { + setupParser("text", new PlainTextPart("This is a long text."), new FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false)); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + private void setLengthAndCutOffLength(int length, int cutOffLength) { + parameters.put("length", length); + parameters.put("cut-off-length", cutOffLength); + } + + @Test + public void sonePartsAreAddedButTheirLengthIsIgnored() { + setupParser("text", new SonePart(sone), new PlainTextPart("This is a long text.")); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + Element body = Jsoup.parseBodyFragment(output).body(); + Element linkNode = (Element) body.childNode(0); + System.out.println(linkNode); + verifyLink(linkNode, "viewSone.html?sone=" + SONE_IDENTITY, "in-sone", "First", "First"); + assertThat(((TextNode) body.childNode(1)).text(), is("This is a …")); + } + + @Test + public void additionalSonePartsAreIgnored() { + setupParser("text", new PlainTextPart("This is a long text."), new SonePart(sone)); + setLengthAndCutOffLength(15, 10); + String output = (String) filter.format(templateContext, "text", parameters); + assertThat(output, is("This is a …")); + } + + @Test + public void freenetLinkIsRenderedCorrectly() { + setupParser("KSK@gpl.txt", new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)); + Element linkNode = filterText("KSK@gpl.txt"); + verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "gpl.txt"); + } + + private void verifyLink(Element linkNode, String url, String cssClass, String tooltip, String text) { assertThat(linkNode.nodeName(), is("a")); assertThat(linkNode.attributes().asList(), containsInAnyOrder( - new Attribute("href", "/Freemail/NewMessage?to=" + SONE_IDENTITY), - new Attribute("class", "in-sone"), - new Attribute("title", "Sone\n" + SONE_FREEMAIL) + new Attribute("href", url), + new Attribute("class", cssClass), + new Attribute("title", tooltip) )); - assertThat(linkNode.text(), is("sone@Sone.freemail")); + assertThat(linkNode.text(), is(text)); + } + + @Test + public void trustedFreenetLinkIsRenderedWithCorrectCssClass() { + setupParser("KSK@gpl.txt", new FreenetLinkPart("KSK@gpl.txt", "gpl.txt", true)); + Element linkNode = filterText("KSK@gpl.txt"); + verifyLink(linkNode, "/KSK@gpl.txt", "freenet-trusted", "KSK@gpl.txt", "gpl.txt"); + } + + private Element filterText(String text) { + String output = (String) filter.format(templateContext, text, Collections.emptyMap()); + return Jsoup.parseBodyFragment(output).body().child(0); + } + + @Test + public void internetLinkIsRenderedCorrectly() throws Exception { + setupParser("http://test.com/test.html", new LinkPart("http://test.com/test.html", "test.com/test.html")); + Element linkNode = filterText("http://test.com/test.html"); + verifyLink(linkNode, "/external-link/?_CHECKED_HTTP_=" + URLEncoder.encode("http://test.com/test.html", "UTF-8"), "internet", + "http://test.com/test.html", "test.com/test.html"); + } + + @Test + public void sonePartsAreRenderedCorrectly() { + setupParser("sone://" + SONE_IDENTITY, new SonePart(sone)); + Element linkNode = filterText("sone://" + SONE_IDENTITY); + verifyLink(linkNode, "viewSone.html?sone=" + SONE_IDENTITY, "in-sone", "First", "First"); + } + + private Sone setupSone(String identity, String name, String firstName) { + Sone sone = mock(Sone.class); + when(sone.getId()).thenReturn(identity); + when(sone.getProfile()).thenReturn(new Profile(sone)); + when(sone.getName()).thenReturn(name); + sone.getProfile().setFirstName(firstName); + when(core.getSone(identity)).thenReturn(Optional.of(sone)); + return sone; + } + + @Test + public void sonePartsWithUnknownSoneIsRenderedAsLinkToWebOfTrust() { + Sone sone = setupSone(SONE_IDENTITY, null, "First"); + setupParser("sone://" + SONE_IDENTITY, new SonePart(sone)); + Element linkNode = filterText("sone://" + SONE_IDENTITY); + verifyLink(linkNode, "/WebOfTrust/ShowIdentity?id=" + SONE_IDENTITY, "in-sone", SONE_IDENTITY, SONE_IDENTITY); + } + + @Test + public void postPartIsCutOffCorrectlyWhenThereAreSpaces() { + Post post = setupPost(sone, "1234 678901 345 789012 45678 01."); + setupParser("post://" + POST_ID, new PostPart(post)); + Element linkNode = filterText("post://" + POST_ID); + verifyLink(linkNode, "viewPost.html?post=" + POST_ID, "in-sone", "First", "1234 678901 345…"); + } + + private Post setupPost(Sone sone, String value) { + Post post = mock(Post.class); + when(post.getId()).thenReturn(POST_ID); + when(post.getSone()).thenReturn(sone); + when(post.getText()).thenReturn(value); + return post; + } + + @Test + public void postPartIsCutOffCorrectlyWhenThereAreNoSpaces() { + Post post = setupPost(sone, "1234567890123456789012345678901."); + setupParser("post://" + POST_ID, new PostPart(post)); + Element linkNode = filterText("post://" + POST_ID); + verifyLink(linkNode, "viewPost.html?post=" + POST_ID, "in-sone", "First", "12345678901234567890…"); + } + + @Test + public void postPartShorterThan21CharsIsNotCutOff() { + Post post = setupPost(sone, "12345678901234567890"); + setupParser("post://" + POST_ID, new PostPart(post)); + Element linkNode = filterText("post://" + POST_ID); + verifyLink(linkNode, "viewPost.html?post=" + POST_ID, "in-sone", "First", "12345678901234567890"); + } + + @Test + public void multiplePartsAreRenderedCorrectly() { + PartContainer parts = new PartContainer(); + parts.add(new PlainTextPart("te")); + parts.add(new PlainTextPart("xt")); + setupParser("text", parts); + String result = (String) filter.format(templateContext, "text", Collections.emptyMap()); + assertThat(result, is("text")); + } + + @Test + public void freemailAddressIsDisplayedCorrectly() { + setupParser(SONE_FREEMAIL, new FreemailPart("sone", FREEMAIL_ID, SONE_IDENTITY)); + Element linkNode = filterText(SONE_FREEMAIL); + verifyLink(linkNode, "/Freemail/NewMessage?to=" + SONE_IDENTITY, "in-sone", "First\n" + SONE_FREEMAIL, "sone@First.freemail"); } } -- 2.7.4