package net.pterodactylus.sone.template import com.google.common.base.Optional 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.test.mock 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.util.template.HtmlFilter import net.pterodactylus.util.template.TemplateContext import net.pterodactylus.util.template.TemplateContextFactory import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.`is` import org.hamcrest.Matchers.containsInAnyOrder import org.jsoup.Jsoup import org.jsoup.nodes.Attribute import org.jsoup.nodes.Element import org.jsoup.nodes.TextNode import org.junit.Test import org.mockito.Mockito.`when` import java.net.URLEncoder /** * Unit test for [RenderFilter]. */ class RenderFilterTest { companion object { private const val FREEMAIL_ID = "t4dlzfdww3xvsnsc6j6gtliox6zaoak7ymkobbmcmdw527ubuqra" private const val SONE_FREEMAIL = "sone@$FREEMAIL_ID.freemail" private const val SONE_IDENTITY = "nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI" private const val POST_ID = "37a06250-6775-4b94-86ff-257ba690953c" } private val core = mock() private val templateContextFactory = TemplateContextFactory() private val templateContext: TemplateContext private val sone = setupSone(SONE_IDENTITY, "Sone", "First") private val parameters = mutableMapOf() init { templateContextFactory.addFilter("html", HtmlFilter()) templateContext = templateContextFactory.createTemplateContext() } private val filter = RenderFilter(core, templateContextFactory) @Test fun plainTextIsRenderedCorrectly() { assertThat(renderParts(PlainTextPart("plain text")), `is`("plain text")) } private fun renderParts(vararg part: Part) = filter.format(templateContext, listOf(*part), parameters) as String @Test fun plainTextPartIsShortenedIfLengthExceedsMaxLength() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a …")) } @Test fun plainTextPartIsNotShortenedIfLengthDoesNotExceedMaxLength() { setLengthAndCutOffLength(20, 10) assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a …")) } @Test fun shortPartsAreNotShortened() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This.")), `is`("This.")) } @Test fun multiplePlainTextPartsAreShortened() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This "), PlainTextPart("is a long text.")), `is`("This is a …")) } @Test fun partsAfterLengthHasBeenReachedAreIgnored() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This is a long text."), PlainTextPart(" And even more.")), `is`("This is a …")) } @Test fun linkPartsAreNotShortened() { setLengthAndCutOffLength(15, 10) val linkNode = Jsoup.parseBodyFragment(renderParts(FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false))).body().child(0) verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "This is a long text.") } @Test fun additionalLinkPartsAreIgnored() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This is a long text."), FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false)), `is`("This is a …")) } private fun setLengthAndCutOffLength(length: Int, cutOffLength: Int) { parameters.put("length", length) parameters.put("cut-off-length", cutOffLength) } @Test fun sonePartsAreAddedButTheirLengthIsIgnored() { setLengthAndCutOffLength(15, 10) val body = Jsoup.parseBodyFragment(renderParts(SonePart(sone), PlainTextPart("This is a long text."))).body() val linkNode = body.childNode(0) as Element println(linkNode) verifyLink(linkNode, "viewSone.html?sone=$SONE_IDENTITY", "in-sone", "First", "First") assertThat((body.childNode(1) as TextNode).text(), `is`("This is a …")) } @Test fun additionalSonePartsAreIgnored() { setLengthAndCutOffLength(15, 10) assertThat(renderParts(PlainTextPart("This is a long text."), SonePart(sone)), `is`("This is a …")) } @Test fun freenetLinkIsRenderedCorrectly() { val linkNode = renderParts(FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)).toLinkNode() verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "gpl.txt") } private fun verifyLink(linkNode: Element, url: String, cssClass: String, tooltip: String, text: String) { assertThat(linkNode.nodeName(), `is`("a")) assertThat>(linkNode.attributes().asList(), containsInAnyOrder( Attribute("href", url), Attribute("class", cssClass), Attribute("title", tooltip) )) assertThat(linkNode.text(), `is`(text)) } @Test fun trustedFreenetLinkIsRenderedWithCorrectCssClass() { val linkNode = renderParts(FreenetLinkPart("KSK@gpl.txt", "gpl.txt", true)).toLinkNode() verifyLink(linkNode, "/KSK@gpl.txt", "freenet-trusted", "KSK@gpl.txt", "gpl.txt") } private fun String.toLinkNode() = Jsoup.parseBodyFragment(this).body().child(0) @Test fun internetLinkIsRenderedCorrectly() { val linkNode = renderParts(LinkPart("http://test.com/test.html", "test.com/test.html")).toLinkNode() 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 fun sonePartsAreRenderedCorrectly() { val linkNode = renderParts(SonePart(sone)).toLinkNode() verifyLink(linkNode, "viewSone.html?sone=" + SONE_IDENTITY, "in-sone", "First", "First") } private fun setupSone(identity: String, name: String?, firstName: String): Sone { val sone = mock() `when`(sone.id).thenReturn(identity) `when`(sone.profile).thenReturn(Profile(sone)) `when`(sone.name).thenReturn(name) sone.profile.firstName = firstName `when`(core.getSone(identity)).thenReturn(Optional.of(sone)) return sone } @Test fun sonePartsWithUnknownSoneIsRenderedAsLinkToWebOfTrust() { val sone = setupSone(SONE_IDENTITY, null, "First") val linkNode = renderParts(SonePart(sone)).toLinkNode() verifyLink(linkNode, "/WebOfTrust/ShowIdentity?id=$SONE_IDENTITY", "in-sone", SONE_IDENTITY, SONE_IDENTITY) } @Test fun postPartIsCutOffCorrectlyWhenThereAreSpaces() { val post = setupPost(sone, "1234 678901 345 789012 45678 01.") val linkNode = renderParts(PostPart(post)).toLinkNode() verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "1234 678901 345…") } private fun setupPost(sone: Sone, value: String): Post { val post = mock() `when`(post.id).thenReturn(POST_ID) `when`(post.sone).thenReturn(sone) `when`(post.text).thenReturn(value) return post } @Test fun postPartIsCutOffCorrectlyWhenThereAreNoSpaces() { val post = setupPost(sone, "1234567890123456789012345678901.") val linkNode = renderParts(PostPart(post)).toLinkNode() verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "12345678901234567890…") } @Test fun postPartShorterThan21CharsIsNotCutOff() { val post = setupPost(sone, "12345678901234567890") val linkNode = renderParts(PostPart(post)).toLinkNode() verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "12345678901234567890") } @Test fun multiplePartsAreRenderedCorrectly() { val parts = PartContainer() parts.add(PlainTextPart("te")) parts.add(PlainTextPart("xt")) assertThat(renderParts(parts), `is`("text")) } @Test fun freemailAddressIsDisplayedCorrectly() { val linkNode = renderParts(FreemailPart("sone", FREEMAIL_ID, SONE_IDENTITY)).toLinkNode() verifyLink(linkNode, "/Freemail/NewMessage?to=$SONE_IDENTITY", "in-sone", "First\n$SONE_FREEMAIL", "sone@First.freemail") } }