1 package net.pterodactylus.sone.web.pages
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.*
16 * Unit test for [OptionsPage].
18 class OptionsPageTest : WebPageTest(::OptionsPage) {
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 core.preferences.newStrictFiltering = true
34 fun setupSoneOptions() {
35 whenever(currentSone.options).thenReturn(DefaultSoneOptions().apply {
37 isShowNewPostNotifications = true
38 isShowNewReplyNotifications = true
39 isShowNewSoneNotifications = true
40 isSoneInsertNotificationEnabled = true
41 loadLinkedImages = FOLLOWED
42 showCustomAvatars = FOLLOWED
47 fun `page returns correct path`() {
48 assertThat(page.path, equalTo("options.html"))
52 fun `page does not require login`() {
53 assertThat(page.requiresLogin(), equalTo(false))
57 fun `page returns correct title`() {
58 addTranslation("Page.Options.Title", "options page title")
59 assertThat(page.getPageTitle(soneRequest), equalTo("options page title"))
63 fun `get request stores all preferences in the template context`() {
65 assertThat(templateContext["auto-follow"], equalTo<Any>(true))
66 assertThat(templateContext["show-notification-new-sones"], equalTo<Any>(true))
67 assertThat(templateContext["show-notification-new-posts"], equalTo<Any>(true))
68 assertThat(templateContext["show-notification-new-replies"], equalTo<Any>(true))
69 assertThat(templateContext["enable-sone-insert-notifications"], equalTo<Any>(true))
70 assertThat(templateContext["load-linked-images"], equalTo<Any>("FOLLOWED"))
71 assertThat(templateContext["show-custom-avatars"], equalTo<Any>("FOLLOWED"))
72 assertThat(templateContext["insertion-delay"], equalTo<Any>(1))
73 assertThat(templateContext["characters-per-post"], equalTo<Any>(50))
74 assertThat(templateContext["fcp-full-access-required"], equalTo<Any>(1))
75 assertThat(templateContext["images-per-page"], equalTo<Any>(4))
76 assertThat(templateContext["fcp-interface-active"], equalTo<Any>(true))
77 assertThat(templateContext["require-full-access"], equalTo<Any>(true))
78 assertThat(templateContext["post-cut-off-length"], equalTo<Any>(51))
79 assertThat(templateContext["posts-per-page"], equalTo<Any>(10))
80 assertThat(templateContext["strict-filtering"], equalTo<Any>(true))
85 fun `get request without sone does not store sone-specific preferences in the template context`() {
88 assertThat(templateContext["auto-follow"], nullValue())
89 assertThat(templateContext["show-notification-new-sones"], nullValue())
90 assertThat(templateContext["show-notification-new-posts"], nullValue())
91 assertThat(templateContext["show-notification-new-replies"], nullValue())
92 assertThat(templateContext["enable-sone-insert-notifications"], nullValue())
93 assertThat(templateContext["load-linked-images"], nullValue())
94 assertThat(templateContext["show-custom-avatars"], nullValue())
98 private fun <T> verifyThatOptionCanBeSet(option: String, setValue: Any?, expectedValue: T, getter: () -> T) {
100 addHttpRequestPart("show-custom-avatars", "ALWAYS")
101 addHttpRequestPart("load-linked-images", "ALWAYS")
102 setValue?.also { addHttpRequestPart(option, it.toString()) }
103 verifyRedirect("options.html") {
104 assertThat(getter(), equalTo(expectedValue))
109 fun `auto-follow option can be set`() {
110 verifyThatOptionCanBeSet("auto-follow", "checked", true) { currentSone.options.isAutoFollow }
114 fun `auto-follow option can be unset`() {
115 verifyThatOptionCanBeSet("auto-follow", null, false) { currentSone.options.isAutoFollow }
119 fun `show new sone notification option can be set`() {
120 verifyThatOptionCanBeSet("show-notification-new-sones", "checked", true) { currentSone.options.isShowNewSoneNotifications }
124 fun `show new sone notification option can be unset`() {
125 verifyThatOptionCanBeSet("" +
126 "", null, false) { currentSone.options.isShowNewSoneNotifications }
130 fun `show new post notification option can be set`() {
131 verifyThatOptionCanBeSet("show-notification-new-posts", "checked", true) { currentSone.options.isShowNewPostNotifications }
135 fun `show new post notification option can be unset`() {
136 verifyThatOptionCanBeSet("show-notification-new-posts", null, false) { currentSone.options.isShowNewPostNotifications }
140 fun `show new reply notification option can be set`() {
141 verifyThatOptionCanBeSet("show-notification-new-replies", "checked", true) { currentSone.options.isShowNewReplyNotifications }
145 fun `show new reply notification option can be unset`() {
146 verifyThatOptionCanBeSet("show-notification-new-replies", null, false) { currentSone.options.isShowNewReplyNotifications }
150 fun `enable sone insert notifications option can be set`() {
151 verifyThatOptionCanBeSet("enable-sone-insert-notifications", "checked", true) { currentSone.options.isSoneInsertNotificationEnabled }
155 fun `enable sone insert notifications option can be unset`() {
156 verifyThatOptionCanBeSet("enable-sone-insert-notifications", null, false) { currentSone.options.isSoneInsertNotificationEnabled }
160 fun `load linked images option can be set`() {
161 verifyThatOptionCanBeSet("load-linked-images", "TRUSTED", TRUSTED) { currentSone.options.loadLinkedImages }
165 fun `show custom avatar option can be set`() {
166 verifyThatOptionCanBeSet("show-custom-avatars", "TRUSTED", TRUSTED) { currentSone.options.showCustomAvatars }
169 private fun verifyThatWrongValueForPreferenceIsDetected(name: String, value: String) {
172 addHttpRequestPart(name, value)
174 assertThat(templateContext["fieldErrors"] as Iterable<*>, hasItem(name))
178 private fun <T> verifyThatPreferencesCanBeSet(name: String, setValue: String?, expectedValue: T, getter: () -> T) {
181 setValue?.also { addHttpRequestPart(name, it) }
182 verifyRedirect("options.html") {
183 assertThat(getter(), equalTo(expectedValue))
188 fun `insertion delay can not be set to less than 0 seconds`() {
189 verifyThatWrongValueForPreferenceIsDetected("insertion-delay", "-1")
193 fun `insertion delay can be set to 0 seconds`() {
194 verifyThatPreferencesCanBeSet("insertion-delay", "0", 0) { core.preferences.insertionDelay }
198 fun `setting insertion to an invalid value will reset it`() {
199 verifyThatPreferencesCanBeSet("insertion-delay", "foo", 60) { core.preferences.insertionDelay }
203 fun `characters per post can not be set to less than -1`() {
204 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "-2")
208 fun `characters per post can be set to -1`() {
209 verifyThatPreferencesCanBeSet("characters-per-post", "-1", -1) { core.preferences.charactersPerPost }
213 fun `characters per post can not be set to 0`() {
214 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "0")
218 fun `characters per post can not be set to 49`() {
219 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "49")
223 fun `characters per post can be set to 50`() {
224 verifyThatPreferencesCanBeSet("characters-per-post", "50", 50) { core.preferences.charactersPerPost }
228 fun `fcp full acess required option can be set to always`() {
229 verifyThatPreferencesCanBeSet("fcp-full-access-required", "2", ALWAYS) { core.preferences.fcpFullAccessRequired }
233 fun `fcp full acess required option can be set to writing`() {
234 verifyThatPreferencesCanBeSet("fcp-full-access-required", "1", WRITING) { core.preferences.fcpFullAccessRequired }
238 fun `fcp full acess required option can be set to no`() {
239 verifyThatPreferencesCanBeSet("fcp-full-access-required", "0", NO) { core.preferences.fcpFullAccessRequired }
243 fun `fcp full acess required option is not changed if invalid value is set`() {
244 verifyThatPreferencesCanBeSet("fcp-full-access-required", "foo", WRITING) { core.preferences.fcpFullAccessRequired }
248 fun `images per page can not be set to 0`() {
249 verifyThatWrongValueForPreferenceIsDetected("images-per-page", "0")
253 fun `images per page can be set to 1`() {
254 verifyThatPreferencesCanBeSet("images-per-page", "1", 1) { core.preferences.imagesPerPage }
258 fun `images per page is set to 9 if invalid value is requested`() {
259 verifyThatPreferencesCanBeSet("images-per-page", "foo", 9) { core.preferences.imagesPerPage }
263 fun `fcp interface can be set to true`() {
264 verifyThatPreferencesCanBeSet("fcp-interface-active", "checked", true) { core.preferences.fcpInterfaceActive }
268 fun `fcp interface can be set to false`() {
269 verifyThatPreferencesCanBeSet("fcp-interface-active", null, false) { core.preferences.fcpInterfaceActive }
273 fun `require full access can be set to true`() {
274 verifyThatPreferencesCanBeSet("require-full-access", "checked", true) { core.preferences.requireFullAccess }
278 fun `require full access can be set to false`() {
279 verifyThatPreferencesCanBeSet("require-full-access", null, false) { core.preferences.requireFullAccess }
283 fun `post cut off length can not be set to -49`() {
284 verifyThatWrongValueForPreferenceIsDetected("post-cut-off-length", "-49")
288 fun `post cut off length can be set to 50`() {
289 verifyThatPreferencesCanBeSet("post-cut-off-length", "50", 50) { core.preferences.postCutOffLength }
293 fun `post cut off length is set to default on invalid value`() {
294 verifyThatPreferencesCanBeSet("post-cut-off-length", "invalid", 200) { core.preferences.postCutOffLength }
298 fun `posts per page can not be set to 0`() {
299 verifyThatWrongValueForPreferenceIsDetected("posts-per-page", "-49")
303 fun `posts per page can be set to 1`() {
304 verifyThatPreferencesCanBeSet("posts-per-page", "1", 1) { core.preferences.postsPerPage }
308 fun `posts per page is set to default on invalid value`() {
309 verifyThatPreferencesCanBeSet("posts-per-page", "invalid", 10) { core.preferences.postsPerPage }
313 fun `strict filtering can be set to true`() {
314 verifyThatPreferencesCanBeSet("strict-filtering", "checked", true) { core.preferences.strictFiltering }
318 fun `strict filtering can be set to false`() {
319 verifyThatPreferencesCanBeSet("strict-filtering", null, false) { core.preferences.strictFiltering }
323 fun `page can be created by dependency injection`() {
324 assertThat(baseInjector.getInstance<OptionsPage>(), notNullValue())
328 fun `page is annotated with correct menuname`() {
329 assertThat(page.menuName, equalTo("Options"))
333 fun `page is annotated with correct template path`() {
334 assertThat(page.templatePath, equalTo("/templates/options.html"))