Add and improve tests for view Sone page
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / pages / ViewSonePageTest.kt
1 package net.pterodactylus.sone.web.pages
2
3 import net.pterodactylus.sone.data.Post
4 import net.pterodactylus.sone.data.PostReply
5 import net.pterodactylus.sone.data.Profile
6 import net.pterodactylus.sone.data.Sone
7 import net.pterodactylus.sone.test.isOnPage
8 import net.pterodactylus.sone.test.mock
9 import net.pterodactylus.sone.test.whenever
10 import net.pterodactylus.sone.utils.Pagination
11 import net.pterodactylus.sone.utils.asOptional
12 import org.hamcrest.MatcherAssert.assertThat
13 import org.hamcrest.Matchers.contains
14 import org.hamcrest.Matchers.equalTo
15 import org.hamcrest.Matchers.nullValue
16 import org.junit.Before
17 import org.junit.Test
18
19 /**
20  * Unit test for [ViewSonePage].
21  */
22 class ViewSonePageTest: WebPageTest() {
23
24         init {
25                 whenever(currentSone.id).thenReturn("sone-id")
26         }
27
28         private val page = ViewSonePage(template, webInterface)
29         private val post1 = createPost("post1", "First Post.", 1000, currentSone)
30         private val post2 = createPost("post2", "Second Post.", 2000, currentSone)
31         private val foreignPost1 = createPost("foreign-post1", "First Foreign Post.", 1000, mock<Sone>())
32         private val foreignPost2 = createPost("foreign-post2", "Second Foreign Post.", 2000, mock<Sone>())
33         private val foreignPost3 = createPost("foreign-post3", "Third Foreign Post.", 3000, mock<Sone>())
34         private val directed1 = createPost("post3", "First directed.", 1500, mock<Sone>(), recipient = currentSone)
35         private val directed2 = createPost("post4", "Second directed.", 2500, mock<Sone>(), recipient = currentSone)
36
37         override fun getPage() = page
38
39         @Before
40         fun setup() {
41                 whenever(currentSone.posts).thenReturn(mutableListOf(post2, post1))
42                 whenever(core.getDirectedPosts("sone-id")).thenReturn(setOf(directed1, directed2))
43                 core.preferences.postsPerPage = 2
44         }
45
46         @Test
47         fun `page returns correct path`() {
48                 assertThat(page.path, equalTo("viewSone.html"))
49         }
50
51         @Test
52         fun `page does not require login`() {
53                 assertThat(page.requiresLogin(), equalTo(false))
54         }
55
56         @Test
57         fun `get request without sone parameter stores null in template context`() {
58                 verifyNoRedirect {
59                         assertThat(templateContext["sone"], nullValue())
60                         assertThat(templateContext["soneId"], equalTo<Any>(""))
61                 }
62         }
63
64         @Test
65         fun `get request with invalid sone parameter stores null in template context`() {
66                 addHttpRequestParameter("sone", "invalid-sone-id")
67                 verifyNoRedirect {
68                         assertThat(templateContext["sone"], nullValue())
69                         assertThat(templateContext["soneId"], equalTo<Any>("invalid-sone-id"))
70                 }
71         }
72
73         @Test
74         fun `get request with valid sone parameter stores sone in template context`() {
75                 whenever(currentSone.posts).thenReturn(mutableListOf())
76                 whenever(core.getDirectedPosts("sone-id")).thenReturn(emptyList())
77                 addHttpRequestParameter("sone", "sone-id")
78                 addSone("sone-id", currentSone)
79                 verifyNoRedirect {
80                         assertThat(templateContext["sone"], equalTo<Any>(currentSone))
81                         assertThat(templateContext["soneId"], equalTo<Any>("sone-id"))
82                 }
83         }
84
85         private fun createPost(id: String, text: String, time: Long, sender: Sone? = null, recipient: Sone? = null) = mock<Post>().apply {
86                 whenever(this.id).thenReturn(id)
87                 sender?.run { whenever(this@apply.sone).thenReturn(this) }
88                 val recipientId = recipient?.id
89                 whenever(this.recipientId).thenReturn(recipientId.asOptional())
90                 whenever(this.recipient).thenReturn(recipient.asOptional())
91                 whenever(this.time).thenReturn(time)
92                 whenever(this.text).thenReturn(text)
93         }
94
95         @Test
96         @Suppress("UNCHECKED_CAST")
97         fun `request with valid sone stores posts and directed posts in template context`() {
98                 addSone("sone-id", currentSone)
99                 addHttpRequestParameter("sone", "sone-id")
100                 verifyNoRedirect {
101                         assertThat(templateContext["posts"] as Iterable<Post>, contains(directed2, post2))
102                         assertThat(templateContext["postPagination"] as Pagination<Post>, isOnPage(0).hasPages(2))
103                 }
104         }
105
106         @Test
107         @Suppress("UNCHECKED_CAST")
108         fun `second page of posts is shown correctly`() {
109                 addSone("sone-id", currentSone)
110                 addHttpRequestParameter("sone", "sone-id")
111                 addHttpRequestParameter("postPage", "1")
112                 verifyNoRedirect {
113                         assertThat(templateContext["posts"] as Iterable<Post>, contains(directed1, post1))
114                         assertThat(templateContext["postPagination"] as Pagination<Post>, isOnPage(1).hasPages(2))
115                 }
116         }
117
118         private fun createReply(text: String, time: Long, post: Post?) = mock<PostReply>().apply {
119                 whenever(this.text).thenReturn(text)
120                 whenever(this.time).thenReturn(time)
121                 whenever(this.post).thenReturn(post.asOptional())
122         }
123
124         @Test
125         @Suppress("UNCHECKED_CAST")
126         fun `replies are shown correctly`() {
127                 val reply1 = createReply("First Reply", 1500, foreignPost1)
128                 val reply2 = createReply("Second Reply", 2500, foreignPost2)
129                 val reply3 = createReply("Third Reply", 1750, post1)
130                 val reply4 = createReply("Fourth Reply", 2250, post2)
131                 val reply5 = createReply("Fifth Reply", 1600, post1)
132                 val reply6 = createReply("Sixth Reply", 2100, directed1)
133                 val reply7 = createReply("Seventh Reply", 2200, null)
134                 val reply8 = createReply("Eigth Reply", 2300, foreignPost1)
135                 val reply9 = createReply("Ninth Reply", 2050, foreignPost3)
136                 whenever(currentSone.replies).thenReturn(setOf(reply1, reply2, reply3, reply4, reply5, reply6, reply7, reply8, reply9))
137                 whenever(core.getReplies("post1")).thenReturn(listOf(reply3, reply5))
138                 whenever(core.getReplies("post2")).thenReturn(listOf(reply4))
139                 whenever(core.getReplies("foreign-post1")).thenReturn(listOf(reply8, reply1))
140                 whenever(core.getReplies("foreign-post2")).thenReturn(listOf(reply2))
141                 whenever(core.getReplies("post3")).thenReturn(listOf(reply6))
142                 whenever(core.getReplies("foreign-post3")).thenReturn(listOf(reply9))
143                 addSone("sone-id", currentSone)
144                 addHttpRequestParameter("sone", "sone-id")
145                 verifyNoRedirect {
146                         assertThat(templateContext["repliedPosts"] as Iterable<Post>, contains(foreignPost2, foreignPost1))
147                         assertThat(templateContext["repliedPostPagination"] as Pagination<Post>, isOnPage(0).hasPages(2))
148                 }
149         }
150
151         @Test
152         @Suppress("UNCHECKED_CAST")
153         fun `second page of replies is shown correctly`() {
154                 val reply1 = createReply("First Reply", 1500, foreignPost1)
155                 val reply2 = createReply("Second Reply", 2500, foreignPost2)
156                 val reply3 = createReply("Third Reply", 1750, post1)
157                 val reply4 = createReply("Fourth Reply", 2250, post2)
158                 val reply5 = createReply("Fifth Reply", 1600, post1)
159                 val reply6 = createReply("Sixth Reply", 2100, directed1)
160                 val reply7 = createReply("Seventh Reply", 2200, null)
161                 val reply8 = createReply("Eigth Reply", 2300, foreignPost1)
162                 val reply9 = createReply("Ninth Reply", 2050, foreignPost3)
163                 whenever(currentSone.replies).thenReturn(setOf(reply1, reply2, reply3, reply4, reply5, reply6, reply7, reply8, reply9))
164                 whenever(core.getReplies("post1")).thenReturn(listOf(reply3, reply5))
165                 whenever(core.getReplies("post2")).thenReturn(listOf(reply4))
166                 whenever(core.getReplies("foreign-post1")).thenReturn(listOf(reply8, reply1))
167                 whenever(core.getReplies("foreign-post2")).thenReturn(listOf(reply2))
168                 whenever(core.getReplies("post3")).thenReturn(listOf(reply6))
169                 whenever(core.getReplies("foreign-post3")).thenReturn(listOf(reply9))
170                 addSone("sone-id", currentSone)
171                 addHttpRequestParameter("sone", "sone-id")
172                 addHttpRequestParameter("repliedPostPage", "1")
173                 verifyNoRedirect {
174                         assertThat(templateContext["repliedPosts"] as Iterable<Post>, contains(foreignPost3))
175                         assertThat(templateContext["repliedPostPagination"] as Pagination<Post>, isOnPage(1).hasPages(2))
176                 }
177         }
178
179         @Test
180         fun `page title is default for request without parameters`() {
181                 addTranslation("Page.ViewSone.Page.TitleWithoutSone", "view sone page without sone")
182                 assertThat(page.getPageTitle(freenetRequest), equalTo("view sone page without sone"))
183         }
184
185         @Test
186         fun `page title is default for request with invalid sone parameters`() {
187                 addHttpRequestParameter("sone", "invalid-sone-id")
188                 addTranslation("Page.ViewSone.Page.TitleWithoutSone", "view sone page without sone")
189                 assertThat(page.getPageTitle(freenetRequest), equalTo("view sone page without sone"))
190         }
191
192         @Test
193         fun `page title contains sone name for request with sone parameters`() {
194                 addHttpRequestParameter("sone", "sone-id")
195                 addSone("sone-id", currentSone)
196                 whenever(currentSone.profile).thenReturn(Profile(currentSone).apply {
197                         firstName = "First"
198                         middleName = "M."
199                         lastName = "Last"
200                 })
201                 addTranslation("Page.ViewSone.Title", "view sone page")
202                 assertThat(page.getPageTitle(freenetRequest), equalTo("First M. Last - view sone page"))
203         }
204
205         @Test
206         fun `page is link-excepted`() {
207                 assertThat(page.isLinkExcepted(null), equalTo(true))
208         }
209
210 }