♻️ Use SoneRequest instead of FreenetRequest
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / pages / OptionsPageTest.kt
1 package net.pterodactylus.sone.web.pages
2
3 import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions
4 import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.FOLLOWED
5 import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent.TRUSTED
6 import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.ALWAYS
7 import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.NO
8 import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.WRITING
9 import net.pterodactylus.sone.test.getInstance
10 import net.pterodactylus.sone.test.whenever
11 import net.pterodactylus.sone.web.baseInjector
12 import net.pterodactylus.util.web.Method.POST
13 import org.hamcrest.MatcherAssert.assertThat
14 import org.hamcrest.Matchers.equalTo
15 import org.hamcrest.Matchers.hasItem
16 import org.hamcrest.Matchers.notNullValue
17 import org.hamcrest.Matchers.nullValue
18 import org.junit.Before
19 import org.junit.Test
20
21 /**
22  * Unit test for [OptionsPage].
23  */
24 class OptionsPageTest: WebPageTest(::OptionsPage) {
25
26         @Before
27         fun setupPreferences() {
28                 core.preferences.newInsertionDelay = 1
29                 core.preferences.newCharactersPerPost = 50
30                 core.preferences.newFcpFullAccessRequired = WRITING
31                 core.preferences.newImagesPerPage = 4
32                 core.preferences.newFcpInterfaceActive = true
33                 core.preferences.newRequireFullAccess = true
34                 core.preferences.newNegativeTrust = 7
35                 core.preferences.newPositiveTrust = 8
36                 core.preferences.newPostCutOffLength = 51
37                 core.preferences.newPostsPerPage = 10
38                 core.preferences.newTrustComment = "11"
39         }
40
41         @Before
42         fun setupSoneOptions() {
43                 whenever(currentSone.options).thenReturn(DefaultSoneOptions().apply {
44                         isAutoFollow = true
45                         isShowNewPostNotifications = true
46                         isShowNewReplyNotifications = true
47                         isShowNewSoneNotifications = true
48                         isSoneInsertNotificationEnabled = true
49                         loadLinkedImages = FOLLOWED
50                         showCustomAvatars = FOLLOWED
51                 })
52         }
53
54         @Test
55         fun `page returns correct path`() {
56                 assertThat(page.path, equalTo("options.html"))
57         }
58
59         @Test
60         fun `page does not require login`() {
61                 assertThat(page.requiresLogin(), equalTo(false))
62         }
63
64         @Test
65         fun `page returns correct title`() {
66                 addTranslation("Page.Options.Title", "options page title")
67                 assertThat(page.getPageTitle(soneRequest), equalTo("options page title"))
68         }
69
70         @Test
71         fun `get request stores all preferences in the template context`() {
72                 verifyNoRedirect {
73                         assertThat(templateContext["auto-follow"], equalTo<Any>(true))
74                         assertThat(templateContext["show-notification-new-sones"], equalTo<Any>(true))
75                         assertThat(templateContext["show-notification-new-posts"], equalTo<Any>(true))
76                         assertThat(templateContext["show-notification-new-replies"], equalTo<Any>(true))
77                         assertThat(templateContext["enable-sone-insert-notifications"], equalTo<Any>(true))
78                         assertThat(templateContext["load-linked-images"], equalTo<Any>("FOLLOWED"))
79                         assertThat(templateContext["show-custom-avatars"], equalTo<Any>("FOLLOWED"))
80                         assertThat(templateContext["insertion-delay"], equalTo<Any>(1))
81                         assertThat(templateContext["characters-per-post"], equalTo<Any>(50))
82                         assertThat(templateContext["fcp-full-access-required"], equalTo<Any>(1))
83                         assertThat(templateContext["images-per-page"], equalTo<Any>(4))
84                         assertThat(templateContext["fcp-interface-active"], equalTo<Any>(true))
85                         assertThat(templateContext["require-full-access"], equalTo<Any>(true))
86                         assertThat(templateContext["negative-trust"], equalTo<Any>(7))
87                         assertThat(templateContext["positive-trust"], equalTo<Any>(8))
88                         assertThat(templateContext["post-cut-off-length"], equalTo<Any>(51))
89                         assertThat(templateContext["posts-per-page"], equalTo<Any>(10))
90                         assertThat(templateContext["trust-comment"], equalTo<Any>("11"))
91                 }
92         }
93
94         @Test
95         fun `get request without sone does not store sone-specific preferences in the template context`() {
96                 unsetCurrentSone()
97                 verifyNoRedirect {
98                         assertThat(templateContext["auto-follow"], nullValue())
99                         assertThat(templateContext["show-notification-new-sones"], nullValue())
100                         assertThat(templateContext["show-notification-new-posts"], nullValue())
101                         assertThat(templateContext["show-notification-new-replies"], nullValue())
102                         assertThat(templateContext["enable-sone-insert-notifications"], nullValue())
103                         assertThat(templateContext["load-linked-images"], nullValue())
104                         assertThat(templateContext["show-custom-avatars"], nullValue())
105                 }
106         }
107
108         private fun <T> verifyThatOptionCanBeSet(option: String, setValue: Any?, expectedValue: T, getter: () -> T) {
109                 setMethod(POST)
110                 addHttpRequestPart("show-custom-avatars", "ALWAYS")
111                 addHttpRequestPart("load-linked-images", "ALWAYS")
112                 setValue?.also { addHttpRequestPart(option, it.toString()) }
113                 verifyRedirect("options.html") {
114                         assertThat(getter(), equalTo(expectedValue))
115                 }
116         }
117
118         @Test
119         fun `auto-follow option can be set`() {
120                 verifyThatOptionCanBeSet("auto-follow", "checked", true) { currentSone.options.isAutoFollow }
121         }
122
123         @Test
124         fun `auto-follow option can be unset`() {
125                 verifyThatOptionCanBeSet("auto-follow", null, false) { currentSone.options.isAutoFollow }
126         }
127
128         @Test
129         fun `show new sone notification option can be set`() {
130                 verifyThatOptionCanBeSet("show-notification-new-sones", "checked", true) { currentSone.options.isShowNewSoneNotifications }
131         }
132
133         @Test
134         fun `show new sone notification option can be unset`() {
135                 verifyThatOptionCanBeSet("" +
136                                 "", null, false) { currentSone.options.isShowNewSoneNotifications }
137         }
138
139         @Test
140         fun `show new post notification option can be set`() {
141                 verifyThatOptionCanBeSet("show-notification-new-posts", "checked", true) { currentSone.options.isShowNewPostNotifications }
142         }
143
144         @Test
145         fun `show new post notification option can be unset`() {
146                 verifyThatOptionCanBeSet("show-notification-new-posts", null, false) { currentSone.options.isShowNewPostNotifications }
147         }
148
149         @Test
150         fun `show new reply notification option can be set`() {
151                 verifyThatOptionCanBeSet("show-notification-new-replies", "checked", true) { currentSone.options.isShowNewReplyNotifications }
152         }
153
154         @Test
155         fun `show new reply notification option can be unset`() {
156                 verifyThatOptionCanBeSet("show-notification-new-replies", null, false) { currentSone.options.isShowNewReplyNotifications }
157         }
158
159         @Test
160         fun `enable sone insert notifications option can be set`() {
161                 verifyThatOptionCanBeSet("enable-sone-insert-notifications", "checked", true) { currentSone.options.isSoneInsertNotificationEnabled }
162         }
163
164         @Test
165         fun `enable sone insert notifications option can be unset`() {
166                 verifyThatOptionCanBeSet("enable-sone-insert-notifications", null, false) { currentSone.options.isSoneInsertNotificationEnabled }
167         }
168
169         @Test
170         fun `load linked images option can be set`() {
171                 verifyThatOptionCanBeSet("load-linked-images", "TRUSTED", TRUSTED) { currentSone.options.loadLinkedImages }
172         }
173
174         @Test
175         fun `show custom avatar option can be set`() {
176                 verifyThatOptionCanBeSet("show-custom-avatars", "TRUSTED", TRUSTED) { currentSone.options.showCustomAvatars }
177         }
178
179         private fun verifyThatWrongValueForPreferenceIsDetected(name: String, value: String) {
180                 unsetCurrentSone()
181                 setMethod(POST)
182                 addHttpRequestPart(name, value)
183                 verifyNoRedirect {
184                         assertThat(templateContext["fieldErrors"] as Iterable<*>, hasItem(name))
185                 }
186         }
187
188         private fun <T> verifyThatPreferencesCanBeSet(name: String, setValue: String?, expectedValue: T, getter: () -> T) {
189                 unsetCurrentSone()
190                 setMethod(POST)
191                 setValue?.also { addHttpRequestPart(name, it) }
192                 verifyRedirect("options.html") {
193                         assertThat(getter(), equalTo(expectedValue))
194                 }
195         }
196
197         @Test
198         fun `insertion delay can not be set to less than 0 seconds`() {
199                 verifyThatWrongValueForPreferenceIsDetected("insertion-delay", "-1")
200         }
201
202         @Test
203         fun `insertion delay can be set to 0 seconds`() {
204                 verifyThatPreferencesCanBeSet("insertion-delay", "0", 0) { core.preferences.insertionDelay }
205         }
206
207         @Test
208         fun `setting insertion to an invalid value will reset it`() {
209                 verifyThatPreferencesCanBeSet("insertion-delay", "foo", 60) { core.preferences.insertionDelay }
210         }
211
212         @Test
213         fun `characters per post can not be set to less than -1`() {
214                 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "-2")
215         }
216
217         @Test
218         fun `characters per post can be set to -1`() {
219                 verifyThatPreferencesCanBeSet("characters-per-post", "-1", -1) { core.preferences.charactersPerPost }
220         }
221
222         @Test
223         fun `characters per post can not be set to 0`() {
224                 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "0")
225         }
226
227         @Test
228         fun `characters per post can not be set to 49`() {
229                 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "49")
230         }
231
232         @Test
233         fun `characters per post can be set to 50`() {
234                 verifyThatPreferencesCanBeSet("characters-per-post", "50", 50) { core.preferences.charactersPerPost }
235         }
236
237         @Test
238         fun `fcp full acess required option can be set to always`() {
239                 verifyThatPreferencesCanBeSet("fcp-full-access-required", "2", ALWAYS) { core.preferences.fcpFullAccessRequired }
240         }
241
242         @Test
243         fun `fcp full acess required option can be set to writing`() {
244                 verifyThatPreferencesCanBeSet("fcp-full-access-required", "1", WRITING) { core.preferences.fcpFullAccessRequired }
245         }
246
247         @Test
248         fun `fcp full acess required option can be set to no`() {
249                 verifyThatPreferencesCanBeSet("fcp-full-access-required", "0", NO) { core.preferences.fcpFullAccessRequired }
250         }
251
252         @Test
253         fun `fcp full acess required option is not changed if invalid value is set`() {
254                 verifyThatPreferencesCanBeSet("fcp-full-access-required", "foo", WRITING) { core.preferences.fcpFullAccessRequired }
255         }
256
257         @Test
258         fun `images per page can not be set to 0`() {
259                 verifyThatWrongValueForPreferenceIsDetected("images-per-page", "0")
260         }
261
262         @Test
263         fun `images per page can be set to 1`() {
264                 verifyThatPreferencesCanBeSet("images-per-page", "1", 1) { core.preferences.imagesPerPage }
265         }
266
267         @Test
268         fun `images per page is set to 9 if invalid value is requested`() {
269                 verifyThatPreferencesCanBeSet("images-per-page", "foo", 9) { core.preferences.imagesPerPage }
270         }
271
272         @Test
273         fun `fcp interface can be set to true`() {
274                 verifyThatPreferencesCanBeSet("fcp-interface-active", "checked", true) { core.preferences.fcpInterfaceActive }
275         }
276
277         @Test
278         fun `fcp interface can be set to false`() {
279                 verifyThatPreferencesCanBeSet("fcp-interface-active", null, false) { core.preferences.fcpInterfaceActive }
280         }
281
282         @Test
283         fun `require full access can be set to true`() {
284                 verifyThatPreferencesCanBeSet("require-full-access", "checked", true) { core.preferences.requireFullAccess }
285         }
286
287         @Test
288         fun `require full access can be set to false`() {
289                 verifyThatPreferencesCanBeSet("require-full-access", null, false) { core.preferences.requireFullAccess }
290         }
291
292         @Test
293         fun `negative trust can not be set to -101`() {
294                 verifyThatWrongValueForPreferenceIsDetected("negative-trust", "-101")
295         }
296
297         @Test
298         fun `negative trust can be set to -100`() {
299                 verifyThatPreferencesCanBeSet("negative-trust", "-100", -100) { core.preferences.negativeTrust }
300         }
301
302         @Test
303         fun `negative trust can be set to 100`() {
304                 verifyThatPreferencesCanBeSet("negative-trust", "100", 100) { core.preferences.negativeTrust }
305         }
306
307         @Test
308         fun `negative trust can not be set to 101`() {
309                 verifyThatWrongValueForPreferenceIsDetected("negative-trust", "101")
310         }
311
312         @Test
313         fun `negative trust is set to default on invalid value`() {
314                 verifyThatPreferencesCanBeSet("negative-trust", "invalid", -25) { core.preferences.negativeTrust }
315         }
316
317         @Test
318         fun `positive trust can not be set to -1`() {
319                 verifyThatWrongValueForPreferenceIsDetected("positive-trust", "-1")
320         }
321
322         @Test
323         fun `positive trust can be set to 0`() {
324                 verifyThatPreferencesCanBeSet("positive-trust", "0", 0) { core.preferences.positiveTrust }
325         }
326
327         @Test
328         fun `positive trust can be set to 100`() {
329                 verifyThatPreferencesCanBeSet("positive-trust", "100", 100) { core.preferences.positiveTrust }
330         }
331
332         @Test
333         fun `positive trust can not be set to 101`() {
334                 verifyThatWrongValueForPreferenceIsDetected("positive-trust", "101")
335         }
336
337         @Test
338         fun `positive trust is set to default on invalid value`() {
339                 verifyThatPreferencesCanBeSet("positive-trust", "invalid", 75) { core.preferences.positiveTrust }
340         }
341
342         @Test
343         fun `post cut off length can not be set to -49`() {
344                 verifyThatWrongValueForPreferenceIsDetected("post-cut-off-length", "-49")
345         }
346
347         @Test
348         fun `post cut off length can be set to 50`() {
349                 verifyThatPreferencesCanBeSet("post-cut-off-length", "50", 50) { core.preferences.postCutOffLength }
350         }
351
352         @Test
353         fun `post cut off length is set to default on invalid value`() {
354                 verifyThatPreferencesCanBeSet("post-cut-off-length", "invalid", 200) { core.preferences.postCutOffLength }
355         }
356
357         @Test
358         fun `posts per page can not be set to 0`() {
359                 verifyThatWrongValueForPreferenceIsDetected("posts-per-page", "-49")
360         }
361
362         @Test
363         fun `posts per page can be set to 1`() {
364                 verifyThatPreferencesCanBeSet("posts-per-page", "1", 1) { core.preferences.postsPerPage }
365         }
366
367         @Test
368         fun `posts per page is set to default on invalid value`() {
369                 verifyThatPreferencesCanBeSet("posts-per-page", "invalid", 10) { core.preferences.postsPerPage }
370         }
371
372         @Test
373         fun `trust comment can be set`() {
374                 verifyThatPreferencesCanBeSet("trust-comment", "trust", "trust") { core.preferences.trustComment }
375         }
376
377         @Test
378         fun `trust comment is set to default when set to empty value`() {
379                 verifyThatPreferencesCanBeSet("trust-comment", "", "Set from Sone Web Interface") { core.preferences.trustComment }
380         }
381
382         @Test
383         fun `page can be created by dependency injection`() {
384             assertThat(baseInjector.getInstance<OptionsPage>(), notNullValue())
385         }
386
387 }