Rename test methods
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / template / RenderFilterTest.kt
1 package net.pterodactylus.sone.template
2
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
27 import org.junit.Test
28 import org.mockito.Mockito.`when`
29 import java.net.URLEncoder
30
31 /**
32  * Unit test for [RenderFilter].
33  */
34 class RenderFilterTest {
35
36         companion object {
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"
41         }
42
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?>()
48
49         init {
50                 templateContextFactory.addFilter("html", HtmlFilter())
51                 templateContext = templateContextFactory.createTemplateContext()
52         }
53
54         private val filter = RenderFilter(core, templateContextFactory)
55
56         @Test
57         fun `plain text part is rendered correctly`() {
58                 assertThat(renderParts(PlainTextPart("plain text")), `is`("plain text"))
59         }
60
61         private fun renderParts(vararg part: Part) = filter.format(templateContext, listOf(*part), parameters) as String
62
63         @Test
64         fun `plain text part is shortened if length exceeds maxl ength`() {
65                 setLengthAndCutOffLength(15, 10)
66                 assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a &hellip;"))
67         }
68
69         @Test
70         fun `plain text part is not shortened if length does not exceed max length`() {
71                 setLengthAndCutOffLength(20, 10)
72                 assertThat(renderParts(PlainTextPart("This is a long text.")), `is`("This is a &hellip;"))
73         }
74
75         @Test
76         fun `short parts are not shortened`() {
77                 setLengthAndCutOffLength(15, 10)
78                 assertThat(renderParts(PlainTextPart("This.")), `is`("This."))
79         }
80
81         @Test
82         fun `multiple plain text parts are shortened`() {
83                 setLengthAndCutOffLength(15, 10)
84                 assertThat(renderParts(PlainTextPart("This "), PlainTextPart("is a long text.")), `is`("This is a &hellip;"))
85         }
86
87         @Test
88         fun `parts after length has been reached are ignored`() {
89                 setLengthAndCutOffLength(15, 10)
90                 assertThat(renderParts(PlainTextPart("This is a long text."), PlainTextPart(" And even more.")), `is`("This is a &hellip;"))
91         }
92
93         @Test
94         fun `link parts are not shortened`() {
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.")
98         }
99
100         @Test
101         fun `additional link parts are ignored`() {
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 &hellip;"))
104         }
105
106         private fun setLengthAndCutOffLength(length: Int, cutOffLength: Int) {
107                 parameters.put("length", length)
108                 parameters.put("cut-off-length", cutOffLength)
109         }
110
111         @Test
112         fun `sone parts are added but their length is ignored`() {
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
116                 println(linkNode)
117                 verifyLink(linkNode, "viewSone.html?sone=$SONE_IDENTITY", "in-sone", "First", "First")
118                 assertThat((body.childNode(1) as TextNode).text(), `is`("This is a …"))
119         }
120
121         @Test
122         fun `additional sone parts are ignored`() {
123                 setLengthAndCutOffLength(15, 10)
124                 assertThat(renderParts(PlainTextPart("This is a long text."), SonePart(sone)), `is`("This is a &hellip;"))
125         }
126
127         @Test
128         fun `freenet link is rendered correctly`() {
129                 val linkNode = renderParts(FreenetLinkPart("KSK@gpl.txt", "gpl.txt", false)).toLinkNode()
130                 verifyLink(linkNode, "/KSK@gpl.txt", "freenet", "KSK@gpl.txt", "gpl.txt")
131         }
132
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)
139                 ))
140                 assertThat(linkNode.text(), `is`(text))
141         }
142
143         @Test
144         fun `trusted freenet link is rendered with correct css class`() {
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")
147         }
148
149         private fun String.toLinkNode() = Jsoup.parseBodyFragment(this).body().child(0)
150
151         @Test
152         fun `internet link is rendered correctly`() {
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")
156         }
157
158         @Test
159         fun `sone parts are rendered correctly`() {
160                 val linkNode = renderParts(SonePart(sone)).toLinkNode()
161                 verifyLink(linkNode, "viewSone.html?sone=" + SONE_IDENTITY, "in-sone", "First", "First")
162         }
163
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))
171                 return sone
172         }
173
174         @Test
175         fun `sone part with unknown sone is rendered as link to web of trust`() {
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)
179         }
180
181         @Test
182         fun `post part is cut off correctly when there are spaces`() {
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…")
186         }
187
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)
193                 return post
194         }
195
196         @Test
197         fun `post part is cut off correctly when there are no spaces`() {
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…")
201         }
202
203         @Test
204         fun `post part shorter than 21 chars is not cut off`() {
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")
208         }
209
210         @Test
211         fun `multiple parts are rendered correctly`() {
212                 val parts = PartContainer()
213                 parts.add(PlainTextPart("te"))
214                 parts.add(PlainTextPart("xt"))
215                 assertThat(renderParts(parts), `is`("text"))
216         }
217
218         @Test
219         fun `freemail address is displayed correctly`() {
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")
222         }
223
224 }