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