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