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