2eb77e2dfbd43ea44aa9a7662e10ae7c4d6e9b86
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / pages / SoneTemplatePageTest.kt
1 package net.pterodactylus.sone.web.pages
2
3 import net.pterodactylus.sone.data.Sone
4 import net.pterodactylus.sone.main.SonePlugin
5 import net.pterodactylus.sone.test.mock
6 import net.pterodactylus.sone.test.whenever
7 import net.pterodactylus.sone.web.page.FreenetRequest
8 import net.pterodactylus.util.notify.Notification
9 import net.pterodactylus.util.template.TemplateContext
10 import net.pterodactylus.util.version.Version
11 import net.pterodactylus.util.web.Method.GET
12 import org.hamcrest.Matcher
13 import org.hamcrest.MatcherAssert.assertThat
14 import org.hamcrest.Matchers.anyOf
15 import org.hamcrest.Matchers.contains
16 import org.hamcrest.Matchers.containsInAnyOrder
17 import org.hamcrest.Matchers.equalTo
18 import org.hamcrest.Matchers.nullValue
19 import org.junit.Test
20 import org.mockito.Mockito.verify
21
22 /**
23  * Unit test for [SoneTemplatePage].
24  */
25 class SoneTemplatePageTest : WebPageTest() {
26
27         private val preferences by lazy { core.preferences!! }
28         private val page = object : SoneTemplatePage("path.html", template, webInterface, true) {}
29
30         @Test
31         fun `current sone is retrieved from web interface`() {
32                 assertThat(page.getCurrentSone(toadletContext), equalTo(currentSone))
33         }
34
35         @Test
36         fun `retrieving current sone without creation is forwarded to web interface`() {
37                 mock<Sone>().let {
38                         whenever(webInterface.getCurrentSone(toadletContext, false)).thenReturn(it)
39                         assertThat(page.getCurrentSone(toadletContext, false), equalTo(it))
40                 }
41         }
42
43         @Test
44         fun `setting the current sone is forwarded to web interface`() {
45                 mock<Sone>().let {
46                         page.setCurrentSone(toadletContext, it)
47                         verify(webInterface).setCurrentSone(toadletContext, it)
48                 }
49         }
50
51         @Test
52         fun `page title is empty string if no page title key was given`() {
53                 SoneTemplatePage("path.html", template, null, webInterface).let { page ->
54                         assertThat(page.getPageTitle(freenetRequest), equalTo(""))
55                 }
56         }
57
58         @Test
59         fun `page title is retrieved from l10n if page title key is given`() {
60                 SoneTemplatePage("path.html", template, "page.title", webInterface).let { page ->
61                         whenever(l10n.getString("page.title")).thenReturn("Page Title")
62                         assertThat(page.getPageTitle(freenetRequest), equalTo("Page Title"))
63                 }
64         }
65
66         @Test
67         fun `additional link nodes contain open search link`() {
68                 addHttpRequestHeader("Host", "www.example.com")
69                 assertThat(page.getAdditionalLinkNodes(freenetRequest), contains(mapOf(
70                                 "rel" to "search",
71                                 "type" to "application/opensearchdescription+xml",
72                                 "title" to "Sone",
73                                 "href" to "http://www.example.com/Sone/OpenSearch.xml"
74                 )))
75         }
76
77         @Test
78         fun `style sheets contains sone CSS file`() {
79                 assertThat(page.styleSheets, contains("css/sone.css"))
80         }
81
82         @Test
83         fun `shortcut icon is the sone icon`() {
84                 assertThat(page.shortcutIcon, equalTo("images/icon.png"))
85         }
86
87         @Test
88         fun `page requires login if require login was specified in the constructor`() {
89                 SoneTemplatePage("path.html", template, webInterface, true).let { page ->
90                         assertThat(page.requiresLogin(), equalTo(true))
91                 }
92         }
93
94         @Test
95         fun `page does not require login if require login was not specified in the constructor`() {
96                 SoneTemplatePage("path.html", template, webInterface, false).let { page ->
97                         assertThat(page.requiresLogin(), equalTo(false))
98                 }
99         }
100
101         private fun verifyVariableIsSet(name: String, value: Any) = verifyVariableMatches(name, equalTo<Any>(value))
102
103         private fun <T> verifyVariableMatches(name: String, matcher: Matcher<T>) {
104                 page.processTemplate(freenetRequest, templateContext)
105                 @Suppress("UNCHECKED_CAST")
106                 assertThat(templateContext[name] as T, matcher)
107         }
108
109         @Test
110         fun `preferences are set in template context`() {
111             verifyVariableIsSet("preferences", preferences)
112         }
113
114         @Test
115         fun `current sone is set in template context`() {
116                 verifyVariableIsSet("currentSone", currentSone)
117         }
118
119         @Test
120         fun `local sones are set in template context`() {
121                 val localSones = listOf(mock<Sone>(), mock<Sone>())
122                 whenever(core.localSones).thenReturn(localSones)
123                 verifyVariableMatches("localSones", containsInAnyOrder(*localSones.toTypedArray()))
124         }
125
126         @Test
127         fun `freenet request is set in template context`() {
128                 verifyVariableIsSet("request", freenetRequest)
129         }
130
131         @Test
132         fun `current version is set in template context`() {
133                 verifyVariableIsSet("currentVersion", SonePlugin.getPluginVersion())
134         }
135
136         @Test
137         fun `has latest version is set correctly in template context if true`() {
138                 whenever(core.updateChecker.hasLatestVersion()).thenReturn(true)
139                 verifyVariableIsSet("hasLatestVersion", true)
140         }
141
142         @Test
143         fun `has latest version is set correctly in template context if false`() {
144                 whenever(core.updateChecker.hasLatestVersion()).thenReturn(false)
145                 verifyVariableIsSet("hasLatestVersion", false)
146         }
147
148         @Test
149         fun `latest edition is set in template context`() {
150                 whenever(core.updateChecker.latestEdition).thenReturn(1234L)
151                 verifyVariableIsSet("latestEdition", 1234L)
152         }
153
154         @Test
155         fun `latest version is set in template context`() {
156                 whenever(core.updateChecker.latestVersion).thenReturn(Version(1, 2, 3))
157                 verifyVariableIsSet("latestVersion", Version(1, 2, 3))
158         }
159
160         @Test
161         fun `latest version time is set in template context`() {
162                 whenever(core.updateChecker.latestVersionDate).thenReturn(12345L)
163                 verifyVariableIsSet("latestVersionTime", 12345L)
164         }
165
166         private fun createNotification(time: Long) = mock<Notification>().apply {
167                 whenever(createdTime).thenReturn(time)
168         }
169
170         @Test
171         fun `notifications are set in template context`() {
172                 val notifications = listOf(createNotification(3000), createNotification(1000), createNotification(2000))
173                 whenever(webInterface.getNotifications(currentSone)).thenReturn(notifications)
174                 verifyVariableMatches("notifications", contains(notifications[1], notifications[2], notifications[0]))
175         }
176
177         @Test
178         fun `notification hash is set in template context`() {
179                 val notifications = listOf(createNotification(3000), createNotification(1000), createNotification(2000))
180                 whenever(webInterface.getNotifications(currentSone)).thenReturn(notifications)
181                 verifyVariableIsSet("notificationHash", listOf(notifications[1], notifications[2], notifications[0]).hashCode())
182         }
183
184         @Test
185         fun `handleRequest method is called`() {
186                 var called = false
187                 val page = object : SoneTemplatePage("path.html", template, webInterface, true) {
188                         override fun handleRequest(request: FreenetRequest, templateContext: TemplateContext) {
189                                 called = true
190                         }
191                 }
192                 page.processTemplate(freenetRequest, templateContext)
193                 assertThat(called, equalTo(true))
194         }
195
196         @Test
197         fun `redirect does not happen if login is not required`() {
198                 val page = SoneTemplatePage("page.html", template, webInterface, false)
199                 assertThat(page.getRedirectTarget(freenetRequest), nullValue())
200         }
201
202         @Test
203         fun `redirect does not happen if sone is logged in`() {
204                 assertThat(page.getRedirectTarget(freenetRequest), nullValue())
205         }
206
207         @Test
208         fun `redirect does happen if sone is not logged in`() {
209                 unsetCurrentSone()
210                 request("index.html", GET)
211                 assertThat(page.getRedirectTarget(freenetRequest), equalTo("login.html?target=index.html"))
212         }
213
214         @Test
215         fun `redirect does happen with parameters encoded correctly if sone is not logged in`() {
216                 unsetCurrentSone()
217                 request("index.html", GET)
218                 addHttpRequestParameter("foo", "b=r")
219                 addHttpRequestParameter("baz", "q&o")
220                 assertThat(page.getRedirectTarget(freenetRequest), anyOf(
221                                 equalTo("login.html?target=index.html%3Ffoo%3Db%253Dr%26baz%3Dq%2526o"),
222                                 equalTo("login.html?target=index.html%3Fbaz%3Dq%2526o%26foo%3Db%253Dr")
223                 ))
224         }
225
226         @Test
227         fun `full access requirement is correctly forwarded from the preferences if false`() {
228                 assertThat(page.isFullAccessOnly, equalTo(false))
229         }
230
231         @Test
232         fun `full access requirement is correctly forwarded from the preferences if true`() {
233                 core.preferences.isRequireFullAccess = true
234                 assertThat(page.isFullAccessOnly, equalTo(true))
235         }
236
237         @Test
238         fun `page is disabled if full access is required but request does not have full access`() {
239                 core.preferences.isRequireFullAccess = true
240                 assertThat(page.isEnabled(toadletContext), equalTo(false))
241         }
242
243         @Test
244         fun `page is disabled if login is required but there is no current sone`() {
245                 unsetCurrentSone()
246                 assertThat(page.isEnabled(toadletContext), equalTo(false))
247         }
248
249         @Test
250         fun `page is enabled if login is required and there is a current sone`() {
251                 assertThat(page.isEnabled(toadletContext), equalTo(true))
252         }
253
254         @Test
255         fun `page is enabled if full access is required and request has full access and login is required and there is a current sone`() {
256                 core.preferences.isRequireFullAccess = true
257                 whenever(toadletContext.isAllowedFullAccess).thenReturn(true)
258                 assertThat(page.isEnabled(toadletContext), equalTo(true))
259         }
260
261         @Test
262         fun `page is enabled if no full access is required and login is not required`() {
263                 SoneTemplatePage("path.html", template, webInterface, false).let { page ->
264                         assertThat(page.isEnabled(toadletContext), equalTo(true))
265                 }
266         }
267
268 }