1 package net.pterodactylus.sone.template
3 import com.google.common.base.Optional
4 import net.pterodactylus.sone.core.Core
5 import net.pterodactylus.sone.data.Post
6 import net.pterodactylus.sone.data.Profile
7 import net.pterodactylus.sone.data.Sone
8 import net.pterodactylus.sone.test.mock
9 import net.pterodactylus.sone.text.FreemailPart
10 import net.pterodactylus.sone.text.FreenetLinkPart
11 import net.pterodactylus.sone.text.LinkPart
12 import net.pterodactylus.sone.text.Part
13 import net.pterodactylus.sone.text.PartContainer
14 import net.pterodactylus.sone.text.PlainTextPart
15 import net.pterodactylus.sone.text.PostPart
16 import net.pterodactylus.sone.text.SonePart
17 import net.pterodactylus.util.template.HtmlFilter
18 import net.pterodactylus.util.template.TemplateContext
19 import net.pterodactylus.util.template.TemplateContextFactory
20 import org.hamcrest.MatcherAssert.assertThat
21 import org.hamcrest.Matchers.`is`
22 import org.hamcrest.Matchers.containsInAnyOrder
23 import org.jsoup.Jsoup
24 import org.jsoup.nodes.Attribute
25 import org.jsoup.nodes.Element
26 import org.jsoup.nodes.TextNode
28 import org.mockito.Mockito.`when`
29 import java.net.URLEncoder
32 * Unit test for [RenderFilter].
34 class RenderFilterTest {
37 private const val FREEMAIL_ID = "t4dlzfdww3xvsnsc6j6gtliox6zaoak7ymkobbmcmdw527ubuqra"
38 private const val SONE_FREEMAIL = "sone@$FREEMAIL_ID.freemail"
39 private const val SONE_IDENTITY = "nwa8lHa271k2QvJ8aa0Ov7IHAV-DFOCFgmDt3X6BpCI"
40 private const val POST_ID = "37a06250-6775-4b94-86ff-257ba690953c"
43 private val core = mock<Core>()
44 private val templateContextFactory = TemplateContextFactory()
45 private val templateContext: TemplateContext
46 private val sone = setupSone(SONE_IDENTITY, "Sone", "First")
47 private val parameters = mutableMapOf<String, Any?>()
50 templateContextFactory.addFilter("html", HtmlFilter())
51 templateContext = templateContextFactory.createTemplateContext()
54 private val filter = RenderFilter(core, templateContextFactory)
57 fun plainTextIsRenderedCorrectly() {
58 assertThat(renderParts(PlainTextPart("plain text")), `is`("plain text"))
61 private fun renderParts(vararg part: Part) = filter.format(templateContext, listOf(*part), parameters) as String
64 fun plainTextPartIsShortenedIfLengthExceedsMaxLength() {
65 setLengthAndCutOffLength(15, 10)
66 assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a …"))
70 fun plainTextPartIsNotShortenedIfLengthDoesNotExceedMaxLength() {
71 setLengthAndCutOffLength(20, 10)
72 assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a …"))
76 fun shortPartsAreNotShortened() {
77 setLengthAndCutOffLength(15, 10)
78 assertThat(renderParts(PlainTextPart("This.")), `is`("This."))
82 fun multiplePlainTextPartsAreShortened() {
83 setLengthAndCutOffLength(15, 10)
84 assertThat(renderParts(PlainTextPart("This "), PlainTextPart("is a long text.")), `is`("This is a …"))
88 fun partsAfterLengthHasBeenReachedAreIgnored() {
89 setLengthAndCutOffLength(15, 10)
90 assertThat(renderParts(PlainTextPart("This is a long text."), PlainTextPart(" And even more.")), `is`("This is a …"))
94 fun linkPartsAreNotShortened() {
95 setLengthAndCutOffLength(15, 10)
96 val linkNode = Jsoup.parseBodyFragment(renderParts(FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false))).body().child(0)
97 verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "This is a long text.")
101 fun additionalLinkPartsAreIgnored() {
102 setLengthAndCutOffLength(15, 10)
103 assertThat(renderParts(PlainTextPart("This is a long text."), FreenetLinkPart("KSK@gpl.txt", "This is a long text.", false)), `is`("This is a …"))
106 private fun setLengthAndCutOffLength(length: Int, cutOffLength: Int) {
107 parameters.put("length", length)
108 parameters.put("cut-off-length", cutOffLength)
112 fun sonePartsAreAddedButTheirLengthIsIgnored() {
113 setLengthAndCutOffLength(15, 10)
114 val body = Jsoup.parseBodyFragment(renderParts(SonePart(sone), PlainTextPart("This is a long text."))).body()
115 val linkNode = body.childNode(0) as Element
117 verifyLink(linkNode, "viewSone.html?sone=$SONE_IDENTITY", "in-sone", "First", "First")
118 assertThat((body.childNode(1) as TextNode).text(), `is`("This is a …"))
122 fun additionalSonePartsAreIgnored() {
123 setLengthAndCutOffLength(15, 10)
124 assertThat(renderParts(PlainTextPart("This is a long text."), SonePart(sone)), `is`("This is a …"))
128 fun freenetLinkIsRenderedCorrectly() {
129 val linkNode = renderParts(FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)).toLinkNode()
130 verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "gpl.txt")
133 private fun verifyLink(linkNode: Element, url: String, cssClass: String, tooltip: String, text: String) {
134 assertThat(linkNode.nodeName(), `is`("a"))
135 assertThat<List<Attribute>>(linkNode.attributes().asList(), containsInAnyOrder(
136 Attribute("href", url),
137 Attribute("class", cssClass),
138 Attribute("title", tooltip)
140 assertThat(linkNode.text(), `is`(text))
144 fun trustedFreenetLinkIsRenderedWithCorrectCssClass() {
145 val linkNode = renderParts(FreenetLinkPart("KSK@gpl.txt", "gpl.txt", true)).toLinkNode()
146 verifyLink(linkNode, "/KSK@gpl.txt", "freenet-trusted", "KSK@gpl.txt", "gpl.txt")
149 private fun String.toLinkNode() = Jsoup.parseBodyFragment(this).body().child(0)
152 fun internetLinkIsRenderedCorrectly() {
153 val linkNode = renderParts(LinkPart("http://test.com/test.html", "test.com/test.html")).toLinkNode()
154 verifyLink(linkNode, "/external-link/?_CHECKED_HTTP_=${URLEncoder.encode("http://test.com/test.html", "UTF-8")}", "internet",
155 "http://test.com/test.html", "test.com/test.html")
159 fun sonePartsAreRenderedCorrectly() {
160 val linkNode = renderParts(SonePart(sone)).toLinkNode()
161 verifyLink(linkNode, "viewSone.html?sone=" + SONE_IDENTITY, "in-sone", "First", "First")
164 private fun setupSone(identity: String, name: String?, firstName: String): Sone {
165 val sone = mock<Sone>()
166 `when`(sone.id).thenReturn(identity)
167 `when`(sone.profile).thenReturn(Profile(sone))
168 `when`(sone.name).thenReturn(name)
169 sone.profile.firstName = firstName
170 `when`(core.getSone(identity)).thenReturn(Optional.of<Sone>(sone))
175 fun sonePartsWithUnknownSoneIsRenderedAsLinkToWebOfTrust() {
176 val sone = setupSone(SONE_IDENTITY, null, "First")
177 val linkNode = renderParts(SonePart(sone)).toLinkNode()
178 verifyLink(linkNode, "/WebOfTrust/ShowIdentity?id=$SONE_IDENTITY", "in-sone", SONE_IDENTITY, SONE_IDENTITY)
182 fun postPartIsCutOffCorrectlyWhenThereAreSpaces() {
183 val post = setupPost(sone, "1234 678901 345 789012 45678 01.")
184 val linkNode = renderParts(PostPart(post)).toLinkNode()
185 verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "1234 678901 345…")
188 private fun setupPost(sone: Sone, value: String): Post {
189 val post = mock<Post>()
190 `when`(post.id).thenReturn(POST_ID)
191 `when`(post.sone).thenReturn(sone)
192 `when`(post.text).thenReturn(value)
197 fun postPartIsCutOffCorrectlyWhenThereAreNoSpaces() {
198 val post = setupPost(sone, "1234567890123456789012345678901.")
199 val linkNode = renderParts(PostPart(post)).toLinkNode()
200 verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "12345678901234567890…")
204 fun postPartShorterThan21CharsIsNotCutOff() {
205 val post = setupPost(sone, "12345678901234567890")
206 val linkNode = renderParts(PostPart(post)).toLinkNode()
207 verifyLink(linkNode, "viewPost.html?post=$POST_ID", "in-sone", "First", "12345678901234567890")
211 fun multiplePartsAreRenderedCorrectly() {
212 val parts = PartContainer()
213 parts.add(PlainTextPart("te"))
214 parts.add(PlainTextPart("xt"))
215 assertThat(renderParts(parts), `is`("text"))
219 fun freemailAddressIsDisplayedCorrectly() {
220 val linkNode = renderParts(FreemailPart("sone", FREEMAIL_ID, SONE_IDENTITY)).toLinkNode()
221 verifyLink(linkNode, "/Freemail/NewMessage?to=$SONE_IDENTITY", "in-sone", "First\n$SONE_FREEMAIL", "sone@First.freemail")