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