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 `plain text part is rendered correctly`() {
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 `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 …"))
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 …"))
76 fun `short parts are not shortened`() {
77 setLengthAndCutOffLength(15, 10)
78 assertThat(renderParts(PlainTextPart("This.")), `is`("This."))
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 …"))
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 …"))
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.")
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 …"))
106 private fun setLengthAndCutOffLength(length: Int, cutOffLength: Int) {
107 parameters.put("length", length)
108 parameters.put("cut-off-length", cutOffLength)
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
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 `additional sone parts are ignored`() {
123 setLengthAndCutOffLength(15, 10)
124 assertThat(renderParts(PlainTextPart("This is a long text."), SonePart(sone)), `is`("This is a …"))
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")
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 `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")
149 private fun String.toLinkNode() = Jsoup.parseBodyFragment(this).body().child(0)
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")
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")
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 `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)
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…")
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 `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…")
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")
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"))
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")