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
33 fun setupSoneOptions() {
34 whenever(currentSone.options).thenReturn(DefaultSoneOptions().apply {
36 isShowNewPostNotifications = true
37 isShowNewReplyNotifications = true
38 isShowNewSoneNotifications = true
39 isSoneInsertNotificationEnabled = true
40 loadLinkedImages = FOLLOWED
41 showCustomAvatars = FOLLOWED
46 fun `page returns correct path`() {
47 assertThat(page.path, equalTo("options.html"))
51 fun `page does not require login`() {
52 assertThat(page.requiresLogin(), equalTo(false))
56 fun `page returns correct title`() {
57 addTranslation("Page.Options.Title", "options page title")
58 assertThat(page.getPageTitle(soneRequest), equalTo("options page title"))
62 fun `get request stores all preferences in the template context`() {
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))
83 fun `get request without sone does not store sone-specific preferences in the template context`() {
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())
96 private fun <T> verifyThatOptionCanBeSet(option: String, setValue: Any?, expectedValue: T, getter: () -> T) {
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))
107 fun `auto-follow option can be set`() {
108 verifyThatOptionCanBeSet("auto-follow", "checked", true) { currentSone.options.isAutoFollow }
112 fun `auto-follow option can be unset`() {
113 verifyThatOptionCanBeSet("auto-follow", null, false) { currentSone.options.isAutoFollow }
117 fun `show new sone notification option can be set`() {
118 verifyThatOptionCanBeSet("show-notification-new-sones", "checked", true) { currentSone.options.isShowNewSoneNotifications }
122 fun `show new sone notification option can be unset`() {
123 verifyThatOptionCanBeSet("" +
124 "", null, false) { currentSone.options.isShowNewSoneNotifications }
128 fun `show new post notification option can be set`() {
129 verifyThatOptionCanBeSet("show-notification-new-posts", "checked", true) { currentSone.options.isShowNewPostNotifications }
133 fun `show new post notification option can be unset`() {
134 verifyThatOptionCanBeSet("show-notification-new-posts", null, false) { currentSone.options.isShowNewPostNotifications }
138 fun `show new reply notification option can be set`() {
139 verifyThatOptionCanBeSet("show-notification-new-replies", "checked", true) { currentSone.options.isShowNewReplyNotifications }
143 fun `show new reply notification option can be unset`() {
144 verifyThatOptionCanBeSet("show-notification-new-replies", null, false) { currentSone.options.isShowNewReplyNotifications }
148 fun `enable sone insert notifications option can be set`() {
149 verifyThatOptionCanBeSet("enable-sone-insert-notifications", "checked", true) { currentSone.options.isSoneInsertNotificationEnabled }
153 fun `enable sone insert notifications option can be unset`() {
154 verifyThatOptionCanBeSet("enable-sone-insert-notifications", null, false) { currentSone.options.isSoneInsertNotificationEnabled }
158 fun `load linked images option can be set`() {
159 verifyThatOptionCanBeSet("load-linked-images", "TRUSTED", TRUSTED) { currentSone.options.loadLinkedImages }
163 fun `show custom avatar option can be set`() {
164 verifyThatOptionCanBeSet("show-custom-avatars", "TRUSTED", TRUSTED) { currentSone.options.showCustomAvatars }
167 private fun verifyThatWrongValueForPreferenceIsDetected(name: String, value: String) {
170 addHttpRequestPart(name, value)
172 assertThat(templateContext["fieldErrors"] as Iterable<*>, hasItem(name))
176 private fun <T> verifyThatPreferencesCanBeSet(name: String, setValue: String?, expectedValue: T, getter: () -> T) {
179 setValue?.also { addHttpRequestPart(name, it) }
180 verifyRedirect("options.html") {
181 assertThat(getter(), equalTo(expectedValue))
186 fun `insertion delay can not be set to less than 0 seconds`() {
187 verifyThatWrongValueForPreferenceIsDetected("insertion-delay", "-1")
191 fun `insertion delay can be set to 0 seconds`() {
192 verifyThatPreferencesCanBeSet("insertion-delay", "0", 0) { core.preferences.insertionDelay }
196 fun `setting insertion to an invalid value will reset it`() {
197 verifyThatPreferencesCanBeSet("insertion-delay", "foo", 60) { core.preferences.insertionDelay }
201 fun `characters per post can not be set to less than -1`() {
202 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "-2")
206 fun `characters per post can be set to -1`() {
207 verifyThatPreferencesCanBeSet("characters-per-post", "-1", -1) { core.preferences.charactersPerPost }
211 fun `characters per post can not be set to 0`() {
212 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "0")
216 fun `characters per post can not be set to 49`() {
217 verifyThatWrongValueForPreferenceIsDetected("characters-per-post", "49")
221 fun `characters per post can be set to 50`() {
222 verifyThatPreferencesCanBeSet("characters-per-post", "50", 50) { core.preferences.charactersPerPost }
226 fun `fcp full acess required option can be set to always`() {
227 verifyThatPreferencesCanBeSet("fcp-full-access-required", "2", ALWAYS) { core.preferences.fcpFullAccessRequired }
231 fun `fcp full acess required option can be set to writing`() {
232 verifyThatPreferencesCanBeSet("fcp-full-access-required", "1", WRITING) { core.preferences.fcpFullAccessRequired }
236 fun `fcp full acess required option can be set to no`() {
237 verifyThatPreferencesCanBeSet("fcp-full-access-required", "0", NO) { core.preferences.fcpFullAccessRequired }
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 }
246 fun `images per page can not be set to 0`() {
247 verifyThatWrongValueForPreferenceIsDetected("images-per-page", "0")
251 fun `images per page can be set to 1`() {
252 verifyThatPreferencesCanBeSet("images-per-page", "1", 1) { core.preferences.imagesPerPage }
256 fun `images per page is set to 9 if invalid value is requested`() {
257 verifyThatPreferencesCanBeSet("images-per-page", "foo", 9) { core.preferences.imagesPerPage }
261 fun `fcp interface can be set to true`() {
262 verifyThatPreferencesCanBeSet("fcp-interface-active", "checked", true) { core.preferences.fcpInterfaceActive }
266 fun `fcp interface can be set to false`() {
267 verifyThatPreferencesCanBeSet("fcp-interface-active", null, false) { core.preferences.fcpInterfaceActive }
271 fun `require full access can be set to true`() {
272 verifyThatPreferencesCanBeSet("require-full-access", "checked", true) { core.preferences.requireFullAccess }
276 fun `require full access can be set to false`() {
277 verifyThatPreferencesCanBeSet("require-full-access", null, false) { core.preferences.requireFullAccess }
281 fun `post cut off length can not be set to -49`() {
282 verifyThatWrongValueForPreferenceIsDetected("post-cut-off-length", "-49")
286 fun `post cut off length can be set to 50`() {
287 verifyThatPreferencesCanBeSet("post-cut-off-length", "50", 50) { core.preferences.postCutOffLength }
291 fun `post cut off length is set to default on invalid value`() {
292 verifyThatPreferencesCanBeSet("post-cut-off-length", "invalid", 200) { core.preferences.postCutOffLength }
296 fun `posts per page can not be set to 0`() {
297 verifyThatWrongValueForPreferenceIsDetected("posts-per-page", "-49")
301 fun `posts per page can be set to 1`() {
302 verifyThatPreferencesCanBeSet("posts-per-page", "1", 1) { core.preferences.postsPerPage }
306 fun `posts per page is set to default on invalid value`() {
307 verifyThatPreferencesCanBeSet("posts-per-page", "invalid", 10) { core.preferences.postsPerPage }
311 fun `page can be created by dependency injection`() {
312 assertThat(baseInjector.getInstance<OptionsPage>(), notNullValue())
316 fun `page is annotated with correct menuname`() {
317 assertThat(page.menuName, equalTo("Options"))
321 fun `page is annotated with correct template path`() {
322 assertThat(page.templatePath, equalTo("/templates/options.html"))