Add test for DI constructability of ViewSonePage
[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.getInstance
8 import net.pterodactylus.sone.test.isOnPage
9 import net.pterodactylus.sone.test.mock
10 import net.pterodactylus.sone.test.whenever
11 import net.pterodactylus.sone.utils.Pagination
12 import net.pterodactylus.sone.utils.asOptional
13 import net.pterodactylus.sone.web.baseInjector
14 import org.hamcrest.MatcherAssert.assertThat
15 import org.hamcrest.Matchers.contains
16 import org.hamcrest.Matchers.equalTo
17 import org.hamcrest.Matchers.notNullValue
18 import org.hamcrest.Matchers.nullValue
19 import org.junit.Before
20 import org.junit.Test
21
22 /**
23  * Unit test for [ViewSonePage].
24  */
25 class ViewSonePageTest: WebPageTest(::ViewSonePage) {
26
27         init {
28                 whenever(currentSone.id).thenReturn("sone-id")
29         }
30
31         private val post1 = createPost("post1", "First Post.", 1000, currentSone)
32         private val post2 = createPost("post2", "Second Post.", 2000, currentSone)
33         private val foreignPost1 = createPost("foreign-post1", "First Foreign Post.", 1000, mock<Sone>())
34         private val foreignPost2 = createPost("foreign-post2", "Second Foreign Post.", 2000, mock<Sone>())
35         private val foreignPost3 = createPost("foreign-post3", "Third Foreign Post.", 3000, mock<Sone>())
36         private val directed1 = createPost("post3", "First directed.", 1500, mock<Sone>(), recipient = currentSone)
37         private val directed2 = createPost("post4", "Second directed.", 2500, mock<Sone>(), recipient = currentSone)
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         @Test
211         fun `page can be created by dependency injection`() {
212             assertThat(baseInjector.getInstance<ViewSonePage>(), notNullValue())
213         }
214
215 }