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