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