🚧 Add Loaders to all template-using pages
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / pages / IndexPageTest.kt
1 package net.pterodactylus.sone.web.pages
2
3 import com.google.common.base.Optional.fromNullable
4 import com.google.common.base.Predicate
5 import net.pterodactylus.sone.data.Post
6 import net.pterodactylus.sone.data.Sone
7 import net.pterodactylus.sone.notify.PostVisibilityFilter
8 import net.pterodactylus.sone.test.getInstance
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.web.baseInjector
13 import net.pterodactylus.sone.web.page.*
14 import org.hamcrest.MatcherAssert.assertThat
15 import org.hamcrest.Matchers.contains
16 import org.hamcrest.Matchers.emptyIterable
17 import org.hamcrest.Matchers.equalTo
18 import org.hamcrest.Matchers.notNullValue
19 import org.junit.Before
20 import org.junit.Test
21 import org.mockito.ArgumentMatchers
22
23 /**
24  * Unit test for [IndexPage].
25  */
26 class IndexPageTest: WebPageTest({ template, webInterface, loaders -> IndexPage(template, webInterface, loaders, postVisibilityFilter) }) {
27
28         companion object {
29                 private val postVisibilityFilter = mock<PostVisibilityFilter>()
30         }
31
32         @Test
33         fun `page returns correct path`() {
34             assertThat(page.path, equalTo("index.html"))
35         }
36
37         @Test
38         fun `page requires login`() {
39             assertThat(page.requiresLogin(), equalTo(true))
40         }
41
42         @Test
43         fun `page returns correct title`() {
44                 whenever(l10n.getString("Page.Index.Title")).thenReturn("index page title")
45             assertThat(page.getPageTitle(soneRequest), equalTo("index page title"))
46         }
47
48         @Before
49         fun setupPostVisibilityFilter() {
50                 whenever(postVisibilityFilter.isVisible(ArgumentMatchers.eq(currentSone))).thenReturn(Predicate<Post> { true })
51         }
52
53         @Before
54         fun setupCurrentSone() {
55                 whenever(currentSone.id).thenReturn("current")
56         }
57
58         @Before
59         fun setupDirectedPosts() {
60                 whenever(core.getDirectedPosts("current")).thenReturn(emptyList())
61         }
62
63         private fun createPost(time: Long, directed: Boolean = false) = mock<Post>().apply {
64                 whenever(this.time).thenReturn(time)
65                 whenever(recipient).thenReturn(fromNullable(if (directed) currentSone else null))
66         }
67
68         @Test
69         fun `index page shows all posts of current sone`() {
70                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
71                 whenever(currentSone.posts).thenReturn(posts)
72                 page.processTemplate(freenetRequest, templateContext)
73                 @Suppress("UNCHECKED_CAST")
74                 assertThat(templateContext["posts"] as Iterable<Post>, contains(*posts.toTypedArray()))
75         }
76
77         @Test
78         fun `index page shows posts directed at current sone from non-followed sones`() {
79                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
80                 whenever(currentSone.posts).thenReturn(posts)
81                 val notFollowedSone = mock<Sone>()
82                 val notFollowedPosts = listOf(createPost(2500, true), createPost(1500))
83                 whenever(notFollowedSone.posts).thenReturn(notFollowedPosts)
84                 addSone("notfollowed1", notFollowedSone)
85                 whenever(core.getDirectedPosts("current")).thenReturn(listOf(notFollowedPosts[0]))
86                 page.processTemplate(freenetRequest, templateContext)
87                 @Suppress("UNCHECKED_CAST")
88                 assertThat(templateContext["posts"] as Iterable<Post>, contains(
89                                 posts[0], notFollowedPosts[0], posts[1], posts[2]
90                 ))
91         }
92
93         @Test
94         fun `index page does not show duplicate posts`() {
95                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
96                 whenever(currentSone.posts).thenReturn(posts)
97                 val followedSone = mock<Sone>()
98                 val followedPosts = listOf(createPost(2500, true), createPost(1500))
99                 whenever(followedSone.posts).thenReturn(followedPosts)
100                 whenever(currentSone.friends).thenReturn(listOf("followed1", "followed2"))
101                 addSone("followed1", followedSone)
102                 page.processTemplate(freenetRequest, templateContext)
103                 @Suppress("UNCHECKED_CAST")
104                 assertThat(templateContext["posts"] as Iterable<Post>, contains(
105                                 posts[0], followedPosts[0], posts[1], followedPosts[1], posts[2]
106                 ))
107         }
108
109         @Test
110         fun `index page uses post visibility filter`() {
111                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
112                 whenever(currentSone.posts).thenReturn(posts)
113                 val followedSone = mock<Sone>()
114                 val followedPosts = listOf(createPost(2500, true), createPost(1500))
115                 whenever(followedSone.posts).thenReturn(followedPosts)
116                 whenever(currentSone.friends).thenReturn(listOf("followed1", "followed2"))
117                 whenever(postVisibilityFilter.isVisible(ArgumentMatchers.eq(currentSone))).thenReturn(Predicate<Post> { (it?.time ?: 10000) < 2500 })
118                 addSone("followed1", followedSone)
119                 page.processTemplate(freenetRequest, templateContext)
120                 @Suppress("UNCHECKED_CAST")
121                 assertThat(templateContext["posts"] as Iterable<Post>, contains(
122                                 posts[1], followedPosts[1], posts[2]
123                 ))
124         }
125
126         @Test
127         fun `index page sets pagination correctly`() {
128                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
129                 whenever(currentSone.posts).thenReturn(posts)
130                 page.processTemplate(freenetRequest, templateContext)
131                 @Suppress("UNCHECKED_CAST")
132                 assertThat((templateContext["pagination"] as Pagination<Post>).items, contains(
133                                 posts[0], posts[1], posts[2]
134                 ))
135         }
136
137         @Test
138         fun `index page sets page correctly`() {
139                 val posts = listOf(createPost(3000), createPost(2000), createPost(1000))
140                 whenever(currentSone.posts).thenReturn(posts)
141                 core.preferences.newPostsPerPage = 1
142                 addHttpRequestParameter("page", "2")
143                 page.processTemplate(freenetRequest, templateContext)
144                 @Suppress("UNCHECKED_CAST")
145                 assertThat((templateContext["pagination"] as Pagination<Post>).page, equalTo(2))
146         }
147
148         @Test
149         fun `index page without posts sets correct pagination`() {
150                 core.preferences.newPostsPerPage = 1
151                 page.processTemplate(freenetRequest, templateContext)
152                 @Suppress("UNCHECKED_CAST")
153                 (templateContext["pagination"] as Pagination<Post>).let { pagination ->
154                         assertThat(pagination.items, emptyIterable())
155                 }
156         }
157
158         @Test
159         fun `page can be created by dependency injection`() {
160             assertThat(baseInjector.getInstance<IndexPage>(), notNullValue())
161         }
162
163         @Test
164         fun `page is annotated with correct menuname`() {
165             assertThat(page.menuName, equalTo("Index"))
166         }
167
168 }